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
This commit is contained in:
Russell Cohen 2023-04-06 12:42:13 -04:00 committed by GitHub
parent 3862ca0a37
commit 187918a0eb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 156 additions and 13 deletions

View File

@ -107,3 +107,38 @@ jobs:
secrets:
SMITHY_RS_PULL_REQUEST_CDN_S3_BUCKET_NAME: ${{ secrets.SMITHY_RS_PULL_REQUEST_CDN_S3_BUCKET_NAME }}
SMITHY_RS_PULL_REQUEST_CDN_ROLE_ARN: ${{ secrets.SMITHY_RS_PULL_REQUEST_CDN_ROLE_ARN }}
semver-checks:
name: check the semver status of this PR
runs-on: smithy_ubuntu-latest_8-core
steps:
- uses: actions/checkout@v3
with:
path: smithy-rs
ref: ${{ inputs.git_ref }}
- name: Get PR info
id: check-breaking-label
uses: actions/github-script@v6
with:
script: |
const response = await github.rest.pulls.get({
pull_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
});
const labels = response.data.labels.map(l => l.name);
const isBreaking = labels.includes("breaking-change");
const data = {
labels,
isBreaking
};
console.log("data:", data);
return data;
- name: Run semver check
uses: ./smithy-rs/.github/actions/docker-build
with:
action: check-semver
action-arguments: ${{ github.event.pull_request.base.sha }} ${{ fromJSON(steps.check-breaking-label.outputs.result).isBreaking }}
- name: print help message
if: failure()
run: echo "::error::This pull request contains breaking changes. Please add the `breaking-changes` label and a changelog entry"

View File

@ -159,6 +159,8 @@ jobs:
with:
action: ${{ matrix.test.action }}
test-rust-windows:
name: Rust Tests on Windows
runs-on: windows-latest

4
ci.mk
View File

@ -120,6 +120,10 @@ generate-codegen-diff:
check-deterministic-codegen:
$(CI_ACTION) $@ $(ARGS)
.PHONY: check-semver
check-semver:
$(CI_ACTION) $@ $(ARGS)
.PHONY: generate-smithy-rs-release
generate-smithy-rs-release:
$(CI_ACTION) $@ $(ARGS)

24
tools/ci-scripts/check-semver Executable file
View File

