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

chore: Refactor release steps ensuring tag is created before running tests and creating release #2154

Merged
merged 10 commits into from
Apr 18, 2024
115 changes: 71 additions & 44 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: 'New Release'
run-name: 'Release ${{ inputs.version_number }}'
run-name: 'Release ${{ inputs.version_number }} (skip tests: ${{ inputs.skip_tests }}, use existing tag: ${{ inputs.use_existing_tag}})'
lantoli marked this conversation as resolved.
Show resolved Hide resolved

# Used for creating a new release. This workflow will run qa acceptance tests, create a new tag, and generate the release with GoReleaser.
on:
Expand All @@ -9,38 +9,43 @@ on:
description: 'Version number (e.g., v1.0.0, v1.0.0-pre, v1.0.0-pre1)'
required: true
skip_tests:
description: 'Skip QA acceptance tests, define value to `true` to explicitly skip'
description: 'Set value to `true` to skip QA acceptance tests, default is `false`'
default: 'false'
use_existing_tag:
description: 'Set value to `true` to use an existing tag for this release version, default is `false`'
description: 'Set value to `true` to use an existing tag for the release process, default is `false`'
default: 'false'
lantoli marked this conversation as resolved.
Show resolved Hide resolved

jobs:

release-config:
runs-on: ubuntu-latest
outputs:
creates_new_tag: ${{ steps.evaluate_inputs.outputs.creates_new_tag }}
is_official_release: ${{ steps.evaluate_inputs.outputs.is_official_release }}
runs_tests: ${{ steps.evaluate_inputs.outputs.runs_tests }}
steps:
- id: evaluate_inputs
run: |
{
echo "creates_new_tag=$(if [ '${{ inputs.use_existing_tag }}' = 'true' ]; then echo 'false'; else echo 'true'; fi)"
echo "is_official_release=$(if echo '${{ inputs.version_number }}' | grep -q 'pre'; then echo 'false'; else echo 'true'; fi)"
echo "runs_tests=$(if [ '${{ inputs.skip_tests }}' = 'true' ]; then echo 'false'; else echo 'true'; fi)"
} >> "$GITHUB_OUTPUT"

validate-version-input:
runs-on: ubuntu-latest
steps:
- name: Validation of version format
run: |
echo "${{ inputs.version_number }}" | grep -P '^v\d+\.\d+\.\d+(-pre[A-Za-z0-9-]*)?$'
echo "${{ inputs.version_number }}" | grep -P '^v\d+\.\d+\.\d+(-pre[A-Za-z0-9-]*)?$'

run-qa-acceptance-tests:
needs: [ validate-version-input ]
# QA acceptance tests are skipped when explicit input parameter is used
# As this job may be skipped following jobs require using 'always()' to make sure they are still run
if: needs.validate-version-input.result == 'success' && inputs.skip_tests != 'true'
secrets: inherit
uses: ./.github/workflows/acceptance-tests.yml
with:
atlas_cloud_env: "qa"
ref: ${{ inputs.use_existing_tag == 'true' && inputs.version_number || github.ref }}

update-examples-reference-in-docs:
needs: [ validate-version-input, run-qa-acceptance-tests ]
needs: [ release-config, validate-version-input ]
if: >-
always()
&& inputs.use_existing_tag != 'true'
lantoli marked this conversation as resolved.
Show resolved Hide resolved
&& !contains(inputs.version_number, 'pre')
&& needs.validate-version-input.result == 'success'
&& (needs.run-qa-acceptance-tests.result == 'skipped' || needs.run-qa-acceptance-tests.result == 'success')
!cancelled()
&& !contains(needs.*.result, 'failure')
&& needs.release-config.outputs.creates_new_tag == 'true'
lantoli marked this conversation as resolved.
Show resolved Hide resolved
&& needs.release-config.outputs.is_official_release == 'true'
uses: ./.github/workflows/run-script-and-commit.yml
with:
script_call: './scripts/update-examples-reference-in-docs.sh ${{inputs.version_number}}'
Expand All @@ -52,13 +57,12 @@ jobs:
passphrase: ${{ secrets.APIX_BOT_PASSPHRASE }}

update-changelog-header:
needs: [ validate-version-input, run-qa-acceptance-tests, update-examples-reference-in-docs ]
needs: [ release-config, validate-version-input, update-examples-reference-in-docs ]
if: >-
always()
&& inputs.use_existing_tag != 'true'
&& !contains(inputs.version_number, 'pre')
&& needs.validate-version-input.result == 'success'
&& (needs.run-qa-acceptance-tests.result == 'skipped' || needs.run-qa-acceptance-tests.result == 'success')
!cancelled()
&& !contains(needs.*.result, 'failure')
&& needs.release-config.outputs.creates_new_tag == 'true'
&& needs.release-config.outputs.is_official_release == 'true'
uses: ./.github/workflows/run-script-and-commit.yml
with:
script_call: './scripts/update-changelog-header-for-release.sh ${{inputs.version_number}}'
Expand All @@ -68,24 +72,19 @@ jobs:
remote: https://svc-apix-bot:${{ secrets.APIX_BOT_PAT }}@github.com/${{ github.repository }}
gpg_private_key: ${{ secrets.APIX_BOT_GPG_PRIVATE_KEY }}
passphrase: ${{ secrets.APIX_BOT_PASSPHRASE }}
release:

