diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 5e591ae..6341c23 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -56,23 +56,37 @@ jobs: fi echo "publishing dtg-credentials ${crate}" - - name: Authenticate to crates.io - uses: rust-lang/crates-io-auth-action@v1 - id: auth - - - name: Publish - env: - CARGO_REGISTRY_TOKEN: ${{ steps.auth.outputs.token }} + # Before authenticating, not after. The skip is what makes a re-pushed tag + # recoverable, and it cannot do that job from behind the auth step: the + # v0.6.0 tag push found 0.6.0 already on crates.io (published by hand + # minutes earlier) and still failed, because it never got past + # "No Trusted Publishing config found" to reach the check that would have + # said there was nothing to do. A step that decides whether to act should + # not sit downstream of acquiring the means to act. + - name: Skip if this version is already published + id: check run: | set -euo pipefail version=$(cargo metadata --no-deps --format-version 1 | jq -r '.packages[0].version') + echo "version=${version}" >> "$GITHUB_OUTPUT" # The sparse index is newline-delimited JSON, one object per version. # A 404 (name never published) is a clean "not there". if curl -sSf "https://index.crates.io/dt/g-/dtg-credentials" 2>/dev/null \ | jq -se --arg v "$version" 'any(.[]; .vers == $v)' >/dev/null; then echo "::notice::dtg-credentials ${version} is already on crates.io — nothing to do" - exit 0 + echo "published=true" >> "$GITHUB_OUTPUT" + else + echo "published=false" >> "$GITHUB_OUTPUT" fi - cargo publish --locked + - name: Authenticate to crates.io + if: steps.check.outputs.published == 'false' + uses: rust-lang/crates-io-auth-action@v1 + id: auth + + - name: Publish + if: steps.check.outputs.published == 'false' + env: + CARGO_REGISTRY_TOKEN: ${{ steps.auth.outputs.token }} + run: cargo publish --locked