name: Release
on:
push:
tags:
- "v*"
workflow_dispatch:
permissions:
actions: read
contents: write
jobs:
release:
runs-on: ubuntu-latest
permissions:
actions: read
contents: write
id-token: write
steps:
- uses: actions/checkout@v5
- name: Wait for CI to pass for this commit
uses: actions/github-script@v7
with:
script: |
const sha = context.sha;
const owner = context.repo.owner;
const repo = context.repo.repo;
const workflowName = "CI";
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
const maxAttempts = 40;
const delayMs = 15000;
for (let i = 1; i <= maxAttempts; i++) {
const runs = await github.paginate(github.rest.actions.listWorkflowRunsForRepo, {
owner,
repo,
event: "push",
per_page: 100,
});
const ciRun = runs.find(
(r) =>
r.name === workflowName &&
r.head_sha === sha
);
if (!ciRun) {
core.info(`Attempt ${i}/${maxAttempts}: CI run not found yet for ${sha}.`);
await sleep(delayMs);
continue;
}
core.info(
`Attempt ${i}/${maxAttempts}: CI run ${ciRun.id} status=${ciRun.status} conclusion=${ciRun.conclusion}`
);
if (ciRun.status !== "completed") {
await sleep(delayMs);
continue;
}
if (ciRun.conclusion !== "success") {
core.setFailed(`CI workflow concluded with '${ciRun.conclusion}'. Aborting release.`);
return;
}
core.info("CI passed for this commit. Proceeding with release.");
return;
}
core.setFailed("Timed out waiting for CI workflow completion.");
- name: Install Rust
run: rustup toolchain install stable
- name: Authenticate to crates.io with trusted publishing
id: auth
uses: rust-lang/crates-io-auth-action@v1
- name: Publish to crates.io
run: cargo publish
env:
CARGO_REGISTRY_TOKEN: ${{ steps.auth.outputs.token }}
- name: Create GitHub release
uses: softprops/action-gh-release@v3
with:
generate_release_notes: true
prerelease: ${{ contains(github.ref, '-') }}