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

Change the release flow to use release branches #2253

Merged
merged 40 commits into from
Feb 1, 2023
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
ca22c78
What happens if we comment out the runtime crate version from gradle.…
LukeMathWalker Jan 26, 2023
1d045ea
Allow running the release and the CI workflows from an arbitrary commit.
LukeMathWalker Jan 26, 2023
37bc560
Does a fake version work?
LukeMathWalker Jan 26, 2023
a8a6ff2
Pass `git_ref` from the release workflow.
LukeMathWalker Jan 26, 2023
219f125
It needs to be a valid semver version.
LukeMathWalker Jan 26, 2023
9394c6b
Sketch new command to upgrade version in gradle.properties
LukeMathWalker Jan 26, 2023
6ee191d
Command implementation
LukeMathWalker Jan 26, 2023
9d997d1
Plug the new publisher command into the `release` action.
LukeMathWalker Jan 27, 2023
8a8713a
Plumb end-to-end
LukeMathWalker Jan 27, 2023
9cadab2
Fix copyright header.
LukeMathWalker Jan 27, 2023
93dcf7b
Fix lint.
LukeMathWalker Jan 27, 2023
d163264
Temporarily comment out the sanity check.
LukeMathWalker Jan 27, 2023
91b2978
Ignore sanity check
LukeMathWalker Jan 27, 2023
63b3a56
Add a command that prints out the template for CHANGELOG.next.toml
LukeMathWalker Jan 30, 2023
aa2a7eb
Add branch check + empty TOML generation.
LukeMathWalker Jan 30, 2023
cfea8dc
Merge branch 'main' into patches
LukeMathWalker Jan 30, 2023
14c4118
Add copyright headers.
LukeMathWalker Jan 30, 2023
99b6ece
Fix imports.
LukeMathWalker Jan 30, 2023
f8de002
Remove sanity check.
LukeMathWalker Jan 31, 2023
dd472e4
Move script to a file.
LukeMathWalker Jan 31, 2023
5dd621d
Merge branch 'main' into patches
LukeMathWalker Jan 31, 2023
7841f53
Add a check to validate the tag.
LukeMathWalker Jan 31, 2023
e07e0cd
Remove second build step.
LukeMathWalker Jan 31, 2023
815ffc5
Move to .github/scripts folder.
LukeMathWalker Feb 1, 2023
4851010
Make the script easier to run locally
LukeMathWalker Feb 1, 2023
a439fc5
Fail if anything fails.
LukeMathWalker Feb 1, 2023
a318f04
Add comment.
LukeMathWalker Feb 1, 2023
42fc4fb
Update .github/scripts/get-or-create-release-branch.sh
LukeMathWalker Feb 1, 2023
7751de1
Update .github/scripts/get-or-create-release-branch.sh
LukeMathWalker Feb 1, 2023
3a52ed7
Update .github/scripts/get-or-create-release-branch.sh
LukeMathWalker Feb 1, 2023
0414cce
Update .github/workflows/ci.yml
LukeMathWalker Feb 1, 2023
e3c0bc2
Remove touch.
LukeMathWalker Feb 1, 2023
9a739ba
Fix indentation and branch name.
LukeMathWalker Feb 1, 2023
c95e895
Update .github/workflows/ci.yml
LukeMathWalker Feb 1, 2023
b7dab07
Update .github/workflows/release.yml
LukeMathWalker Feb 1, 2023
53bb4cc
Update .github/workflows/release.yml
LukeMathWalker Feb 1, 2023
7806c72
Explicit flags.
LukeMathWalker Feb 1, 2023
62e0518
Use the path that was provided.
LukeMathWalker Feb 1, 2023
2526b89
Format
LukeMathWalker Feb 1, 2023
5b2fa2b
Merge branch 'main' into patches
LukeMathWalker Feb 1, 2023
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
15 changes: 15 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@ on:
required: false
default: false
type: boolean
git_ref:
description: |
LukeMathWalker marked this conversation as resolved.
Show resolved Hide resolved
The git reference that all checks should be run against. It can be a branch, a tag or a commit SHA.
If unspecified, it will default to the git reference that triggered the execution of this workflow.
LukeMathWalker marked this conversation as resolved.
Show resolved Hide resolved
required: false
type: string
default: ""

