Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 31 additions & 3 deletions .github/workflows/moq-release.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
# Publishes moq-noq-proto, moq-noq-udp, moq-noq, and web-transport-moq when a `v*` tag
# is pushed. The tag must match `workspace.package.version`.
#
# Crates already on crates.io are skipped, so a run that stopped partway can be finished
# by dispatching this workflow with the same tag.
#
# Uses crates.io trusted publishing, so each crate must list this repository
# and workflow as a trusted publisher. The very first version of a crate has to
# be published with a token from a maintainer's machine.
Expand All @@ -10,28 +13,53 @@ on:
push:
tags:
- "v*"
workflow_dispatch:
inputs:
tag:
description: Existing tag to publish, such as v1.3.2
required: true

permissions:
contents: read

jobs:
publish:
runs-on: ubuntu-latest
timeout-minutes: 30
# Room for every crate's index wait below.
timeout-minutes: 60
environment: release
permissions:
id-token: write
env:
TAG: ${{ inputs.tag || github.ref_name }}
steps:
- uses: actions/checkout@v6
with:
ref: refs/tags/${{ env.TAG }}
persist-credentials: false
- uses: dtolnay/rust-toolchain@stable
- name: Tag matches the workspace version
run: |
version=$(cargo metadata --format-version=1 --no-deps | jq -r '.packages[] | select(.name == "moq-noq") | .version')
test "v$version" = "${GITHUB_REF_NAME}" || { echo "tag ${GITHUB_REF_NAME} but Cargo.toml says $version"; exit 1; }
test "v$version" = "$TAG" || { echo "tag $TAG but Cargo.toml says $version"; exit 1; }
- uses: rust-lang/crates-io-auth-action@v1
id: auth
- run: cargo publish --workspace --locked
# One crate at a time, in dependency order. Cargo waits only 60s for a published crate
# to reach the index (longer needs a nightly flag), and the next crate cannot build
# until it does, so wait here instead.
- name: Publish
env:
CARGO_REGISTRY_TOKEN: ${{ steps.auth.outputs.token }}
run: |
version=${TAG#v}
for crate in moq-noq-proto moq-noq-udp moq-noq web-transport-moq; do
# Sparse index path for names of four or more characters.
listed() { curl -sf "https://index.crates.io/${crate:0:2}/${crate:2:2}/$crate" | grep -qF "\"vers\":\"$version\""; }
if listed; then
echo "$crate $version is already published"
continue
fi
cargo publish -p "$crate" --locked
for _ in $(seq 60); do listed && break; sleep 10; done

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Allow the job to cover all four index waits

If three or four crates take close to the configured ten-minute allowance to appear in the index, these per-crate loops can require up to 40 minutes before accounting for publishing, but the publish job still has a 30-minute timeout. GitHub will therefore terminate a valid fresh release during the third or fourth wait; increase the job timeout with suitable headroom or enforce an aggregate wait that fits within it.

Useful? React with 馃憤聽/ 馃憥.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 22776ca: the job timeout is now 60 minutes, which covers the waits. Indexing normally takes seconds, and a run that is cut off can now be finished by dispatching again.

(Written by Claude Opus 5.5)

listed || { echo "$crate $version is not in the index after 10 minutes"; exit 1; }
done
Loading