name: Check semver on: workflow_dispatch: concurrency: group: check-semver-${{ github.event.pull_request.number || github.ref }} cancel-in-progress: true env: TOOLCHAIN: nightly-2025-05-09 jobs: isdraft: uses: ./.github/workflows/reusable-isdraft.yml preflight: needs: isdraft uses: ./.github/workflows/reusable-preflight.yml check-semver: runs-on: ubuntu-latest timeout-minutes: 90 needs: [preflight] container: image: ${{ needs.preflight.outputs.IMAGE }} steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v4.1.7 with: fetch-depth: 2 - name: extra git setup run: | git config --global --add safe.directory '*' git branch old HEAD^1 - name: Comment If Backport if: ${{ startsWith(github.event.pull_request.base.ref, 'stable') }} env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} PR: ${{ github.event.pull_request.number }} run: | echo "This is a backport into stable." cat > msg.txt <Emergency Bypass

If you really need to bypass this check: add validate: false to each crate in the Prdoc where a breaking change is introduced. This will release a new major version of that crate and all its reverse dependencies and basically break the release.

EOF gh issue comment $PR --edit-last -F msg.txt || gh issue comment $PR -F msg.txt echo "PRDOC_EXTRA_ARGS=--max-bump minor" >> $GITHUB_ENV - name: Rust Cache uses: Swatinem/rust-cache@f13886b937689c021905a6b90929199931d60db1 # v2.8.1 with: save-if: ${{ github.ref == 'refs/heads/master' }} - name: Rust compilation prerequisites run: | rustup default $TOOLCHAIN rustup target add wasm32-unknown-unknown --toolchain $TOOLCHAIN rustup component add rust-src --toolchain $TOOLCHAIN - name: Install pezkuwi-publish # Set the target dir to cache the build. run: CARGO_TARGET_DIR=./target/ cargo install pezkuwi-publish@0.10.6 --locked -q - name: Get original PR number shell: bash if: ${{ github.ref != 'refs/heads/master' }} env: PR_TITLE: ${{ github.event.pull_request.title }} run: | . ./.github/scripts/common/lib.sh original_pr_number='' echo "Checking PR title: $PR_TITLE" if [[ "$PR_TITLE" =~ 'Backport' ]]; then # Extracting the original PR number from the backport's PR title original_pr_number=$(extract_pr_number_from_pr_title "$PR_TITLE") echo "Extracted PR number: $original_pr_number" else original_pr_number=${{ github.event.pull_request.number }} fi echo "PR_NUMBER=$original_pr_number" >> $GITHUB_ENV - name: Check semver if: ${{ github.ref != 'refs/heads/master' }} shell: bash env: PRDOC_EXTRA_ARGS: ${{ env.PRDOC_EXTRA_ARGS }} PR: ${{ env.PR_NUMBER }} BASE_BRANCH: ${{ github.event.pull_request.base.ref }} PR_LABELS: ${{ toJson(github.event.pull_request.labels.*.name) }} run: | if [ -z "$PR" ]; then echo "Skipping master/merge queue" exit 0 fi # Skip semver check if PR targets stable branch and has R0-no-crate-publish-require label if [[ "$BASE_BRANCH" =~ ^stable[0-9]{4}$ ]]; then if echo "$PR_LABELS" | grep -q "R0-no-crate-publish-require"; then echo "â„šī¸ Skipping the SemVer check is not recommended and should only be done in rare cases: PR targets stable branch '$BASE_BRANCH' and has 'R0-no-crate-publish-require' label." exit 0 fi fi export CARGO_TARGET_DIR=target export RUSTFLAGS='-A warnings -A missing_docs' export SKIP_WASM_BUILD=1 prdoc_file="prdoc/pr_$PR.prdoc" # Always run pezkuwi-publish to check for all issues (mismatches and missing crates) # Capture output to check for specific error types parity_output=$(mktemp) if ! pezkuwi-publish --color always prdoc --since old --validate prdoc/pr_$PR.prdoc $PRDOC_EXTRA_ARGS -v --toolchain $TOOLCHAIN 2>&1 | tee "$parity_output"; then # Check if there are missing crates (files changed but not listed in prdoc) if grep -q "Files changed but crate not listed in PR Doc" "$parity_output"; then rm -f "$parity_output" cat < "$minor_patch_temp" has_validate_false=false while read -r line; do if [[ "$line" =~ bump:[[:space:]]*(minor|patch) ]]; then read -r next_line || true if [[ "$next_line" =~ validate:[[:space:]]*false ]]; then has_validate_false=true break fi fi done < "$minor_patch_temp" rm -f "$minor_patch_temp" if [ "$has_validate_false" = true ]; then echo "â„šī¸ Found minor/patch bumps with validate: false override. Semver validation was skipped for these crates by pezkuwi-publish." fi fi # Check if there are any major bumps if ! grep -q "bump:[[:space:]]*major" "$prdoc_file"; then echo "✅ All semver changes in backport are valid (minor, patch, or none)." exit 0 fi # Process each major bump and check the next line temp_file=$(mktemp) grep -A1 "bump:[[:space:]]*major" "$prdoc_file" > "$temp_file" error_found=false while IFS= read -r line; do if [[ "$line" =~ bump:[[:space:]]*major ]]; then # This is the bump line, read the next line if IFS= read -r next_line; then if [[ "$next_line" =~ validate:[[:space:]]*false ]]; then continue # This major bump is properly validated else error_found=true break fi else # No next line, means no validate: false error_found=true break fi fi done < "$temp_file" rm -f "$temp_file" if [ "$error_found" = true ]; then echo "❌ Error: Found major bump without 'validate: false'" echo "📘 See: https://github.com/pezkuwichain/pezkuwi-sdk/blob/master/docs/contributor/prdoc.md#backporting-prs" echo "🔧 Add 'validate: false' after the major bump in $prdoc_file with justification." exit 1 fi # If we reach here, all major bumps have validate: false echo "âš ī¸ Backport contains major bumps, but they are all marked with validate: false." echo "✅ Semver override accepted. Please ensure justification is documented in the PR description."