env:
rust_version: 1.62.1
Expand All @@ -39,6 +46,7 @@ jobs:
- uses: actions/checkout@v3
with:
path: smithy-rs
ref: ${{ inputs.git_ref }}
# The models from aws-sdk-rust are needed to generate the full SDK for CI
- uses: actions/checkout@v3
with:
Expand Down Expand Up @@ -84,6 +92,7 @@ jobs:
- uses: actions/checkout@v3
with:
path: smithy-rs
ref: ${{ inputs.git_ref }}
- name: Run ${{ matrix.test.action }}
uses: ./smithy-rs/.github/actions/docker-build
with:
Expand Down Expand Up @@ -113,6 +122,7 @@ jobs:
- uses: actions/checkout@v3
with:
path: smithy-rs
ref: ${{ inputs.git_ref }}
- name: Run ${{ matrix.test.action }}
uses: ./smithy-rs/.github/actions/docker-build
with:
Expand All @@ -128,6 +138,8 @@ jobs:
RUSTFLAGS: -D warnings
steps:
- uses: actions/checkout@v3
with:
ref: ${{ inputs.git_ref }}
# Pinned to the commit hash of v2.1.0
- uses: Swatinem/rust-cache@b894d59a8d236e2979b247b80dac8d053ab340dd
with:
Expand Down Expand Up @@ -190,6 +202,8 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v3
with:
ref: ${{ inputs.git_ref }}
# Pinned to the commit hash of v2.1.0
- uses: Swatinem/rust-cache@b894d59a8d236e2979b247b80dac8d053ab340dd
with:
Expand Down Expand Up @@ -258,6 +272,7 @@ jobs:
- uses: actions/checkout@v3
with:
path: smithy-rs
ref: ${{ inputs.git_ref }}
- name: Run ${{ matrix.actions.action }}
uses: ./smithy-rs/.github/actions/docker-build
with:
Expand Down
212 changes: 183 additions & 29 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,48 +6,44 @@

# Allow only one release to run at a time
concurrency:
group: release-smithy-rs
group: release-smithy-rs-${{ inputs.dry_run }}
cancel-in-progress: true

env:
rust_version: 1.62.1

name: Release smithy-rs
run-name: ${{ github.workflow }} - ${{ inputs.dry_run && 'Dry run' || 'Production run' }}
run-name: ${{ github.workflow }} ${{ inputs.semantic_version }} (${{ inputs.commit_sha }}) - ${{ inputs.dry_run && 'Dry run' || 'Production run' }}
on:
workflow_dispatch:
inputs:
commit_sha:
description: The SHA of the git commit that you want to release (e.g. b2318b0)
required: true
type: string
semantic_version:
description: The semver tag that you want to release (e.g. 0.52.1)
required: true
type: string
dry_run:
description: Dry runs will only produce release artifacts, but will not cut a release tag in GitHub nor publish to crates.io
description: Dry runs will only produce release artifacts, but they will not cut a release tag in GitHub nor publish to crates.io
required: true
type: boolean
default: true

jobs:
main-branch-check:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any way we could check that the versions we will be publishing in gradle.properties aren't already published? Would be a nice sanity check that the gradle.properties was correctly updated.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It'd be quite cumbersome.
Things can fail at any step, including publishing - leaving us with some unpublished runtime crates. I'm opting for building the workflow in such a way that all steps are idempotent, therefore allowing us to retry any transient failure by re-triggering the workflow from the right commit.

name: Check that workflow is running in main
runs-on: ubuntu-latest
steps:
- name: Main branch check
if: ${{ github.ref_name != 'main' }}
uses: actions/github-script@v6
with:
script: |
core.setFailed("The release workflow can only be ran on main (current branch: ${{ github.ref_name }})")

# If a release is kicked off before an image is built after push to main,
# or if a dry-run release is kicked off against a non-main branch to test
# automation changes, we'll need to build a base image to work against.
# This job will be a no-op if an image was already built on main.
# We'll need to build a base image to work against if:
# - a release was kicked off before the image build step triggered by a push to the release branch/main completed
# - a dry-run release was kicked off against a feature branch to test automation changes
# This job will be a no-op if an image had already been built.
acquire-base-image:
name: Acquire Base Image
needs:
- main-branch-check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
path: smithy-rs
ref: ${{ inputs.commit_sha }}
fetch-depth: 0
- name: Acquire base image
id: acquire
Expand All @@ -61,17 +57,151 @@ jobs:

release-ci:
name: Prerelease checks
if: inputs.dry_run == false
needs:
- acquire-base-image
uses: ./.github/workflows/ci.yml
with:
run_sdk_examples: false
git_ref: ${{ inputs.commit_sha }}

