diff --git a/README.md b/README.md index 6b34840..42f389d 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,7 @@ jobs: | ---- | ---- | ----------- | | [rust-cache] | Action | Caches dependencies, install artifacts, and build artifacts in Rust projects. | | [rust-set-rust-version] | Workflow | Updates the rust-version in Rust crates to the latest stable version. | +| [rust-check-git-rev-deps] | Workflow | Check that git rev dependencies do not reference revisions likely to be orphaned. | #### Releasing / Publishing diff --git a/rust-check-git-rev-deps/README.md b/rust-check-git-rev-deps/README.md new file mode 100644 index 0000000..c481d61 --- /dev/null +++ b/rust-check-git-rev-deps/README.md @@ -0,0 +1,18 @@ +# rust-check-git-rev-deps Action + +The rust-check-git-rev-deps action checks that `git` dependencies that are +versioned by a commit sha are not referring to a commit that is likely to become +orphaned. + +Commits are accepted by the check if they can be found in one of: +- The history of the default branch of the repository. +- The history of a tag of the repository. + +## Usage + +```yml +jobs: + my_job: + steps: + - uses: stellar/actions/rust-check-git-rev-deps@main +``` diff --git a/rust-check-git-rev-deps/action.yml b/rust-check-git-rev-deps/action.yml new file mode 100644 index 0000000..70bdbee --- /dev/null +++ b/rust-check-git-rev-deps/action.yml @@ -0,0 +1,7 @@ +name: 'Rust Check Git Rev Deps' +description: 'Check that git revision dependencies are unlikely to be orphaned' +runs: + using: "composite" + steps: + - shell: bash + run: ${{ github.action_path }}/check.sh diff --git a/rust-check-git-rev-deps/check.sh b/rust-check-git-rev-deps/check.sh new file mode 100755 index 0000000..8d90b24 --- /dev/null +++ b/rust-check-git-rev-deps/check.sh @@ -0,0 +1,41 @@ +#!/usr/bin/env bash + +set -o errexit +set -o pipefail +set -o nounset + +# Get repo and sha's of all dependencies in the current cargo workspace that are +# git references containing a revision/commit sha. +cargo metadata --format-version 1 --no-deps \ + | jq -r '[.packages[].dependencies] | flatten | [.[] | .source | select(. != null) | select(. | startswith("git+")) | select(. | contains("?rev=")) | sub("^git\\+"; "") | split("?rev=")] | unique | sort | .[] | @tsv' \ + | { + fails=0 + while IFS=$'\t' read -r repo sha; do + # For each, clone the repo, checkout the default branch and tags, and check + # that the commit can be found in at least one of them. + temp=$(mktemp -d) + echo -e "\033[1;34mChecking "$repo" @ "$sha"\033[0m" + git clone "$repo" "$temp" + pushd "$temp" + found=0 + for ref in . $(git tag); do + git -c advice.detachedHead=false checkout "$ref" + desc="$(git describe --all)" + echo -e "\033[1;33mChecking is in "$desc"\033[0m" + if git merge-base --is-ancestor "$sha" HEAD; then + echo -e "\033[1;32mCommit is in the history of $desc.\033[0m" + found=1 + else + echo -e "Commit is NOT in the history of $desc." + fi + done + if (( $found == 0 )); then + fails=1 + fi + popd + done + if (( $fails > 0 )); then + echo -e "\033[1;31mDependency revisions must reference a version of the dependency that is on the default branch, or a tag, so that they do not become orphaned.\033[0m" + exit 1 + fi + }