diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 342fdcc743f..c522a19a1f2 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -51,6 +51,18 @@ jobs: - run: rustup update stable && rustup default stable - run: cargo update -p cargo --locked + check-version-bump: + runs-on: ubuntu-latest + env: + BASE_SHA: ${{ github.event.pull_request.base.sha }} + HEAD_SHA: ${{ github.sha }} + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 # make `git diff` work + - run: rustup update stable && rustup default stable + - run: ci/validate-version-bump.sh + test: runs-on: ${{ matrix.os }} env: diff --git a/ci/validate-version-bump.sh b/ci/validate-version-bump.sh new file mode 100755 index 00000000000..9b54fdaaf76 --- /dev/null +++ b/ci/validate-version-bump.sh @@ -0,0 +1,61 @@ +#!/bin/bash +# This script checks if a crate needs a version bump. +# +# At the time of writing, it doesn't check what kind of bump is required. +# In the future, we could take SemVer compatibliity into account, like +# integrating `cargo-semver-checks` of else +# +# Inputs: +# BASE_SHA The commit SHA of the branch where the PR wants to merge into. +# HEAD_SHA The commit SHA that triggered the workflow. + +set -euo pipefail + +# When `BASE_SHA` is missing, we assume it is from bors merge commit, +# so hope `HEAD~` to find the previous commit on master branch. +base_sha=$(git rev-parse "${BASE_SHA:-HEAD~1}") +head_sha=$(git rev-parse "${HEAD_SHA:-HEAD}") + +echo "Base branch is $base_sha" +echo "Current head is $head_sha" + +# Gets crate names of members that has been changed from $bash_sha to $head_sha. +changed_crates=$( + git diff --name-only "$base_sha" "$head_sha" -- crates/ credential/ benches/ \ + | cut -d'/' -f2 \ + | sort -u +) + +if [ -z "$changed_crates" ] +then + echo "No file changed in member crates." + exit 0 +fi + +# Checks publish status for only crates with code changes. +publish_status_table=$( + echo "$changed_crates" \ + | xargs printf -- '--package %s\n' \ + | xargs cargo unpublished +) + +# "yes" -> code changed but no version difference -> need a bump +# Prints 2nd column (sep by space), which is the name of the crate. +crates_need_bump=$( + echo "$publish_status_table" \ + | { grep '| yes ' || true; } \ + | awk '{print $2}' +) + +if [ -z "$crates_need_bump" ] +then + echo "No version bump needed for member crates." + exit 0 +fi + +echo "Detected changes in these crates but no version bump found:" +echo "$crates_need_bump" +echo +echo "Please bump at least one patch version for each corresponding Cargo.toml:" +echo 'Run "cargo unpublished" to read the publish status table for details.' +exit 1 diff --git a/crates/xtask-unpublished/src/xtask.rs b/crates/xtask-unpublished/src/xtask.rs index aa47f86d0c0..f1086951f8a 100644 --- a/crates/xtask-unpublished/src/xtask.rs +++ b/crates/xtask-unpublished/src/xtask.rs @@ -1,3 +1,9 @@ +//! `xtask-unpublished` outputs a table with publish status --- a local version +//! and a version on crates.io for comparisons. +//! +//! This aims to help developers check if there is any crate required a new +//! publish, as well as detect if a version bump is needed in CI pipeline. + use std::collections::HashSet; use cargo::core::registry::PackageRegistry;