diff --git a/.github/workflows/gem-bump-checker.yml b/.github/workflows/gem-bump-checker.yml new file mode 100644 index 000000000..152a846ee --- /dev/null +++ b/.github/workflows/gem-bump-checker.yml @@ -0,0 +1,105 @@ +name: Gem Bump Checker + +on: + workflow_call: + inputs: + gem_name: + required: false + type: string + default: ${{ github.event.repository.name }} + secrets: + GH_TOKEN: + required: true + +jobs: + check-files: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + show-progress: false + token: ${{ secrets.GH_TOKEN }} + - uses: ruby/setup-ruby@v1 + with: + rubygems: latest + bundler-cache: true + + - name: "Determine HEAD of default branch" + id: fetch_default_branch_head + run: echo "sha=$(git ls-remote origin HEAD | cut -f 1)" >> "$GITHUB_OUTPUT" + + - name: "Determine HEAD of current branch" + id: fetch_current_branch_head + run: echo "sha=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT" + + - name: Check PR author + id: check_pr_author + run: echo "pr_author=${{ github.event.pull_request.user.login }}" >> "$GITHUB_OUTPUT" + + - name: Check for version and changelog updates + if: steps.check_pr_author.outputs.pr_author != 'dependabot[bot]' + env: + GH_TOKEN: ${{ secrets.GH_TOKEN }} + BASE_REF: ${{ steps.fetch_default_branch_head.outputs.sha }} + HEAD_REF: ${{ steps.fetch_current_branch_head.outputs.sha }} + run: | + MODIFIED_FILES=$(git diff --name-only "$BASE_REF".."$HEAD_REF") + + if ! echo "$MODIFIED_FILES" | grep 'version.rb' && \ + ! echo "$MODIFIED_FILES" | grep '\.gemspec$'; then + echo "Error: Either version.rb or a .gemspec file must be modified with each pull request to bump the gem version." + exit 1 + fi + + if ! echo "$MODIFIED_FILES" | grep 'CHANGELOG.md'; then + echo "Error: CHANGELOG.md must be updated with each pull request." + exit 1 + fi + + - name: Dependabot version bump + if: steps.check_pr_author.outputs.pr_author == 'dependabot[bot]' + env: + GEM_NAME: ${{ inputs.gem_name }} + GH_TOKEN: ${{ secrets.GH_TOKEN }} + BRANCH_NAME: ${{ github.event.pull_request.head.ref }} + run: | + set -euo pipefail + + git checkout "$BRANCH_NAME" + + curr_ver=$(ruby -r rubygems -e "puts Gem::Specification::load('$GEM_NAME.gemspec').version") + major=$(echo "$curr_ver" | cut -d . -f1) + minor=$(echo "$curr_ver" | cut -d . -f2) + patch=$(echo "$curr_ver" | cut -d . -f3) + next_ver="$major.$minor.$((patch + 1))" # Increment the patch version + + if ! [[ -r CHANGELOG.md ]]; then + echo "CHANGELOG.md not found or not readable. Exiting." + exit 0 + fi + + if ! grep -qR --include "version.rb" --include "*.gemspec" "$curr_ver"; then + echo "Can't find version.rb or *.gemspec containing the string '$curr_ver'. Exiting." + exit 0 + fi + + find . -type f \( -iname "version.rb" -o -iname "*.gemspec" \) -exec sed -i "0,/$curr_ver/s//${next_ver}/" {} \; + + printf "# %s\n\n* Update dependencies\n\n" "$next_ver" > NEW_CHANGELOG.md + cat CHANGELOG.md >> NEW_CHANGELOG.md + mv NEW_CHANGELOG.md CHANGELOG.md + + git config --global user.name "GOV.UK Continuous Integration User" + git config --global user.email "govuk-ci@users.noreply.github.com" + + git add CHANGELOG.md + + find . \( -path ./vendor/bundle -prune \) -o \( -type f \( -iname version.rb -o -iname "*.gemspec" \) -print \) | while read -r file; do + file_path=${file#./} + git add "$file_path" + done + + git commit -m "Automated version bump to v$next_ver" + git push origin "$BRANCH_NAME"