create-tag:
runs-on: ubuntu-latest
needs: [ validate-version-input, run-qa-acceptance-tests, update-examples-reference-in-docs, update-changelog-header ]
# Release is skipped if there are failures in previous steps
if: >-
always()
&& needs.validate-version-input.result == 'success'
lantoli marked this conversation as resolved.
Show resolved Hide resolved
&& (needs.run-qa-acceptance-tests.result == 'skipped' || needs.run-qa-acceptance-tests.result == 'success')
&& (needs.update-examples-reference-in-docs.result == 'skipped' || needs.update-examples-reference-in-docs.result == 'success')
&& (needs.update-changelog-header.result == 'skipped' || needs.update-changelog-header.result == 'success')
steps:
needs: [ release-config, validate-version-input, update-examples-reference-in-docs, update-changelog-header ]
if: >-
!cancelled()
&& !contains(needs.*.result, 'failure')
&& needs.release-config.outputs.creates_new_tag == 'true'
steps:
- name: Checkout
uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633
with:
ref: ${{ inputs.use_existing_tag == 'true' && inputs.version_number || 'master' }}
- name: Unshallow
run: git fetch --prune --unshallow
ref: 'master'
- name: Get the latest commit SHA
id: get-sha
run: echo "sha=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT"
Expand All @@ -96,7 +95,31 @@ jobs:
commit_sha: ${{ steps.get-sha.outputs.sha }}
gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }}
gpg_passphrase: ${{ secrets.PASSPHRASE }}
tag_exists_error: ${{ inputs.use_existing_tag != 'true' }}

run-qa-acceptance-tests:
needs: [ release-config, validate-version-input, update-examples-reference-in-docs, update-changelog-header, create-tag ]
if: >-
!cancelled()
&& !contains(needs.*.result, 'failure')
&& needs.release-config.outputs.runs_tests == 'true'
secrets: inherit
uses: ./.github/workflows/acceptance-tests.yml
with:
atlas_cloud_env: "qa"
ref: ${{ inputs.version_number }}

release:
runs-on: ubuntu-latest
needs: [ validate-version-input, update-examples-reference-in-docs, update-changelog-header, create-tag, run-qa-acceptance-tests ]
# Release is skipped if there are failures in previous steps
if: >-
!cancelled()
&& !contains(needs.*.result, 'failure')
steps:
- name: Checkout
uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633
with:
ref: ${{ inputs.version_number }}
- name: Set up Go
uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491
with:
Expand All @@ -117,9 +140,13 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

jira-release-version:
if: ${{ !contains(inputs.version_number, 'pre') }}
needs: [ release ]
runs-on: ubuntu-latest
needs: [ release-config, release ]
# if release job is skipped, cancelled, or failed we do not run this job
if: >-
!cancelled()
&& needs.release.result == 'success'
&& needs.release-config.outputs.is_official_release == 'true'
steps:
- uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633
- uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491
Expand Down
16 changes: 16 additions & 0 deletions RELEASING.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,19 @@ Pre-releases are not needed for a regular release process, but they can be gener
- You will see the release in the [GitHub Release page](https://github.com/mongodb/terraform-provider-mongodbatlas/releases) once the [release action](.github/workflows/release.yml) has completed. HashiCorp has a process in place that will retrieve the latest release from the GitHub repository and add the binaries to the HashiCorp Terraform Registry (more details [here](https://developer.hashicorp.com/terraform/registry/providers/publishing#webhooks)).
- **CDKTF Update - Only for major release, i.e. the left most version digit increment (see this [comment](https://github.com/cdktf/cdktf-repository-manager/pull/202#issuecomment-1602562201))**: Once the provider has been released, we need to update the provider version in our CDKTF. Raise a PR against [cdktf/cdktf-repository-manager](https://github.com/cdktf/cdktf-repository-manager).
- Example PR: [#183](https://github.com/cdktf/cdktf-repository-manager/pull/183)

## FAQ

**What happens if a release execution fails to create the tag but generated automatic commits into master?**

All steps before creating the tag are idempotent, meaning you can run the process again and no additional commits will be generated in the second run.

**What happens if a release execution creates a tag but fails during acceptance tests or creating the release (go releaser step)?**

Once a tag has been created in a previous execution, you can make use of the input `Using an existing tag` to run a new release process.

Depending on the nature of the failure, you may want to introduce new changes into the current release. In this case you must:
- Delete the existing tag.
- Incorporate any new fixes into master.
- Manually trigger the [Generate Changelog workflow](https://github.com/AgustinBettati/terraform-provider-mongodbatlas/actions/workflows/generate-changelog.yml) to remove the current header and including any new entries that have been merged. This will run automatically if you have merged PRs after deleting the tag.
AgustinBettati marked this conversation as resolved.
Show resolved Hide resolved
- Trigger a new release process, this will create a tag that includes your latest fixes.