Skip to content

Commit 187918a

Browse files
authored
Add semver-checks CI job (#2518)
* Add semver-checks CI job * Add flag to skip generation * Make it possible to suppress semver checks with label * fix GitHub script * Fix but in semver-checks python script * Cleanup debug info * Move to ci-pr
1 parent 3862ca0 commit 187918a

File tree

8 files changed

+156
-13
lines changed

8 files changed

+156
-13
lines changed

.github/workflows/ci-pr.yml

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,3 +107,38 @@ jobs:
107107
secrets:
108108
SMITHY_RS_PULL_REQUEST_CDN_S3_BUCKET_NAME: ${{ secrets.SMITHY_RS_PULL_REQUEST_CDN_S3_BUCKET_NAME }}
109109
SMITHY_RS_PULL_REQUEST_CDN_ROLE_ARN: ${{ secrets.SMITHY_RS_PULL_REQUEST_CDN_ROLE_ARN }}
110+
111+
semver-checks:
112+
name: check the semver status of this PR
113+
runs-on: smithy_ubuntu-latest_8-core
114+
steps:
115+
- uses: actions/checkout@v3
116+
with:
117+
path: smithy-rs
118+
ref: ${{ inputs.git_ref }}
119+
- name: Get PR info
120+
id: check-breaking-label
121+
uses: actions/github-script@v6
122+
with:
123+
script: |
124+
const response = await github.rest.pulls.get({
125+
pull_number: context.issue.number,
126+
owner: context.repo.owner,
127+
repo: context.repo.repo,
128+
});
129+
const labels = response.data.labels.map(l => l.name);
130+
const isBreaking = labels.includes("breaking-change");
131+
const data = {
132+
labels,
133+
isBreaking
134+
};
135+
console.log("data:", data);
136+
return data;
137+
- name: Run semver check
138+
uses: ./smithy-rs/.github/actions/docker-build
139+
with:
140+
action: check-semver
141+
action-arguments: ${{ github.event.pull_request.base.sha }} ${{ fromJSON(steps.check-breaking-label.outputs.result).isBreaking }}
142+
- name: print help message
143+
if: failure()
144+
run: echo "::error::This pull request contains breaking changes. Please add the `breaking-changes` label and a changelog entry"

.github/workflows/ci.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,8 @@ jobs:
159159
with:
160160
action: ${{ matrix.test.action }}
161161

162+
163+
162164
test-rust-windows:
163165
name: Rust Tests on Windows
164166
runs-on: windows-latest

ci.mk

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,10 @@ generate-codegen-diff:
120120
check-deterministic-codegen:
121121
$(CI_ACTION) $@ $(ARGS)
122122

123+
.PHONY: check-semver
124+
check-semver:
125+
$(CI_ACTION) $@ $(ARGS)
126+
123127
.PHONY: generate-smithy-rs-release
124128
generate-smithy-rs-release:
125129
$(CI_ACTION) $@ $(ARGS)

tools/ci-scripts/check-semver

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#!/bin/bash
2+
#
3+
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4+
# SPDX-License-Identifier: Apache-2.0
5+
#
6+
7+
set -eux
8+
cd smithy-rs
9+
10+
if [[ $# -gt 2 ]]; then
11+
echo "Usage: check-semver <base-revision> <warn-on-failure (true/false)>"
12+
exit 1
13+
fi
14+
15+
# Override version commit hash to prevent unnecessary diffs
16+
export SMITHY_RS_VERSION_COMMIT_HASH_OVERRIDE=ci
17+
base_revision="$1"
18+
warn_on_failure="$2"
19+
if [[ $warn_on_failure == "true" ]]
20+
then
21+
./tools/ci-scripts/codegen-diff/semver-checks.py . "${base_revision}" || echo "allowing failure"
22+
else
23+
./tools/ci-scripts/codegen-diff/semver-checks.py . "${base_revision}"
24+
fi

tools/ci-scripts/codegen-diff/check-deterministic-codegen.py

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,18 @@
33
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
44
# SPDX-License-Identifier: Apache-2.0
55

6-
import sys
76
import os
8-
from diff_lib import get_cmd_output, generate_and_commit_generated_code
7+
import sys
8+
9+
from diff_lib import get_cmd_output, checkout_commit_and_generate
10+
911

1012
def main():
1113
repository_root = sys.argv[1]
1214
os.chdir(repository_root)
1315
(_, head_commit_sha, _) = get_cmd_output("git rev-parse HEAD")
14-
get_cmd_output("git checkout -B once")
15-
generate_and_commit_generated_code(head_commit_sha, targets=['aws:sdk'])
16-
get_cmd_output(f"git checkout {head_commit_sha}")
17-
get_cmd_output("git checkout -B twice")
18-
generate_and_commit_generated_code(head_commit_sha, targets=['aws:sdk'])
16+
checkout_commit_and_generate(head_commit_sha, targets=['aws:sdk'], branch_name='once')
17+
checkout_commit_and_generate(head_commit_sha, targets=['aws:sdk'], branch_name='twice')
1918
get_cmd_output('git diff once..twice --exit-code')
2019

2120

tools/ci-scripts/codegen-diff/codegen-diff-revisions.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import sys
88

99
from diff_lib import eprint, run, get_cmd_status, get_cmd_output, generate_and_commit_generated_code, make_diffs, \
10-
write_to_file, HEAD_BRANCH_NAME, BASE_BRANCH_NAME, OUTPUT_PATH
10+
write_to_file, HEAD_BRANCH_NAME, BASE_BRANCH_NAME, OUTPUT_PATH, running_in_docker_build
1111

1212

1313
# This script can be run and tested locally. To do so, you should check out
@@ -32,8 +32,6 @@
3232
# ```
3333
# Make sure the local version matches the version referenced from the GitHub Actions workflow.
3434

35-
def running_in_docker_build():
36-
return os.environ.get("SMITHY_RS_DOCKER_BUILD_IMAGE") == "1"
3735

3836

3937
def main():

tools/ci-scripts/codegen-diff/diff_lib.py

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,21 @@
2020
target_aws_sdk = 'aws:sdk'
2121

2222

23+
def running_in_docker_build():
24+
return os.environ.get("SMITHY_RS_DOCKER_BUILD_IMAGE") == "1"
25+
26+
27+
def checkout_commit_and_generate(revision_sha, branch_name, targets=None):
28+
if running_in_docker_build():
29+
eprint(f"Fetching base revision {revision_sha} from GitHub...")
30+
run(f"git fetch --no-tags --progress --no-recurse-submodules --depth=1 origin {revision_sha}")
31+
32+
# Generate code for HEAD
33+
eprint(f"Creating temporary branch {branch_name} with generated code for {revision_sha}")
34+
run(f"git checkout {revision_sha} -B {branch_name}")
35+
generate_and_commit_generated_code(revision_sha, targets)
36+
37+
2338
def generate_and_commit_generated_code(revision_sha, targets=None):
2439
targets = targets or [target_codegen_client, target_codegen_server, target_aws_sdk]
2540
# Clean the build artifacts before continuing
@@ -170,12 +185,14 @@ def run(command, shell=False, check=True):
170185

171186

172187
# Returns (status, stdout, stderr) from a shell command
173-
def get_cmd_output(command, cwd=None, check=True, **kwargs):
188+
def get_cmd_output(command, cwd=None, check=True, quiet=False, **kwargs):
174189
if isinstance(command, str):
175-
eprint(f"running {command}")
190+
if not quiet:
191+
eprint(f"running {command}")
176192
command = shlex.split(command)
177193
else:
178-
eprint(f"running {' '.join(command)}")
194+
if not quiet:
195+
eprint(f"running {' '.join(command)}")
179196

180197
result = subprocess.run(
181198
command,
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
#!/usr/bin/env python3
2+
3+
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4+
# SPDX-License-Identifier: Apache-2.0
5+
import sys
6+
import os
7+
from diff_lib import get_cmd_output, get_cmd_status, eprint, running_in_docker_build, checkout_commit_and_generate, \
8+
OUTPUT_PATH
9+
10+
11+
CURRENT_BRANCH = 'current'
12+
BASE_BRANCH = 'base'
13+
# This script runs `cargo semver-checks` against a previous version of codegen
14+
def main(skip_generation=False):
15+
if len(sys.argv) != 3:
16+
eprint("Usage: semver-checks.py <repository root> <base commit sha>")
17+
sys.exit(1)
18+
19+
repository_root = sys.argv[1]
20+
base_commit_sha = sys.argv[2]
21+
os.chdir(repository_root)
22+
(_, head_commit_sha, _) = get_cmd_output("git rev-parse HEAD")
23+
24+
# Make sure the working tree is clean
25+
if get_cmd_status("git diff --quiet") != 0:
26+
eprint("working tree is not clean. aborting")
27+
sys.exit(1)
28+
29+
if not skip_generation:
30+
checkout_commit_and_generate(head_commit_sha, CURRENT_BRANCH, targets=['aws:sdk'])
31+
checkout_commit_and_generate(base_commit_sha, BASE_BRANCH, targets=['aws:sdk'])
32+
get_cmd_output(f'git checkout {CURRENT_BRANCH}')
33+
sdk_directory = os.path.join(OUTPUT_PATH, 'aws-sdk', 'sdk')
34+
os.chdir(sdk_directory)
35+
36+
failed = False
37+
for path in os.listdir():
38+
eprint(f'checking {path}...', end='')
39+
if get_cmd_status(f'git cat-file -e base:{sdk_directory}/{path}/Cargo.toml') == 0:
40+
(status, out, err) = get_cmd_output(f'cargo semver-checks check-release '
41+
f'--baseline-rev {BASE_BRANCH} '
42+
# in order to get semver-checks to work with publish-false crates, need to specify
43+
# package and manifest path explicitly
44+
f'--manifest-path {path}/Cargo.toml '
45+
f'-p {path} '
46+
f'--release-type patch', check=False, quiet=True)
47+
if status == 0:
48+
eprint('ok!')
49+
else:
50+
failed = True
51+
eprint('failed!')
52+
if out:
53+
eprint(out)
54+
eprint(err)
55+
else:
56+
eprint(f'skipping {path} because it does not exist in base')
57+
if failed:
58+
eprint('One or more crates failed semver checks!')
59+
exit(1)
60+
61+
62+
if __name__ == "__main__":
63+
skip_generation = bool(os.environ.get('SKIP_GENERATION') or False)
64+
main(skip_generation=skip_generation)

0 commit comments

Comments
 (0)