From c3bef00b2b8c023d64471607213204d8eb82573d Mon Sep 17 00:00:00 2001 From: Alex Abashev Date: Sun, 1 Nov 2026 18:25:16 +0300 Subject: [PATCH] Follow releases into the README from CI The README's examples name the plugin's own version and the open-java-format version to add, and both were changed by hand: the formatter one still says 2.98.0.4, two releases behind. The "Follow releases" workflow now compares each with the latest GitHub release of openjavaformat/ once an hour, as the docs and the action repositories do for the formatter. main takes no direct pushes here, so instead of committing it changes the README on the branch follow-releases/ and opens a pull request for it, approved with the workflow's token and set to auto-merge, the way Dependabot's pull requests land. BOT_PAT pushes the branch, opens the pull request and turns on auto-merge, because a push or a pull request made with GITHUB_TOKEN starts no workflow runs, so build would never run on it. mise.toml now names this workflow among the token's consumers. --- .github/workflows/follow-releases.yml | 91 +++++++++++++++++++++++++++ mise.toml | 8 +-- 2 files changed, 95 insertions(+), 4 deletions(-) create mode 100644 .github/workflows/follow-releases.yml diff --git a/.github/workflows/follow-releases.yml b/.github/workflows/follow-releases.yml new file mode 100644 index 0000000..e509320 --- /dev/null +++ b/.github/workflows/follow-releases.yml @@ -0,0 +1,91 @@ +name: Follow releases + +# The README's examples name the latest release of open-java-format and of the plugin itself. Once +# an hour this compares each with the latest GitHub release of openjavaformat/. When a new +# release is out, the README is changed on the branch follow-releases/, and a pull request +# for it is opened, approved and set to merge once build passes, the way Dependabot's are: main +# takes no direct pushes. +# +# BOT_PAT pushes the branch, opens the pull request and turns on auto-merge: a push or a pull request +# made with the workflow's own token starts no workflow runs, so build would never run on the pull +# request, nor anything on main after the merge. The workflow's own token approves, because BOT_PAT's +# account opened the pull request and cannot approve it. + +on: + schedule: + - cron: '17 * * * *' # not on the hour, when GitHub's schedule queue is longest + workflow_dispatch: + +permissions: {} + +jobs: + bump: + name: Bump ${{ matrix.artifact }} + runs-on: ubuntu-latest + permissions: + contents: read # check out the README + pull-requests: write # approve the pull request + strategy: + fail-fast: false + matrix: + artifact: [open-java-format, fmt-maven-plugin] + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + + - name: Open a pull request when a new release is out + shell: bash + env: + ARTIFACT: ${{ matrix.artifact }} + GH_TOKEN: ${{ github.token }} + BOT_PAT: ${{ secrets.BOT_PAT }} + run: | + # Every example names the version on the line after $ARTIFACT. + current=$(sed -n "/$ARTIFACT<\/artifactId>/{n;s/.*\(.*\)<\/version>.*/\1/p;q}" README.md) + release=$(gh release view --repo "openjavaformat/$ARTIFACT" --json tagName,publishedAt) + latest=$(jq -r .tagName <<< "$release") + published=$(jq -r '.publishedAt[:10]' <<< "$release") + # The latest release is the one published last, and a fix for an older line can come out + # after a newer line started: only a higher version number is a bump. + newer=$(printf '%s\n' "$current" "$latest" | sort -V | tail -n 1) + if [ "$latest" = "$current" ] || [ "$newer" != "$latest" ]; then + echo "Already on $current; the latest release is $latest." + exit 0 + fi + + sed -i "/$ARTIFACT<\/artifactId>/{n;s/.*<\/version>/$latest<\/version>/}" README.md + + # The branch lives as long as its pull request is open, and on after the pull request is + # closed unmerged. Either way, a branch with this README needs nothing more. + branch=follow-releases/$ARTIFACT + if git fetch --quiet --depth 1 origin "refs/heads/$branch" 2> /dev/null && + git diff --quiet FETCH_HEAD -- README.md; then + echo "$branch names $latest already." + exit 0 + fi + git diff + + git config user.name 'github-actions[bot]' + git config user.email '41898282+github-actions[bot]@users.noreply.github.com' + git commit --all --quiet --file - < /dev/null + else + url=$(GH_TOKEN=$BOT_PAT gh pr create --head "$branch" --title "$title" --body "$body") + gh pr review --approve "$url" + GH_TOKEN=$BOT_PAT gh pr merge --auto --squash "$url" + fi diff --git a/mise.toml b/mise.toml index 6b4fd04..17ec459 100644 --- a/mise.toml +++ b/mise.toml @@ -15,10 +15,10 @@ env = { NO_COLOR = "1" } # suppress gh's OSC-11 terminal-background probe run = """ set -euo pipefail -# BOT_PAT is consumed by update-pr-branch.yml and by the auto-merge step of -# dependabot-automerge.yml, and it cannot be GITHUB_TOKEN: a push made with GITHUB_TOKEN starts no -# workflow runs, so a branch would be brought up to date — or a pull request merged — and then -# never re-checked. +# BOT_PAT is consumed by update-pr-branch.yml, by the auto-merge step of dependabot-automerge.yml +# and by follow-releases.yml, and it cannot be GITHUB_TOKEN: a push made with GITHUB_TOKEN starts no +# workflow runs, so a branch would be brought up to date — or a pull request opened or merged — and +# then never re-checked. # # The token needs these repository permissions: # Pull requests Write PUT /repos/{owner}/{repo}/pulls/{n}/update-branch requires it