Skip to content

Commit f45887e

Browse files
authored
Merge pull request #909 from scylladb/semver-checks
Semver checks
2 parents e3ae2cd + f6d68d3 commit f45887e

File tree

4 files changed

+155
-0
lines changed

4 files changed

+155
-0
lines changed
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
# This workflow tests semver compatibilty.
2+
# For PRs it checks if PR makes any API breaking changes, and assings appropriate label if so.
3+
name: Semver checks
4+
5+
on:
6+
pull_request_target:
7+
branches:
8+
- main
9+
- 'branch-*'
10+
push:
11+
tags:
12+
- v*.*.*
13+
14+
env:
15+
CARGO_TERM_COLOR: always
16+
RUST_BACKTRACE: full
17+
PR_BASE: ${{ github.event.pull_request.base.sha }}
18+
PR_HEAD: ${{ github.event.pull_request.head.sha }}
19+
PR_ID: ${{ github.event.number }}
20+
21+
jobs:
22+
semver-pull-request-check:
23+
runs-on: ubuntu-latest
24+
if: github.event_name == 'pull_request_target'
25+
# Disable all permissions
26+
# This is important, because this job runs on untrusted input from
27+
# the user and it's possible for the user to take over the job,
28+
# for example by adding malicious build.rs file. If the job had,
29+
# for example, `pull_requests: write` permission, malicous user
30+
# could do us a lot of harm. This is also the reason that there are
31+
# 2 jobs - it's so that it's not possible to take over a job that
32+
# has permissions.
33+
permissions: {}
34+
timeout-minutes: 30
35+
# This is to prevent a situation, when job A triggered by push 1 finishes
36+
# after job B triggered by push 2. That could result in incorrectly assigning
37+
# or removing a PR label.
38+
concurrency:
39+
# Can't use `env.PR_ID` because concurrency doesn't have access to env context.
40+
group: semver-pull-request-check-${{ github.event.number }}
41+
cancel-in-progress: true
42+
outputs:
43+
exitcode: ${{ steps.semver-pr-check.outputs.exitcode }}
44+
output: ${{ steps.semver-pr-check.outputs.output }}
45+
steps:
46+
- name: Checkout
47+
uses: actions/checkout@v3
48+
with:
49+
fetch-depth: "2"
50+
ref: "refs/pull/${{ env.PR_ID }}/merge"
51+
# Check if there was another push before this job started.
52+
# If there was, wrong commit would be checked out.
53+
- name: Sanity check
54+
run: |
55+
[[ "$(git rev-parse 'HEAD^2')" == "$PR_HEAD" ]]
56+
# I don't know any way to do this using checkout action
57+
- name: Fetch PR base
58+
run: git fetch origin "$PR_BASE"
59+
- name: Install semver-checks
60+
# Official action uses binary releases fetched from GitHub
61+
# If this pipeline becomes too slow, we should do this too
62+
run: cargo install cargo-semver-checks --no-default-features
63+
- name: Verify the API compatibilty with PR base
64+
id: semver-pr-check
65+
run: |
66+
set +e
67+
echo "output<<SEMVER_STDOUT_EOF" >> $GITHUB_OUTPUT
68+
# Weird sed strip ANSI colors from output
69+
make semver-rev rev="$PR_BASE" |& tee /dev/tty | sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[mGK]//g" >> $GITHUB_OUTPUT
70+
exitcode=${PIPESTATUS[0]}
71+
echo "SEMVER_STDOUT_EOF" >> $GITHUB_OUTPUT
72+
echo "exitcode=$exitcode" >> $GITHUB_OUTPUT
73+
exit "$exitcode"
74+
continue-on-error: true
75+
76+
semver-pull-request-label:
77+
runs-on: ubuntu-latest
78+
if: github.event_name == 'pull_request_target'
79+
permissions:
80+
pull-requests: write
81+
needs: semver-pull-request-check
82+
timeout-minutes: 3
83+
steps:
84+
- name: Remove breaking label on success
85+
run: gh pr edit "$PR_ID" --remove-label semver-checks-breaking
86+
if: needs.semver-pull-request-check.outputs.exitcode == '0'
87+
env:
88+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
89+
GH_REPO: ${{ github.repository }}
90+
- name: Add breaking label on failure
91+
run: gh pr edit "$PR_ID" --add-label semver-checks-breaking
92+
if: needs.semver-pull-request-check.outputs.exitcode != '0'
93+
env:
94+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
95+
GH_REPO: ${{ github.repository }}
96+
- name: Post report on semver break
97+
run: |
98+
gh pr comment "$PR_ID" --body "\
99+
\`cargo semver-checks\` detected some API incompatibilities in this PR.
100+
See the following report for details:
101+
<details>
102+
<summary>cargo semver-checks output</summary>
103+
104+
\`\`\`
105+
$SEMVER_OUTPUT
106+
\`\`\`
107+
108+
</details>
109+
"
110+
if: needs.semver-pull-request-check.outputs.exitcode != '0'
111+
env:
112+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
113+
GH_REPO: ${{ github.repository }}
114+
SEMVER_OUTPUT: ${{ needs.semver-pull-request-check.outputs.output }}
115+
116+
117+
semver-push-tag:
118+
runs-on: ubuntu-latest
119+
if: github.event_name == 'push'
120+
timeout-minutes: 30
121+
steps:
122+
- uses: actions/checkout@v3
123+
- name: Install semver-checks
124+
run: cargo install cargo-semver-checks --no-default-features
125+
- name: Run semver-checks to see if it agrees with version updates
126+
run: make semver-version

CONTRIBUTING.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,22 @@ There are a few scenarios:
8686
using command like `cargo update -p toml_datetime --precise 0.6.3` and go back to step 3.
8787
5. Rename `Cargo.lock` to `Cargo.lock.msrv`.
8888

89+
### Semver checking
90+
91+
Our CI runs cargo semver-checks and labels PRs that introduce breaking changes.
92+
If you don't intend to change public API, you can perform the checks locally,
93+
using command `make semver-rev`. Make sure you have semver-checks installed first,
94+
you can install it using `cargo install cargo-semver-checks`.
95+
96+
`make semver-rev` will check for API breaking changes using `main` branch as baseline.
97+
To use different branch / commit call `make semver-rev rev=BRANCH`.
98+
99+
The tool is NOT perfect and only checks some aspect of semver-compatibility.
100+
It is NOT a replacement for a human reviewer, it is only supposed to help them
101+
and catch some erros that they might have missed.
102+
103+
Tool that we curently use: https://github.com/obi1kenobi/cargo-semver-checks
104+
89105
## Contributing to the book
90106

91107
The documentation book is written using [mdbook](https://github.com/rust-lang/mdBook)\

Makefile

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,14 @@ build:
4848
docs:
4949
mdbook build docs
5050

51+
.PHONY: semver-rev
52+
semver-rev:
53+
./scripts/semver-checks.sh $(if $(rev),--baseline-rev $(rev),--baseline-rev main)
54+
55+
.PHONY: semver-version
56+
semver-version:
57+
./scripts/semver-checks.sh $(if $(version),--baseline-version $(version),)
58+
5159
.PHONY: up
5260
up:
5361
$(COMPOSE) up -d --wait

scripts/semver-checks.sh

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#!/bin/sh
2+
3+
set -x
4+
5+
cargo semver-checks -p scylla -p scylla-cql $@

0 commit comments

Comments
 (0)