From ee39c1490d176ff154c38a85dbfd186245ae8191 Mon Sep 17 00:00:00 2001 From: Cecile Robert-Michon Date: Mon, 11 Dec 2023 22:22:22 +0000 Subject: [PATCH] Add automation to create release branch and tags --- .github/workflows/release.yaml | 113 ++++++++++++++++++++++---- .gitignore | 3 - CHANGELOG/README.md | 5 ++ Makefile | 2 +- docs/book/src/developers/releasing.md | 47 ++++++----- 5 files changed, 124 insertions(+), 46 deletions(-) create mode 100644 CHANGELOG/README.md diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 395ef72c1ca..3f5e8308c26 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -1,42 +1,119 @@ +name: Create Release + on: push: - # Sequence of patterns matched against refs/tags - tags: - - 'v*' # Push events to matching v*, i.e. v1.0, v20.15.10 + branches: + - main + paths: + - 'CHANGELOG/*.md' -name: release +permissions: + contents: write # Allow to push a tag, create a release branch and publish a draft release. jobs: - build: - name: tag release + push_release_tag: runs-on: ubuntu-latest + outputs: + release_tag: ${{ steps.release-version.outputs.release_version }} + steps: + - name: Harden Runner + uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 + with: + egress-policy: audit + - name: Checkout code + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1 + with: + fetch-depth: 0 + - name: Get changed files + id: changed-files + uses: tj-actions/changed-files@1c938490c880156b746568a518594309cfb3f66b # tag=v40.2.1 + - name: Get release version + id: release-version + run: | + if [[ ${{ steps.changed-files.outputs.all_changed_files_count }} != 1 ]]; then + echo "1 release notes file should be changed to create a release tag, found ${{ steps.changed-files.outputs.all_changed_files_count }}" + exit 1 + fi + for changed_file in ${{ steps.changed-files.outputs.all_changed_files }}; do + export RELEASE_VERSION=$(echo "${changed_file}" | grep -oP '(?<=/)[^/]+(?=\.md)') + echo "RELEASE_VERSION=$RELEASE_VERSION" >> $GITHUB_ENV + echo "RELEASE_VERSION=$RELEASE_VERSION" >> $GITHUB_OUTPUT + if [[ "$RELEASE_VERSION" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$ ]]; then + echo "Valid semver: $RELEASE_VERSION" + else + echo "Invalid semver: $RELEASE_VERSION" + exit 1 + fi + done + - name: Determine the release branch to use + run: | + if [[ $RELEASE_VERSION =~ beta ]] || [[ $RELEASE_VERSION =~ alpha ]]; then + export RELEASE_BRANCH=main + echo "RELEASE_BRANCH=$RELEASE_BRANCH" >> $GITHUB_ENV + echo "This is a beta or alpha release, will use release branch $RELEASE_BRANCH" + else + export RELEASE_BRANCH=release-$(echo $RELEASE_VERSION | sed -E 's/^v([0-9]+)\.([0-9]+)\..*$/\1.\2/') + echo "RELEASE_BRANCH=$RELEASE_BRANCH" >> $GITHUB_ENV + echo "This is not a beta or alpha release, will use release branch $RELEASE_BRANCH" + fi + - name: Create or checkout release branch + run: | + if git show-ref --verify --quiet "refs/remotes/origin/$RELEASE_BRANCH"; then + echo "Branch $RELEASE_BRANCH already exists" + git checkout "$RELEASE_BRANCH" + else + git checkout -b "$RELEASE_BRANCH" + git push origin "$RELEASE_BRANCH" + echo "Created branch $RELEASE_BRANCH" + fi + - name: Validate tag does not already exist + run: | + if [[ $(git tag -l $RELEASE_VERSION) ]]; then + echo "Tag $RELEASE_VERSION already exists, exiting" + exit 1 + fi + - name: Create Release Tag + run: | + git config user.name "${GITHUB_ACTOR}" + git config user.email "${GITHUB_ACTOR}@users.noreply.github.com" + git tag -a ${RELEASE_VERSION} -m ${RELEASE_VERSION} + git push origin ${RELEASE_VERSION} + echo "Created tag $RELEASE_VERSION" + release: + name: create draft release + runs-on: ubuntu-latest + needs: push_release_tag steps: - name: Harden Runner uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 with: egress-policy: audit - - name: Set env - run: echo "RELEASE_TAG=${GITHUB_REF:10}" >> $GITHUB_ENV + run: echo "RELEASE_TAG=${RELEASE_TAG}" >> $GITHUB_ENV + env: + RELEASE_TAG: ${{needs.push_release_tag.outputs.release_tag}} - name: checkout code - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # tag=v4.1.1 with: fetch-depth: 0 - - name: Install go - uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 + ref: ${{ env.RELEASE_TAG }} + - name: Calculate go version + run: echo "go_version=$(make go-version)" >> $GITHUB_ENV + - name: Set up Go + uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # tag=v4.1.0 with: - go-version: '^1.20' + go-version: ${{ env.go_version }} - name: generate release artifacts run: | make release - - name: generate release notes + - name: get release notes run: | - make release-notes - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + curl -L "https://raw.githubusercontent.com/${{ github.repository }}/main/CHANGELOG/${{ env.RELEASE_TAG }}.md" \ + -o "${{ env.RELEASE_TAG }}.md" - name: Release - uses: softprops/action-gh-release@de2c0eb89ae2a093876385947365aca7b0e5f844 # v1 + uses: softprops/action-gh-release@de2c0eb89ae2a093876385947365aca7b0e5f844 # tag=v1 with: draft: true files: out/* - body_path: _releasenotes/release-notes-${{ env.RELEASE_TAG }}.md + body_path: ${{ env.RELEASE_TAG }}.md + tag_name: ${{ env.RELEASE_TAG }} \ No newline at end of file diff --git a/.gitignore b/.gitignore index 3a899f1c3f2..849681a887e 100644 --- a/.gitignore +++ b/.gitignore @@ -79,9 +79,6 @@ hack/boilerplate/*.pyc # Helm chart caching .helm/ -# release notes -_releasenotes - # calico manifests archive release-*/manifests/calico-*.yaml diff --git a/CHANGELOG/README.md b/CHANGELOG/README.md new file mode 100644 index 00000000000..abdd2959103 --- /dev/null +++ b/CHANGELOG/README.md @@ -0,0 +1,5 @@ +# CHANGELOG + +This folder contains release notes for past releases. Changes to this folder in the main branch trigger a GitHub Action that creates release tags and a draft release. + +See [release documentation](https://capz.sigs.k8s.io/developers/releasing) for more information. diff --git a/Makefile b/Makefile index 523782a44b5..03fb6316a55 100644 --- a/Makefile +++ b/Makefile @@ -585,7 +585,7 @@ endif # the previous release tag, e.g., v0.3.9, excluding pre-release tags PREVIOUS_TAG ?= $(shell git tag -l | grep -E "^v[0-9]+\.[0-9]+\.[0-9]+$$" | sort -V | grep -B1 $(RELEASE_TAG) | head -n 1 2>/dev/null) RELEASE_DIR ?= out -RELEASE_NOTES_DIR := _releasenotes +RELEASE_NOTES_DIR := CHANGELOG GIT_REPO_NAME ?= cluster-api-provider-azure GIT_ORG_NAME ?= kubernetes-sigs FULL_VERSION := $(RELEASE_TAG:v%=%) diff --git a/docs/book/src/developers/releasing.md b/docs/book/src/developers/releasing.md index 87ab543fd0e..9e19b41dd68 100644 --- a/docs/book/src/developers/releasing.md +++ b/docs/book/src/developers/releasing.md @@ -37,6 +37,8 @@ Sometimes pull requests touch a large number of files and are more likely to cre - Make sure the [metadata.yaml](https://github.com/kubernetes-sigs/cluster-api-provider-azure/blob/main/metadata.yaml) file is up to date and contains the new release with the correct cluster-api contract version. - If not, open a [PR](https://github.com/kubernetes-sigs/cluster-api-provider-azure/pull/1928) to add it. +This must be done prior to generating release artifacts, so the release contains the correct metadata information for clusterctl to use. + ### Change milestone (skip for patch releases) - Create a new GitHub milestone for the next release @@ -63,35 +65,30 @@ releaseSeries: Additionally, we need to update the `type: InfrastructureProvider` spec in [azure-dev.yaml](https://github.com/kubernetes-sigs/cluster-api-provider-azure/blob/main/test/e2e/config/azure-dev.yaml) to express that our intent is to test (using the above example) `1.5`. By convention we use a sentinel patch version "99" to express "any patch version". In this example we want to look for the `type: InfrastructureProvider` with a `name` value of `v1.4.99` and update it to `v1.5.99`: -``` +```yaml - name: v1.5.99 # "vNext"; use manifests from local source files ``` -### Create a tag +This can be done in parallel with release publishing and does not impact the release or its artifacts. -Before you create a GPG-signed tag you may need to prepare your local environment's TTY to properly hoist your signed key into the flow of the `git tag` command: +### Open a PR for release notes -```sh -$ export GPG_TTY=$(tty) -``` +1. Checkout the latest commit on the release branch, e.g. `release-1.4`, or the main branch if the release branch doesn't yet exist (e.g. beta release). + +1. Generate release notes by running the following command: -- Prepare the release branch. :warning: Always release from the release branch and not from main! - - If releasing a patch release, check out the existing release branch and make sure you have the latest changes: - - `git checkout release-1.x` - - `git fetch upstream` - - `git rebase upstream/release-1.x` - - If releasing a minor release, create a new release branch from the main branch: - - `git fetch upstream` - - `git rebase upstream/main` - - `git checkout -b release-1.x` - - `git push upstream release-1.x` -- Create tag with git - - `export RELEASE_TAG=v1.2.3` (the tag of the release to be cut) - - `git tag -s ${RELEASE_TAG} -m "${RELEASE_TAG}"` - - `-s` creates a signed tag, you must have a GPG key [added to your GitHub account](https://docs.github.com/en/authentication/managing-commit-signature-verification/adding-a-new-gpg-key-to-your-github-account) - - `git push upstream ${RELEASE_TAG}` - -This will automatically trigger a [Github Action](https://github.com/kubernetes-sigs/cluster-api-provider-azure/actions) to create a draft release. + ```sh + export RELEASE_TAG=v1.2.3 # change this to the tag of the release to be cut + make release-notes + ``` + +1. Review the release notes file generated at `CHANGELOG/.md` and make any necessary changes. + +1. Open a pull request with the release notes. + +**Note**: Important! The commit should only contain the release notes file, nothing else, otherwise automation will not work. + +Merging the PR will automatically trigger a [Github Action](https://github.com/kubernetes-sigs/cluster-api-provider-azure/actions) to create a release branch (if needed), push a tag, and publish a draft release. ### Promote image to prod repo @@ -113,9 +110,11 @@ Using [the above example PR](https://github.com/kubernetes/k8s.io/pull/4284), to - Manually format and categorize the release notes - Ensure that the promoted release image is live. For example: + ```sh -$ docker pull registry.k8s.io/cluster-api-azure/cluster-api-azure-controller:${RELEASE_TAG} +docker pull registry.k8s.io/cluster-api-azure/cluster-api-azure-controller:${RELEASE_TAG} ``` + - Publish release - [Announce][release-announcement] the release