generated from amazon-archives/__template_Apache-2.0
-
Notifications
You must be signed in to change notification settings - Fork 237
414 lines (391 loc) · 16.7 KB
/
release.yml
File metadata and controls
414 lines (391 loc) · 16.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
# This is the shared release workflow run by both `prod-release.yml` and `dry-run-release.yml'.
# A calling workflow will indicate whether it wants to run this with a prod run or a dry run.
# Allow only one release to run at a time
concurrency:
group: release-smithy-rs-${{ inputs.dry_run }}
cancel-in-progress: true
env:
rust_version: 1.86.0
name: Release smithy-rs
on:
workflow_call:
inputs:
commit_sha:
description: The SHA of the git commit that you want to release.
required: true
type: string
dry_run:
description: When true, it only produces release artifacts, but will not cut a release tag in GitHub or publish to crates.io.
required: true
type: boolean
skip_ci:
description: Skip CI when executing a release
required: true
type: boolean
secrets:
RELEASE_AUTOMATION_BOT_PAT:
required: true
RELEASE_AUTOMATION_BOT_CRATESIO_TOKEN:
required: true
CANARY_GITHUB_ACTIONS_ROLE_ARN:
required: true
CANARY_STACK_CDK_OUTPUTS_BUCKET_NAME:
required: true
SMITHY_RS_ECR_PUSH_ROLE_ARN:
required: true
MAVEN_CENTRAL_GPG_PUBLIC_KEY_SECRET_ARN:
required: true
MAVEN_CENTRAL_GPG_PRIVATE_KEY_SECRET_ARN:
required: true
MAVEN_CENTRAL_GPG_PASSPHRASE_SECRET_ARN:
required: true
MAVEN_CENTRAL_SONATYPE_CREDENTIALS_SECRET_ARN:
required: true
jobs:
check-actor-for-prod-run:
name: Check actor for prod run
if: inputs.dry_run == false
runs-on: ubuntu-latest
env:
ACTOR: ${{ github.actor }}
steps:
- uses: GitHubSecurityLab/actions-permissions/monitor@v1
- name: Check actor for prod run
run: |
set -e
if [ "${ACTOR}" != "aws-sdk-rust-ci" ]; then
echo "Error: The current actor is '${ACTOR}' but only 'aws-sdk-rust-ci' is allowed to run a prod release workflow."
exit 1
fi
echo "The current actor is 'aws-sdk-rust-ci', continuing with the workflow."
# 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
permissions:
id-token: write
contents: read
needs:
- check-actor-for-prod-run
# We need `always` here otherwise this job won't run if the previous job has been skipped
# See https://samanpavel.medium.com/github-actions-conditional-job-execution-e6aa363d2867
if: |
always() &&
(needs.check-actor-for-prod-run.result == 'success' || needs.check-actor-for-prod-run.result == 'skipped')
runs-on: smithy_ubuntu-latest_16-core
steps:
- uses: GitHubSecurityLab/actions-permissions/monitor@v1
- uses: actions/checkout@v4
with:
path: smithy-rs
ref: ${{ inputs.commit_sha }}
fetch-depth: 0
- name: Acquire credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ secrets.SMITHY_RS_ECR_PUSH_ROLE_ARN }}
role-session-name: GitHubActions
aws-region: us-west-2
- name: Acquire base image
id: acquire
run: ./smithy-rs/.github/scripts/acquire-build-image
- name: Upload base image
uses: actions/upload-artifact@v4
with:
name: smithy-rs-base-image
path: smithy-rs-base-image
retention-days: 1
release-ci:
name: Pre-release checks
# We need `always` here otherwise this job won't run if the previous job has been skipped
# See https://samanpavel.medium.com/github-actions-conditional-job-execution-e6aa363d2867
if: always() && inputs.skip_ci == false
needs:
- acquire-base-image
uses: ./.github/workflows/ci.yml
with:
git_ref: ${{ inputs.commit_sha }}
secrets:
CANARY_GITHUB_ACTIONS_ROLE_ARN: ${{ secrets.CANARY_GITHUB_ACTIONS_ROLE_ARN }}
CANARY_STACK_CDK_OUTPUTS_BUCKET_NAME: ${{ secrets.CANARY_STACK_CDK_OUTPUTS_BUCKET_NAME }}
check-semver-hazards:
name: Check for semver hazards
needs:
- acquire-base-image
# We need `always` here otherwise this job won't run if the previous job has been skipped
# See https://samanpavel.medium.com/github-actions-conditional-job-execution-e6aa363d2867
if: always()
runs-on: smithy_ubuntu-latest_8-core
steps:
- uses: actions/checkout@v4
with:
path: smithy-rs
ref: ${{ inputs.commit_sha }}
fetch-depth: 0
- uses: actions/checkout@v4
with:
repository: awslabs/aws-sdk-rust
path: aws-sdk-rust
fetch-depth: 0
- name: Run check-semver-hazards
uses: ./smithy-rs/.github/actions/docker-build
with:
action: check-semver-hazards
use_cache: false
get-or-create-release-branch:
name: Get or create a release branch
needs:
- acquire-base-image
- check-semver-hazards
- release-ci
# We need `always` here otherwise this job won't run if the previous job has been skipped
# See https://samanpavel.medium.com/github-actions-conditional-job-execution-e6aa363d2867
if: |
always() &&
needs.acquire-base-image.result == 'success' &&
(needs.release-ci.result == 'success' || needs.release-ci.result == 'skipped')
runs-on: ubuntu-latest
outputs:
release_branch: ${{ steps.branch-push.outputs.release_branch }}
new_release_series: ${{ steps.branch-push.outputs.new_release_series }}
steps:
- uses: GitHubSecurityLab/actions-permissions/monitor@v1
- uses: actions/checkout@v4
with:
ref: ${{ inputs.commit_sha }}
token: ${{ secrets.RELEASE_AUTOMATION_BOT_PAT }}
fetch-depth: 0
- name: Get or create release branch
id: branch-push
shell: bash
env:
DRY_RUN: ${{ inputs.dry_run }}
run: |
set -e
./.github/scripts/get-or-create-release-branch.sh output
cat output > $GITHUB_OUTPUT
release:
name: Release
needs:
- get-or-create-release-branch
# See https://github.com/actions/runner/issues/2205#issuecomment-1381988186 for an explanation as to why
# we need this here _even though_ the job we depend on is never skipped.
if: |
always() &&
!contains(needs.*.result, 'failure') &&
!contains(needs.*.result, 'cancelled')
runs-on: ubuntu-latest
steps:
- uses: GitHubSecurityLab/actions-permissions/monitor@v1
- name: Install Rust
uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ env.rust_version }}
- name: Checkout smithy-rs
uses: actions/checkout@v4
with:
ref: ${{ inputs.commit_sha }}
path: smithy-rs
token: ${{ secrets.RELEASE_AUTOMATION_BOT_PAT }}
fetch-depth: 0
- name: Generate release artifacts
uses: ./smithy-rs/.github/actions/docker-build
with:
action: generate-smithy-rs-release
use_cache: false
- name: Download all artifacts
uses: ./smithy-rs/.github/actions/download-all-artifacts
# This step is not idempotent, as it pushes release artifacts to the `smithy-rs-release-1.x.y` branch. However,
# if this step succeeds but a subsequent step fails, retrying the release workflow is "safe" in that it does not
# create any inconsistent states; this step would simply fail because the release branch would be ahead of `main`
# due to previously pushed artifacts.
# To successfully retry a release, revert the commits in the release branch that pushed the artifacts.
- name: Push smithy-rs changes
shell: bash
working-directory: smithy-rs-release/smithy-rs
id: push-changelog
env:
RELEASE_BRANCH_NAME: ${{ needs.get-or-create-release-branch.outputs.release_branch }}
DRY_RUN: ${{ inputs.dry_run }}
run: |
if ! git diff-index --quiet HEAD; then
echo "Pushing release commits..."
# This will fail if we tried to release from a non-HEAD commit on the release branch.
# The only scenario where we would try to release a non-HEAD commit from the release branch is
# to retry a release action execution that failed due to a transient issue.
# In that case, we expect the commit to be releasable as-is, i.e. the changelog should have already
# been processed.
git fetch
if [[ "${DRY_RUN}" == "true" ]]; then
# During dry-runs, "git push" without "--force" can fail if smithy-rs-release-x.y.z-preview is behind
# smithy-rs-release-x.y.z, but that does not matter much during dry-runs.
git push --force origin "HEAD:refs/heads/${RELEASE_BRANCH_NAME}"
git push --dry-run origin "HEAD:refs/heads/${RELEASE_BRANCH_NAME}"
else
echo "attempting to push $(git rev-parse HEAD) to $RELEASE_BRANCH_NAME $(git rev-parse $RELEASE_BRANCH_NAME)"
git push origin "HEAD:refs/heads/${RELEASE_BRANCH_NAME}"
fi
fi
echo "commit_sha=$(git rev-parse HEAD)" > $GITHUB_OUTPUT
# This step is idempotent; the `publisher` will not publish a crate if the version is already published on crates.io.
- name: Publish to crates.io
shell: bash
working-directory: smithy-rs-release/crates-to-publish
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.RELEASE_AUTOMATION_BOT_CRATESIO_TOKEN }}
run: |
cargo install --path "$(realpath ../smithy-rs/tools/ci-build/publisher)"
# Verify the publisher tool installed successfully
publisher --version
if [[ "${{ inputs.dry_run }}" == "true" ]]; then
if [[ ! -f aws-smithy-types/Cargo.toml ]]; then
echo "Crates to publish not found!"
exit 1
fi
echo "Checking cargo auth token..."
# This version has already been yanked. This command succeeds if we have a token with permission to yank the crate.
cargo yank aws-sigv4 --version 0.55.0
else
publisher publish -y --location .
fi
# This step is not idempotent and MUST be performed last, as it will generate a new release in the `smithy-rs`
# repository with the release tag that is always unique and has an increasing numerical suffix.
- name: Tag release
uses: actions/github-script@v7
with:
github-token: ${{ secrets.RELEASE_AUTOMATION_BOT_PAT }}
script: |
const createReleaseScript = require("./smithy-rs/.github/workflows/release-scripts/create-release.js");
await createReleaseScript({
github,
isDryRun: ${{ inputs.dry_run }},
releaseManifestPath: "smithy-rs-release/smithy-rs-release-manifest.json",
releaseCommitish: "${{ steps.push-changelog.outputs.commit_sha }}"
});
publish-to-maven-central:
name: Publish Codegen artifacts to Maven Central
needs:
- release
if: always() && needs.release.result == 'success'
runs-on: ubuntu-latest
steps:
- uses: GitHubSecurityLab/actions-permissions/monitor@v1
- uses: actions/checkout@v4
with:
path: smithy-rs
ref: ${{ inputs.commit_sha }}
fetch-depth: 0
- name: Set up JDK
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: '17'
- name: Check if publishing is needed
id: check-publish
shell: bash
working-directory: smithy-rs
run: |
# Run the Gradle task to check if publishing is needed
./gradlew checkMavenCentralPublishingNeeded
# Read the result from the build
if grep -q "mavenCentralPublishingNeeded=true" build/maven-central/publishing.properties; then
echo "publish=true" >> $GITHUB_OUTPUT
else
echo "publish=false" >> $GITHUB_OUTPUT
fi
- name: Acquire credentials
if: steps.check-publish.outputs.publish == 'true'
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ secrets.SMITHY_RS_ECR_PUSH_ROLE_ARN }}
role-session-name: GitHubActions
aws-region: us-west-2
- name: Publish to Maven Central
if: steps.check-publish.outputs.publish == 'true'
shell: bash
working-directory: smithy-rs
env:
GPG_PUBLIC_KEY_SECRET_ARN: ${{ secrets.MAVEN_CENTRAL_GPG_PUBLIC_KEY_SECRET_ARN }}
GPG_PRIVATE_KEY_SECRET_ARN: ${{ secrets.MAVEN_CENTRAL_GPG_PRIVATE_KEY_SECRET_ARN }}
GPG_PASSPHRASE_SECRET_ARN: ${{ secrets.MAVEN_CENTRAL_GPG_PASSPHRASE_SECRET_ARN }}
SONATYPE_CREDENTIALS_SECRET_ARN: ${{ secrets.MAVEN_CENTRAL_SONATYPE_CREDENTIALS_SECRET_ARN }}
JRELEASER_DRY_RUN: ${{ inputs.dry_run }}
run: |
pwd
# Get secrets from AWS Secrets Manager
GPG_PUBLIC_KEY=$(aws secretsmanager get-secret-value --secret-id $GPG_PUBLIC_KEY_SECRET_ARN --query SecretString --output text)
GPG_PRIVATE_KEY=$(aws secretsmanager get-secret-value --secret-id $GPG_PRIVATE_KEY_SECRET_ARN --query SecretString --output text)
GPG_PASSPHRASE=$(aws secretsmanager get-secret-value --secret-id $GPG_PASSPHRASE_SECRET_ARN --query SecretString --output text)
# Get Sonatype credentials from JSON secret
SONATYPE_CREDS=$(aws secretsmanager get-secret-value --secret-id $SONATYPE_CREDENTIALS_SECRET_ARN --query SecretString --output text)
MAVEN_CENTRAL_USERNAME=$(echo $SONATYPE_CREDS | jq -r '.["sonatype-portal-token-username"]')
MAVEN_CENTRAL_TOKEN=$(echo $SONATYPE_CREDS | jq -r '.["sonatype-portal-token"]')
# Set up JReleaser environment variables
export JRELEASER_GPG_PUBLIC_KEY="$GPG_PUBLIC_KEY"
export JRELEASER_GPG_SECRET_KEY="$GPG_PRIVATE_KEY"
export JRELEASER_GPG_PASSPHRASE="$GPG_PASSPHRASE"
export JRELEASER_MAVENCENTRAL_USERNAME="$MAVEN_CENTRAL_USERNAME"
export JRELEASER_MAVENCENTRAL_TOKEN="$MAVEN_CENTRAL_TOKEN"
export JRELEASER_GENERIC_TOKEN=not-used-but-must-be-set
# Run Gradle publish task to stage outputs to build/m2 directory
./gradlew publish
ls -lsa build/m2/software/amazon/smithy/rust
./gradlew jreleaserConfig
./gradlew jreleaserFullRelease
# If this step fails for any reason, there's no need to retry the release workflow, as this step is auxiliary
# and the release itself was successful. Instead, manually trigger `backport-pull-request.yml`.
open-backport-pull-request:
name: Open backport pull request to merge the release branch back to main
needs:
- release
# See https://github.com/actions/runner/issues/2205#issuecomment-1381988186 for details on the workaround
if: inputs.dry_run == false && always() && needs.release.result == 'success'
uses: ./.github/workflows/backport-pull-request.yml
secrets:
RELEASE_AUTOMATION_BOT_PAT: ${{ secrets.RELEASE_AUTOMATION_BOT_PAT }}
publish-build-image:
name: Publish new smithy-rs-build-image tag to ECR
runs-on: smithy_ubuntu-latest_8-core
needs:
- acquire-base-image
- release
if: always() && needs.release.result == 'success'
steps:
- uses: GitHubSecurityLab/actions-permissions/monitor@v1
- uses: actions/checkout@v4
with:
path: smithy-rs
ref: ${{ inputs.commit_sha }}
fetch-depth: 0
- name: Download all artifacts
uses: ./smithy-rs/.github/actions/download-all-artifacts
- name: Acquire credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ secrets.SMITHY_RS_ECR_PUSH_ROLE_ARN }}
role-session-name: GitHubActions
aws-region: us-west-2
- name: Tag and upload new build image
env:
DRY_RUN: ${{ inputs.dry_run }}
shell: bash
run: |
set -x
ls -lsa
docker image ls
# re-load the already built image from previous acquire-build-image step
# image tags in CI are tagged as ci-<tools-dir-sha>
CI_IMAGE_TAG="ci-$(./smithy-rs/.github/scripts/docker-image-hash)"
docker load -i smithy-rs-base-image/smithy-rs-base-image
docker tag "smithy-rs-base-image:${CI_IMAGE_TAG}" "smithy-rs-base-image:local"
docker image ls
# running acquire-build-image with local builds turned off is mostly a no-op
# but it sets up the appropriate "local" tags needed for re-tagging
ALLOW_LOCAL_BUILD=false ./smithy-rs/.github/scripts/acquire-build-image
docker image ls
RELEASE_IMAGE_TAG=$(jq -r ".tagName" smithy-rs-release/smithy-rs-release-manifest.json)
./smithy-rs/.github/scripts/upload-build-image.sh $RELEASE_IMAGE_TAG