get-or-create-release-branch:
name: Get or create a release branch
needs:
- release-ci
outputs:
release_branch: ${{ steps.branch-push.outputs.release_branch }}
new_release_series: ${{ steps.branch-push.outputs.new_release_series }}
steps:
- uses: actions/checkout@v3
with:
ref: ${{ inputs.commit_sha }}
token: ${{ secrets.RELEASE_AUTOMATION_BOT_PAT }}
- name: Get or create release branch
id: branch-push
shell: bash
env:
SEMANTIC_VERSION: ${{ inputs.semantic_version }}
DRY_RUN: ${{ inputs.dry_run }}
run: |
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider pulling this out to a separate shell script file so that it can be easily tested locally

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in dd472e4
Shellcheck found a lot of issues 😅 Thanks for pointing it out.

# Split on the dots
version_array=( ${SEMANTIC_VERSION//./ } )
major=version_array[0]
minor=version_array[1]
patch=version_array[2]
if [[ major == 0 ]]; then
branch_name="smithy-rs-release-${major}.${minor}.x"
if [[ patch == 0 ]]; then
echo "new_release_series=true" > $GITHUB_OUTPUT
fi
else
branch_name="smithy-rs-release-${major}.x.y"
if [[ minor == 0 && patch == 0 ]]; then
echo "new_release_series=true" > $GITHUB_OUTPUT
fi
fi

if [[ "${DRY_RUN}" == "true" ]]; then
branch_name="${branch_name}-preview"
fi
echo "release_branch=${branch_name}" > $GITHUB_OUTPUT

if [[ "${DRY_RUN}" == "true" ]]; then
git push -f origin HEAD:${branch_name}
else
commit_sha=$(git rev-parse --verify --short HEAD)
if [[ git ls-remote --exit-code --heads origin ${branch_name} ]]; then
# The release branch already exists, we need to make sure that our commit is its current tip
branch_head_sha=$(git rev-parse --verify --short refs/heads/patches)
if [[ branch_head_sha != commit_sha ]]; then
echo "The release branch - ${branch_name} - already exists. ${commit_sha}, the commit you chose when "
echo "launching this release, is not its current HEAD (${branch_head_sha}). This is not allowed: you "
echo "MUST release from the HEAD of the release branch if it already exists."
exit 1
fi
else
# The release branch does not exist.
# We need to make sure that the commit SHA that we are releasing is on `main`.
git fetch origin main
if [[ git branch --contains ${commit_sha} | grep main ]]; then
# We can then create create the release branch and set the current commit as its tip
git checkout -b ${branch_name}
git push origin ${branch_name}
else
echo "You must choose a commit from main to create a new release series!"
exit 1
fi
fi
fi

upgrade-gradle-properties:
name: Upgrade gradle.properties
if: inputs.dry_run == false
needs:
- get-or-create-release-branch
outputs:
commit_sha: ${{ steps.gradle-push.outputs.commit_sha }}
release_branch: ${{ needs.get-or-create-release-branch.outputs.release_branch }}
steps:
- uses: actions/checkout@v3
with:
ref: ${{ inputs.release_branch }}
token: ${{ secrets.RELEASE_AUTOMATION_BOT_PAT }}
- name: Upgrade gradle.properties
uses: ./smithy-rs/.github/actions/docker-build
with:
action: upgrade-gradle-smithy-rs-release ${{ inputs.semantic_version }}
- name: Push gradle.properties changes
id: gradle-push
shell: bash
env:
SEMANTIC_VERSION: ${{ inputs.semantic_version }}
DRY_RUN: ${{ inputs.dry_run }}
run: |
if [[ git diff-index --quiet HEAD ]]; then
# The file was actually changed, we need to commit and push the changes
git commit gradle.properties -m "Upgrade the smithy-rs runtime crates version to ${SEMANTIC_VERSION}"
echo "Pushing upgraded gradle.properties commits..."
LukeMathWalker marked this conversation as resolved.
Show resolved Hide resolved
git push origin
fi
echo "commit_sha=$(git rev-parse --verify --short HEAD)" > $GITHUB_OUTPUT
LukeMathWalker marked this conversation as resolved.
Show resolved Hide resolved

# We'll need to build a base image again if the previous job upgraded the gradle.properties file.
# This job will be a no-op if the version in gradle.properties had already been upgraded.
acquire-base-image-2:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What in tools/ uses the gradle.properties file? Doesn't seem like this should be necessary. Even if a tool reads gradle.properties from the filesystem, it shouldn't need an updated Docker image since that version number isn't being compiled into the tool.

Separately, you will probably want an escape hatch for using the latest tools in main for the actual release workflow since you may need an updated publisher to actually successfully publish.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Separately, you will probably want an escape hatch for using the latest tools in main for the actual release workflow since you may need an updated publisher to actually successfully publish.

My assumption is that you can always merge the upgraded tools into the release branch if that's required, indeed as an escape hatch.

name: Acquire Base Image
runs-on: ubuntu-latest
needs:
- upgrade-gradle-properties
outputs:
commit_sha: ${{ steps.output.outputs.commit_sha }}
release_branch: ${{ needs.upgrade-gradle-properties.outputs.release_branch }}
steps:
- uses: actions/checkout@v3
with:
path: smithy-rs
# The ref for the commit after the gradle.properties upgrade
ref: ${{ needs.upgrade-gradle-properties.outputs.commit_sha }}
fetch-depth: 0
- name: Acquire base image
id: acquire
run: ./smithy-rs/tools/ci-build/acquire-build-image
- name: Upload base image
uses: actions/upload-artifact@v3
with:
name: smithy-rs-base-image
path: smithy-rs-base-image
retention-days: 1
- name: Persist the SHA we used to build the Docker image
id: output
shell: bash
run: |
echo "commit_sha=$(git rev-parse --verify --short HEAD)" > $GITHUB_OUTPUT

release:
name: Release
needs:
- acquire-base-image
- release-ci
- acquire-base-image-2
runs-on: ubuntu-latest
steps:
- name: Install Rust
Expand All @@ -81,6 +211,7 @@ jobs:
- name: Checkout smithy-rs
uses: actions/checkout@v3
with:
ref: ${{ needs.acquire-base-image-2.outputs.release_branch }}
path: smithy-rs
token: ${{ secrets.RELEASE_AUTOMATION_BOT_PAT }}
- name: Generate release artifacts
Expand All @@ -93,13 +224,8 @@ jobs:
shell: bash
working-directory: smithy-rs-release/smithy-rs
run: |
if [[ "${{ inputs.dry_run }}" == "true" ]]; then
echo "Pushing a preview of the release to the smithy-rs-release-preview branch"
git push --force origin HEAD:smithy-rs-release-preview
else
echo "Pushing release commits..."
git push origin
fi
echo "Pushing release commits..."
git push origin
- name: Tag release
uses: actions/github-script@v6
with:
Expand Down Expand Up @@ -133,3 +259,31 @@ jobs:
else
publisher publish -y --location .
fi

trim-changelog-next-on-main:
name: Remove released entries from CHANGELOG.next.toml on the main branch
if: inputs.dry_run == false && needs.get-or-create-release-branch.outputs.new_release_series == true
Comment on lines +186 to +188
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SDK changelog entries need to end up in aws/SDK_CHANGELOG.next.json upon release so that the SDK changelog can be generated when it is released. It currently uses the changelogger split subcommand to accomplish this. Does this new release process preserve that?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes - the aws/SDK_CHANGELOG.next.json will be on the release branch and it's generated in the previous step of the workflow.

needs:
- get-or-create-release-branch
- release
runs-on: ubuntu-latest
steps:
- name: Checkout smithy-rs
uses: actions/checkout@v3
with:
ref: ${{ inputs.commit_sha }}
token: ${{ secrets.RELEASE_AUTOMATION_BOT_PAT }}
- name: Empty CHANGELOG.next.toml
uses: ./smithy-rs/.github/actions/docker-build
with:
action: generate-new-changelog-next-toml
- name: Push smithy-rs changes
shell: bash
run: |
# This will fail if other commits have been pushed to `main` after `commit_sha`
# In particular, this will ALWAYS fail if you are creating a new release series from
# a commit that is not the current tip of `main`.
# We can build more refined automation to handle this case in the future - until then, it'll require
# a manual PR to edit the current CHANGELOG.next.toml file and remove the released entries.
git commit CHANGELOG.next.toml -m "Remove released entries from CHANGELOG.next.toml"
LukeMathWalker marked this conversation as resolved.
Show resolved Hide resolved
git push origin main
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ rust.msrv=1.62.1
org.gradle.jvmargs=-Xmx1024M

# Version number to use for the generated runtime crates
smithy.rs.runtime.crate.version=0.54.1
smithy.rs.runtime.crate.version=0.0.0-smithy-rs-head

kotlin.code.style=official

Expand Down
11 changes: 11 additions & 0 deletions tools/changelogger/src/init.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
use crate::render::EXAMPLE_ENTRY;
use clap::Parser;
use std::io::Write;

#[derive(Parser, Debug, Eq, PartialEq)]
pub struct InitArgs {}

pub fn subcommand_init(_args: &InitArgs) -> anyhow::Result<()> {
writeln!(std::io::stdout(), "{}", EXAMPLE_ENTRY)?;
Ok(())
}
1 change: 1 addition & 0 deletions tools/changelogger/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@
*/

pub mod entry;
pub mod init;
pub mod render;
pub mod split;
Loading