Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a GitHub workflow for finalizing a release #6998

Merged
merged 1 commit into from
Oct 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Add a GitHub workflow for finalizing a release
This automates the second half of the release process (the first being
automated by `prepare-release.yml`). After this workflow completes, the only
action that should remain for the releaser to do is to merge the
`dev-release-*` pull request. We can't do that as part of this workflow,
because CI has to finish first, and it seems pointless to create another
workflow just to merge 1 PR.

Apply some of the aspects of this pipeline to `prepare-release.yml` as well:

* Make the release notes extraction process more sophisticated to work
  around GitHub's frustrating handling of line breaks in PR and release
  descriptions.

* Use GitHub app credentials in order to be able to trigger other pipelines.
  • Loading branch information
SpecLad committed Oct 13, 2023
commit 55f23cc5c66edbc4e1ddde1b8c291439b45168da
109 changes: 109 additions & 0 deletions .github/workflows/finalize-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
name: Finalize release
on:
workflow_dispatch:
jobs:
main:
runs-on: ubuntu-latest
steps:
- name: Discover pending release
id: discover
env:
GH_TOKEN: "${{ github.token }}"
run: |
gh --repo="${{ github.repository }}" \
pr list --base master --state open --json number,headRefName \
--jq 'map(select(.headRefName | startswith("release-")))' \
> /tmp/release-prs.json

if jq -e 'length < 1' /tmp/release-prs.json > /dev/null; then
echo "No open release pull requests found."
exit 1
elif jq -e 'length > 1' /tmp/release-prs.json > /dev/null; then
echo "Multiple open release pull requests found:"
jq -r '.[] | "https://github.com/${{ github.repository }}/pull/\(.number)"' /tmp/release-prs.json
exit 1
fi

jq -r '.[] | "prNumber=\(.number)", "version=\(.headRefName | ltrimstr("release-"))"' \
/tmp/release-prs.json >> "$GITHUB_OUTPUT"

# When you use the default github.token to make changes in the repository,
# it does not trigger further GitHub pipelines. We want to trigger CI for
# the pull request and artifact building for the release, so we have to use
# an app token.
- name: Generate authentication token
id: gen-token
uses: actions/create-github-app-token@v1
with:
app-id: "${{ secrets.CVAT_BOT_APP_ID }}"
private-key: "${{ secrets.CVAT_BOT_PRIVATE_KEY }}"

- name: Install dependencies
run:
sudo apt-get install -y pandoc

- uses: actions/checkout@v4
with:
ref: "release-${{ steps.discover.outputs.version }}"

- name: Verify that the release is new
env:
NEW_VERSION: "${{ steps.discover.outputs.version }}"
run: |
if git ls-remote --exit-code origin "refs/tags/v$NEW_VERSION" > /dev/null; then
echo "Release v$NEW_VERSION already exists"
exit 1
fi

# Do post-release tasks before publishing the release. If anything goes wrong,
# the dev-release-* branch can be deleted, and the whole process restarted again;
# whereas we can't unmerge the release PR.

- name: Create post-release branch
run:
git checkout -b "dev-release-${{ steps.discover.outputs.version }}"

- name: Bump version
run:
./dev/update_version.py --minor

- name: Commit post-release changes
run: |
git -c user.name='cvat-bot[bot]' -c user.email='147643061+cvat-bot[bot]@users.noreply.github.com' \
commit -a -m "Update ${{ github.ref_name }} after v${{ steps.discover.outputs.version }}"

- name: Push post-release branch
run:
git push -u origin "dev-release-${{ steps.discover.outputs.version }}"

- name: Create post-release pull request
env:
GH_TOKEN: "${{ steps.gen-token.outputs.token }}"
run: |
gh pr create \
--base="${{ github.ref_name }}" \
--title="Update ${{ github.ref_name }} after v${{ steps.discover.outputs.version }}" \
--body=""

# Now publish the release.

- name: Merge release pull request
env:
GH_TOKEN: "${{ steps.gen-token.outputs.token }}"
run:
gh pr merge --merge "${{ steps.discover.outputs.prNumber }}" --delete-branch

- name: Create release
env:
GH_TOKEN: "${{ steps.gen-token.outputs.token }}"
NEW_VERSION: "${{ steps.discover.outputs.version }}"
run: |
# We could grab the release notes from the PR description, but it could
# be outdated if any changes were made on the release branch. So instead,
# just re-extract them from the changelog again.

./dev/gh_release_notes.sh \
| gh release create "v$NEW_VERSION" \
--target=master \
--title="v$NEW_VERSION" \
--notes-file=-
27 changes: 21 additions & 6 deletions .github/workflows/prepare-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,20 @@ jobs:
exit 1
fi

# When you use the default github.token to make changes in the repository,
# it does not trigger further GitHub pipelines. We want to trigger CI for
# the pull request, so we have to use an app token.
- name: Generate authentication token
id: gen-token
uses: actions/create-github-app-token@v1
with:
app-id: "${{ secrets.CVAT_BOT_APP_ID }}"
private-key: "${{ secrets.CVAT_BOT_PRIVATE_KEY }}"

- name: Install dependencies
run:
sudo apt-get install -y pandoc

- uses: actions/checkout@v4

- name: Verify that the release is new
Expand All @@ -42,7 +56,7 @@ jobs:

- name: Commit release preparation changes
run: |
git -c user.name='github-actions[bot]' -c user.email='github-actions[bot]@users.noreply.github.com' \
git -c user.name='cvat-bot[bot]' -c user.email='147643061+cvat-bot[bot]@users.noreply.github.com' \
azhavoro marked this conversation as resolved.
Show resolved Hide resolved
commit -a -m "Prepare release v${{ inputs.newVersion }}"

- name: Push release branch
Expand All @@ -51,9 +65,10 @@ jobs:

- name: Create release pull request
env:
GH_TOKEN: "${{ github.token }}"
GH_TOKEN: "${{ steps.gen-token.outputs.token }}"
run: |
gh pr create \
--base=master \
--title="Release v${{ inputs.newVersion }}" \
--body="$(awk '/^## / { hn += 1; next } hn == 1 && !/^</' CHANGELOG.md)"
./dev/gh_release_notes.sh \
| gh pr create \
--base=master \
--title="Release v${{ inputs.newVersion }}" \
--body-file=-
14 changes: 14 additions & 0 deletions dev/gh_release_notes.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/bin/sh

# This script takes the release notes for the most recent release
# and reformats them for use in GitHub.

# In GitHub PR and release descriptions, a single line break is
# equivalent to <br>, so we pipe the text through pandoc to unwrap all lines.

set -eu

repo_root="$(dirname "$0")/.."

awk '/^## / { hn += 1; next } hn == 1 && !/^</' "$repo_root/CHANGELOG.md" \
| pandoc -f gfm -t gfm --wrap=none
Loading