@ -0,0 +1,24 @@
#!/bin/bash
#
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
#
set -eux
cd smithy-rs
if [[ $# -gt 2 ]]; then
echo "Usage: check-semver <base-revision> <warn-on-failure (true/false)>"
exit 1
fi
# Override version commit hash to prevent unnecessary diffs
export SMITHY_RS_VERSION_COMMIT_HASH_OVERRIDE=ci
base_revision="$1"
warn_on_failure="$2"
if [[ $warn_on_failure == "true" ]]
then
./tools/ci-scripts/codegen-diff/semver-checks.py . "${base_revision}" || echo "allowing failure"
else
./tools/ci-scripts/codegen-diff/semver-checks.py . "${base_revision}"
fi

View File

@ -3,19 +3,18 @@
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
import sys
import os
from diff_lib import get_cmd_output, generate_and_commit_generated_code
import sys
from diff_lib import get_cmd_output, checkout_commit_and_generate
def main():
repository_root = sys.argv[1]
os.chdir(repository_root)
(_, head_commit_sha, _) = get_cmd_output("git rev-parse HEAD")
get_cmd_output("git checkout -B once")
generate_and_commit_generated_code(head_commit_sha, targets=['aws:sdk'])
get_cmd_output(f"git checkout {head_commit_sha}")
get_cmd_output("git checkout -B twice")
generate_and_commit_generated_code(head_commit_sha, targets=['aws:sdk'])
checkout_commit_and_generate(head_commit_sha, targets=['aws:sdk'], branch_name='once')
checkout_commit_and_generate(head_commit_sha, targets=['aws:sdk'], branch_name='twice')
get_cmd_output('git diff once..twice --exit-code')

View File

@ -7,7 +7,7 @@ import os
import sys
from diff_lib import eprint, run, get_cmd_status, get_cmd_output, generate_and_commit_generated_code, make_diffs, \
write_to_file, HEAD_BRANCH_NAME, BASE_BRANCH_NAME, OUTPUT_PATH
write_to_file, HEAD_BRANCH_NAME, BASE_BRANCH_NAME, OUTPUT_PATH, running_in_docker_build
# This script can be run and tested locally. To do so, you should check out
@ -32,8 +32,6 @@ from diff_lib import eprint, run, get_cmd_status, get_cmd_output, generate_and_c
# ```
# Make sure the local version matches the version referenced from the GitHub Actions workflow.
def running_in_docker_build():
return os.environ.get("SMITHY_RS_DOCKER_BUILD_IMAGE") == "1"
def main():

View File

@ -20,6 +20,21 @@ target_codegen_server = 'codegen-server-test'
target_aws_sdk = 'aws:sdk'
def running_in_docker_build():
return os.environ.get("SMITHY_RS_DOCKER_BUILD_IMAGE") == "1"
def checkout_commit_and_generate(revision_sha, branch_name, targets=None):
if running_in_docker_build():
eprint(f"Fetching base revision {revision_sha} from GitHub...")
run(f"git fetch --no-tags --progress --no-recurse-submodules --depth=1 origin {revision_sha}")
# Generate code for HEAD
eprint(f"Creating temporary branch {branch_name} with generated code for {revision_sha}")
run(f"git checkout {revision_sha} -B {branch_name}")
generate_and_commit_generated_code(revision_sha, targets)
def generate_and_commit_generated_code(revision_sha, targets=None):
targets = targets or [target_codegen_client, target_codegen_server, target_aws_sdk]
# Clean the build artifacts before continuing
@ -170,12 +185,14 @@ def run(command, shell=False, check=True):
# Returns (status, stdout, stderr) from a shell command
def get_cmd_output(command, cwd=None, check=True, **kwargs):
def get_cmd_output(command, cwd=None, check=True, quiet=False, **kwargs):
if isinstance(command, str):
eprint(f"running {command}")
if not quiet:
eprint(f"running {command}")
command = shlex.split(command)
else:
eprint(f"running {' '.join(command)}")
if not quiet:
eprint(f"running {' '.join(command)}")
result = subprocess.run(
command,

View File

@ -0,0 +1,64 @@
#!/usr/bin/env python3
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
import sys
import os
from diff_lib import get_cmd_output, get_cmd_status, eprint, running_in_docker_build, checkout_commit_and_generate, \
OUTPUT_PATH
CURRENT_BRANCH = 'current'
BASE_BRANCH = 'base'
# This script runs `cargo semver-checks` against a previous version of codegen
def main(skip_generation=False):
if len(sys.argv) != 3:
eprint("Usage: semver-checks.py <repository root> <base commit sha>")
sys.exit(1)
repository_root = sys.argv[1]
base_commit_sha = sys.argv[2]
os.chdir(repository_root)
(_, head_commit_sha, _) = get_cmd_output("git rev-parse HEAD")
# Make sure the working tree is clean
if get_cmd_status("git diff --quiet") != 0:
eprint("working tree is not clean. aborting")
sys.exit(1)
if not skip_generation:
checkout_commit_and_generate(head_commit_sha, CURRENT_BRANCH, targets=['aws:sdk'])
checkout_commit_and_generate(base_commit_sha, BASE_BRANCH, targets=['aws:sdk'])
get_cmd_output(f'git checkout {CURRENT_BRANCH}')
sdk_directory = os.path.join(OUTPUT_PATH, 'aws-sdk', 'sdk')
os.chdir(sdk_directory)
failed = False
for path in os.listdir():
eprint(f'checking {path}...', end='')
if get_cmd_status(f'git cat-file -e base:{sdk_directory}/{path}/Cargo.toml') == 0:
(status, out, err) = get_cmd_output(f'cargo semver-checks check-release '
f'--baseline-rev {BASE_BRANCH} '
# in order to get semver-checks to work with publish-false crates, need to specify
# package and manifest path explicitly
f'--manifest-path {path}/Cargo.toml '
f'-p {path} '
f'--release-type patch', check=False, quiet=True)
if status == 0:
eprint('ok!')
else:
failed = True
eprint('failed!')
if out:
eprint(out)
eprint(err)
else:
eprint(f'skipping {path} because it does not exist in base')
if failed:
eprint('One or more crates failed semver checks!')
exit(1)
if __name__ == "__main__":
skip_generation = bool(os.environ.get('SKIP_GENERATION') or False)
main(skip_generation=skip_generation)