name: PublishCrates
on:
workflow_call:
inputs:
plan:
required: true
type: string
jobs:
cargo-publish:
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
steps:
- name: Checkout sources
uses: actions/checkout@v6
with:
submodules: recursive
- name: Authenticate with crates.io
id: auth
uses: rust-lang/crates-io-auth-action@v1
- name: Publish crates
run: |
set -euo pipefail
version_of() {
cargo pkgid -p "$1" | sed -E 's/.*[#@]//'
}
crate_exists() {
local crate="$1"
local version="$2"
local status
status="$(curl \
--silent \
--show-error \
--output /dev/null \
--write-out "%{http_code}" \
--user-agent "rustcodegraph-release-ci" \
"https://crates.io/api/v1/crates/${crate}/${version}")"
case "${status}" in
200) return 0 ;;
404) return 1 ;;
*)
echo "Unexpected crates.io response for ${crate} ${version}: HTTP ${status}" >&2
return 2
;;
esac
}
wait_for_crate() {
local crate="$1"
local version="$2"
for _ in {1..30}; do
if crate_exists "${crate}" "${version}"; then
return 0
fi
sleep 10
done
echo "Timed out waiting for ${crate} ${version} to appear on crates.io" >&2
return 1
}
publish_crate() {
local crate="$1"
local version
version="$(version_of "${crate}")"
if crate_exists "${crate}" "${version}"; then
echo "${crate} ${version} is already published; skipping"
return 0
fi
cargo publish -p "${crate}" --locked
wait_for_crate "${crate}" "${version}"
}
publish_crate rustcodegraph
env:
CARGO_REGISTRY_TOKEN: ${{ steps.auth.outputs.token }}