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

Update release automation #2877

Merged
merged 1 commit into from
Jun 16, 2022
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
104 changes: 95 additions & 9 deletions .github/workflows/govmomi-release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -33,20 +44,82 @@ 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
# https://quay.io/repository/git-chglog/git-chglog from tag v0.14.2
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
Expand All @@ -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 }}
Expand All @@ -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
Expand All @@ -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: |
Expand Down
182 changes: 162 additions & 20 deletions RELEASE.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,43 @@
# 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
`LICENSE.txt`, `README` and `CHANGELOG`
- 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
Expand All @@ -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
Expand All @@ -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).
Expand Down