From 80489cb54a3b7401c6d972ed4200ad440b0d6531 Mon Sep 17 00:00:00 2001 From: Michael Gasch Date: Wed, 15 Jun 2022 16:26:37 +0200 Subject: [PATCH] chore: Update release automation Closes: #2875 Signed-off-by: Michael Gasch --- .github/workflows/govmomi-release.yaml | 104 ++++++++++++-- RELEASE.md | 182 ++++++++++++++++++++++--- 2 files changed, 257 insertions(+), 29 deletions(-) diff --git a/.github/workflows/govmomi-release.yaml b/.github/workflows/govmomi-release.yaml index e81c7b50a..fef5407da 100644 --- a/.github/workflows/govmomi-release.yaml +++ b/.github/workflows/govmomi-release.yaml @@ -15,15 +15,26 @@ name: Release on: - push: - tags: - - "v*" # Push events to matching v*, i.e. v0.25.0, v1.15.1 + workflow_dispatch: + inputs: + tag: + description: 'Create release using this non-existing semantic tag for the specified ref' + required: true + type: string + default: 'v0.99.0' + dryrun: + description: 'Verify release workflow without pushing any changes (catches most but not all errors)' + type: boolean + required: false + default: true jobs: release: name: Create Release runs-on: ubuntu-20.04 timeout-minutes: 60 + outputs: + latesttag: ${{ steps.tag.outputs.islatest }} steps: - name: Docker Login @@ -33,12 +44,74 @@ jobs: uses: actions/checkout@v3 with: fetch-depth: 0 # for CHANGELOG + ref: ${{ github.ref }} # branch provided on dispatch + + - name: Validate branch and tag + run: | + # do not allow release on master branch + if [[ ${{ github.ref }} == refs/heads/master ]]; then + echo "::error:: release must be done on a release branch" + exit 1 + fi + + # check it starts with "v" + if [[ ${{ inputs.tag }} != v* ]]; then + echo "::error:: tag must have a \"v\" prefix" + exit 1 + fi + + # check it does not exist + if [[ $(git tag -l ${{ inputs.tag }} ) ]]; then + echo "::error:: tag already exists" + exit 1 + fi + + # set tag environment variable + echo "TAG=${{ inputs.tag }}" >> $GITHUB_ENV - name: Set up Go uses: actions/setup-go@v3 with: go-version: 1.18 + - name: Update version.go + run: | + # strip semantic v + export GOVMOMI_VERSION=${TAG#"v"} + + sed -i "s/ClientVersion =.*/ClientVersion = \"$GOVMOMI_VERSION\"/" internal/version/version.go + git --no-pager diff internal/version/version.go + + # configure author + # https://github.community/t/github-actions-bot-email-address/17204/6 + git config --local user.email 41898282+github-actions[bot]@users.noreply.github.com + git config --local user.name "GitHub Action" + + # commit changes + git add internal/version/version.go + git commit -s -m "chore: Update version.go for ${TAG}" + + - name: Create tag + id: tag + run: | + # create new tag + git tag -a ${TAG} -m "Release ${TAG}" + + # find latest tag sorted by semver ref + LATEST=$(git tag --sort=v:refname | tail -1) + + # check whether the new tag is also the latest + if [[ $LATEST == $TAG ]]; then + echo "::set-output name=islatest::true" + else + echo "::set-output name=islatest::false" + fi + + - name: Push changes and tag to release branch + if: ${{ !inputs.dryrun }} + run: | + git push --atomic --follow-tags origin ${{ github.ref }} + - name: Create RELEASE CHANGELOG env: IMAGE: quay.io/git-chglog/git-chglog @@ -46,7 +119,7 @@ jobs: IMAGE_SHA: 998e89dab8dd8284cfff5f8cfb9e9af41fe3fcd4671f2e86a180e453c20959e3 run: | # generate CHANGELOG for this Github release tag only - docker run --rm -v $PWD:/workdir ${IMAGE}@sha256:${IMAGE_SHA} -o RELEASE_CHANGELOG.md --sort semver --tag-filter-pattern '^v[0-9]+' $(basename "${{ github.ref }}" ) + docker run --rm -v $PWD:/workdir ${IMAGE}@sha256:${IMAGE_SHA} -o RELEASE_CHANGELOG.md --sort semver --tag-filter-pattern '^v[0-9]+' ${TAG} - name: Archive CHANGELOG uses: actions/upload-artifact@v3 @@ -57,7 +130,18 @@ jobs: ./RELEASE_CHANGELOG.md retention-days: 14 + - name: Simulate Release without pushing Artifacts + if: ${{ inputs.dryrun }} + uses: goreleaser/goreleaser-action@v3 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + version: latest + args: release --snapshot --rm-dist --release-notes RELEASE_CHANGELOG.md + + - name: Create Release and build/push Artifacts + if: ${{ !inputs.dryrun }} uses: goreleaser/goreleaser-action@v3 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -70,6 +154,8 @@ jobs: name: Create CHANGELOG.md PR runs-on: ubuntu-20.04 continue-on-error: true + # only update CHANGELOG for latest semver tag + if: ${{ !inputs.dryrun && needs.release.outputs.latesttag == 'true' }} steps: - name: Checkout @@ -92,16 +178,16 @@ jobs: id: cpr uses: peter-evans/create-pull-request@v4 with: - commit-message: "Update CHANGELOG for ${{ github.ref }}" + commit-message: "Update CHANGELOG for ${{ inputs.tag }}" delete-branch: true - title: "Update CHANGELOG for ${{ github.ref }}" + title: "Update CHANGELOG for ${{ inputs.tag }}" signoff: true - reviewers: embano1,dougm draft: false body: | - Update CHANGELOG.md for new release. + ### Update CHANGELOG.md for new release. - **Note:** Due to a [limitation](https://github.com/peter-evans/create-pull-request/blob/master/docs/concepts-guidelines.md#triggering-further-workflow-runs) in Github Actions please **close and immediately reopen** this PR to trigger the required workflow checks before merging. + > **Note** + > Due to a [limitation](https://github.com/peter-evans/create-pull-request/blob/master/docs/concepts-guidelines.md#triggering-further-workflow-runs) in Github Actions please **close and immediately reopen** this PR to trigger the required workflow checks before merging. - name: Pull Request Information run: | diff --git a/RELEASE.md b/RELEASE.md index 45ed3900b..1a12c0640 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -1,11 +1,16 @@ -# How to create a new `govmomi` Release on Github +# How to create a `govmomi` Release on Github -On every new tag matching `v*` pushed to the repository a Github Action Release -Workflow is executed. +> **Note** +> +> The steps outlined in this document can only be performed by maintainers or +> administrators of this project. + +The release automation is based on Github +[Actions](https://github.com/features/actions) and has been improved over time +to simplify the experience for creating `govmomi` releases. The Github Actions release [workflow](.github/workflows/govmomi-release.yaml) -uses [`goreleaser`](http://goreleaser.com/) ([configuration -file](.goreleaser.yml)) and automatically creates/pushes: +uses [`goreleaser`](http://goreleaser.com/) and automatically creates/pushes: - Release artifacts for `govc` and `vcsim` to the [release](https://github.com/vmware/govmomi/releases) page, including @@ -13,10 +18,26 @@ file](.goreleaser.yml)) and automatically creates/pushes: - Docker images for `vmware/govc` and `vmware/vcsim` to Docker Hub - Source code -⚠️ **Note:** These steps can only be performed by maintainers or administrators -of this project. +Starting with release tag `v0.29.0`, releases are not tagged on the `master` +branch anymore but a dedicated release branch, for example `release-0.29`. This +process has already been followed for patch releases and back-ports. + +> **Warning** +> +> If you create a release after the `v0.29.0` tag, start +> [here](#creating-a-release-after-v0290). To create a release with an older +> tag, e.g. cherrypick or back-port, continue +> [here](#creating-a-release-before-v0290). + +## Creating a release after Version `v0.29.0` + +The release process from `v0.29.0` has been further simplified and is done +through the Github UI. The only pre-requirement is creating a release branch, +which can be done through the Github UI or `git` CLI. -## Verify `master` branch is up to date with the remote +This guide describes the CLI process. + +### Verify `master` branch is up to date with the remote ```console git checkout master @@ -27,14 +48,32 @@ git diff master origin/master git pull origin/master ``` -⚠️ **Note:** These steps assume `origin` to point to the remote -`https://github.com/vmware/govmomi`, respectively -`git@github.com:vmware/govmomi`. +> **Warning** +> +> These steps assume `origin` to point to the remote +> `https://github.com/vmware/govmomi`, respectively +> `git@github.com:vmware/govmomi`. -## Verify `make docs` and `CONTRIBUTORS` are up to date +### Create a release branch -⚠️ Run the following commands and commit (PR) any changes before proceeding with -the release. +For new releases, create a release branch from the most recent commit in +`master`, e.g. `release-0.30`. + +```console +export RELEASE_BRANCH=release-0.30 +git checkout -b ${RELEASE_BRANCH} +``` + +For maintenance/patch releases on **existing** release branches **after** tag +`v0.29.0` simply checkout the existing release branch and add commits to the +existing release branch. + +### Verify `make docs` and `CONTRIBUTORS` are up to date + +> **Warning** +> +> Run the following commands and commit any changes to the release branch before +> proceeding with the release. ```console make doc @@ -44,33 +83,136 @@ if [ -z "$(git status --porcelain)" ]; then else echo "working directory dirty: please commit changes" fi + +# perform git add && git commit ... in case there were changes +``` + +### Push the release branch + +> **Warning** +> +> Do not create a tag as this will be done by the release automation. + +The final step is pushing the new/updated release branch. + +```console +git push origin ${RELEASE_BRANCH} +``` + +### Create a release in the Github UI + +Open the `govmomi` Github [repository](https://github.com/vmware/govmomi) and +navigate to `Actions -> Workflows -> Release`. + +Click `Run Workflow` which opens a dropdown list. + +Select the new/updated branch, e.g. `release-0.30`, i.e. **not** the `master` +branch. + +Specify a semantic `tag` to associate with the release, e.g. `v0.30.0`. + +> **Warning** +> +> This tag **must not** exist or the release will fail during the validation +> phase. + +By default, a dry-run is performed to rule out most (but not all) errors during +a release. If you do not want to perform a dry-run, e.g. to finally create a +release, deselect the `Verify release workflow ...` checkbox. + +Click `Run Workflow` to kick off the workflow. + +After successful completion and if the newly created `tag` is the **latest** +(semantic version sorted) tag in the repository, a PR is automatically opened +against the `master` branch to update the `CHANGELOG`. Please review and merge +accordingly. + +## Creating a release before Version `v0.29.0` + +The release process before `v0.29.0` differs since it's based on manually +creating and pushing tags. Here, on every new tag matching `v*` pushed to the +repository a Github Action Release Workflow is executed. + +### Verify `master` branch is up to date with the remote + +```console +git checkout master +git fetch -avp +git diff master origin/master + +# if your local and remote branches diverge run +git pull origin/master +``` + +> **Warning** +> +> These steps assume `origin` to point to the remote +> `https://github.com/vmware/govmomi`, respectively +> `git@github.com:vmware/govmomi`. + +### Create a release branch + +Pick a reference (commit, branch or tag) **before** the `v0.29.0` tag and create +a release branch from there. + +The following example creates a cherrypick release (`v0.28.1`) based on the +`v0.28.0` tag. + +```console +export RELEASE_BRANCH=release-0.28 +git checkout -b ${RELEASE_BRANCH} v0.28.0 ``` +Optionally, incorporate (cherry-pick) commits into the branch. + +> **Warning** +> +> Make sure that these commits/ranges do not contain commits after the `v0.29.0` +> tag which include release automation changes, i.e. files in `.github/workflows/`! + +### Verify `make docs` and `CONTRIBUTORS` are up to date + +> **Warning** +> +> Run the following commands and commit any changes to the release branch before +> proceeding with the release. + +```console +make doc +./scripts/contributors.sh +if [ -z "$(git status --porcelain)" ]; then + echo "working directory clean: proceed with release" +else + echo "working directory dirty: please commit changes" +fi + +# perform git add && git commit ... in case there were changes +``` -## Set `RELEASE_VERSION` variable +### Set `RELEASE_VERSION` variable This variable is used and referenced in the subsequent commands. Set it to the **upcoming** release version, adhering to the [semantic versioning](https://semver.org/) scheme: ```console -export RELEASE_VERSION=v0.27.0 +export RELEASE_VERSION=v0.28.1 ``` -## Create the Git Tag +### Create the Git Tag ```console git tag -a ${RELEASE_VERSION} -m "Release ${RELEASE_VERSION}" ``` -## Push the new Tag +### Push the new Tag ```console # Will trigger Github Actions Release Workflow -git push origin refs/tags/${RELEASE_VERSION} +git push --atomic origin ${RELEASE_BRANCH} refs/tags/${RELEASE_VERSION} ``` -## Verify Github Action Release Workflow +### Verify Github Action Release Workflow After pushing a new release tag, the status of the workflow can be inspected [here](https://github.com/vmware/govmomi/actions/workflows/govmomi-release.yaml).