Merge pull request #114 from ecmwf/chore/release-0.9.1 #14
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Publish Crate | |
| on: | |
| push: | |
| tags: | |
| - '*' | |
| workflow_dispatch: | |
| inputs: | |
| dry_run: | |
| description: "Dry-run only (no actual publish)" | |
| required: false | |
| type: boolean | |
| default: true | |
| jobs: | |
| verify-tag: | |
| if: ${{ github.event_name == 'push' || github.event_name == 'workflow_dispatch' }} | |
| runs-on: ubuntu-latest | |
| outputs: | |
| should_publish: ${{ steps.check.outputs.should_publish }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Verify tag matches crate versions | |
| id: check | |
| run: | | |
| set -euo pipefail | |
| server_version=$(grep '^version\s*=' Cargo.toml | head -1 | cut -d'"' -f2) | |
| validators_version=$(grep '^version\s*=' aviso-validators/Cargo.toml | head -1 | cut -d'"' -f2) | |
| ecpds_version=$(grep '^version\s*=' aviso-ecpds/Cargo.toml | head -1 | cut -d'"' -f2) | |
| if [ -z "${server_version}" ] || [ -z "${validators_version}" ] || [ -z "${ecpds_version}" ]; then | |
| echo "::error::Could not extract crate versions from Cargo manifests" | |
| exit 1 | |
| fi | |
| # All three crates must move in lockstep. A divergent version is | |
| # almost always an accidental partial bump in a PR rather than an | |
| # intentional independent release; failing loud here catches it | |
| # at tag-push time rather than after a half-finished publish. | |
| if [ "${server_version}" != "${validators_version}" ] || [ "${server_version}" != "${ecpds_version}" ]; then | |
| echo "::error::Crate versions are not in lockstep: server=${server_version}, validators=${validators_version}, ecpds=${ecpds_version}" | |
| echo "should_publish=false" >> "$GITHUB_OUTPUT" | |
| exit 1 | |
| fi | |
| if [ "${{ github.event_name }}" = "workflow_dispatch" ] && [ "${{ inputs.dry_run }}" != "true" ]; then | |
| echo "::error::Manual non-dry-run publishing is disabled. Create and push a matching release tag to publish." | |
| echo "should_publish=false" >> "$GITHUB_OUTPUT" | |
| exit 1 | |
| fi | |
| if [ "${{ github.event_name }}" = "workflow_dispatch" ] && [ "${{ inputs.dry_run }}" = "true" ]; then | |
| echo "should_publish=true" >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| fi | |
| # Accept both `0.4.1` and `v0.4.1` git tags; strip leading `v` | |
| # before comparing to the Cargo manifest versions. | |
| pushed_tag="${{ github.ref_name }}" | |
| normalized_tag="${pushed_tag#v}" | |
| if [ "${normalized_tag}" = "${server_version}" ]; then | |
| echo "should_publish=true" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "Tag ${pushed_tag} (normalized: ${normalized_tag}) does not match crate version ${server_version}, skipping." | |
| echo "should_publish=false" >> "$GITHUB_OUTPUT" | |
| fi | |
| publish-validators: | |
| needs: verify-tag | |
| if: ${{ needs.verify-tag.outputs.should_publish == 'true' }} | |
| runs-on: ubuntu-latest | |
| env: | |
| CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Install Rust stable | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Publish aviso-validators | |
| run: | | |
| set -euo pipefail | |
| ERR_FILE="${RUNNER_TEMP}/publish-validators.err" | |
| if [ "${{ github.event_name }}" = "workflow_dispatch" ] && [ "${{ inputs.dry_run }}" = "true" ]; then | |
| cargo publish --manifest-path aviso-validators/Cargo.toml --dry-run | |
| else | |
| if cargo publish --manifest-path aviso-validators/Cargo.toml 2>"${ERR_FILE}"; then | |
| exit 0 | |
| fi | |
| if grep -q 'already exists on crates.io index' "${ERR_FILE}"; then | |
| echo "aviso-validators is already published for this version; continuing." | |
| exit 0 | |
| fi | |
| cat "${ERR_FILE}" >&2 | |
| exit 1 | |
| fi | |
| publish-ecpds: | |
| needs: verify-tag | |
| if: ${{ needs.verify-tag.outputs.should_publish == 'true' }} | |
| runs-on: ubuntu-latest | |
| env: | |
| CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Install Rust stable | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Publish aviso-ecpds | |
| run: | | |
| set -euo pipefail | |
| ERR_FILE="${RUNNER_TEMP}/publish-ecpds.err" | |
| if [ "${{ github.event_name }}" = "workflow_dispatch" ] && [ "${{ inputs.dry_run }}" = "true" ]; then | |
| cargo publish --manifest-path aviso-ecpds/Cargo.toml --dry-run | |
| else | |
| if cargo publish --manifest-path aviso-ecpds/Cargo.toml 2>"${ERR_FILE}"; then | |
| exit 0 | |
| fi | |
| if grep -q 'already exists on crates.io index' "${ERR_FILE}"; then | |
| echo "aviso-ecpds is already published for this version; continuing." | |
| exit 0 | |
| fi | |
| cat "${ERR_FILE}" >&2 | |
| exit 1 | |
| fi | |
| publish-server: | |
| needs: [publish-validators, publish-ecpds] | |
| if: ${{ needs.publish-validators.result == 'success' && needs.publish-ecpds.result == 'success' }} | |
| runs-on: ubuntu-latest | |
| env: | |
| CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Install Rust stable | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Publish aviso-server | |
| run: | | |
| set -euo pipefail | |
| ERR_FILE="${RUNNER_TEMP}/publish-server.err" | |
| if [ "${{ github.event_name }}" = "workflow_dispatch" ] && [ "${{ inputs.dry_run }}" = "true" ]; then | |
| cargo publish --manifest-path Cargo.toml --dry-run | |
| exit 0 | |
| fi | |
| for attempt in 1 2 3 4 5 6 7 8 9 10; do | |
| if cargo publish --manifest-path Cargo.toml 2>"${ERR_FILE}"; then | |
| exit 0 | |
| fi | |
| # crates.io index propagation can lag in two shapes, and | |
| # every alternative below MUST be scoped to the aviso | |
| # leaf crates so an unrelated dependency-resolution error | |
| # (e.g. a real bug in a serde or tokio version pin) does | |
| # not get mistaken for index lag and silently retried for | |
| # 5 minutes: | |
| # | |
| # shape A (first publish only): the leaf crate does not | |
| # exist on the registry at all yet -- "no matching | |
| # package named `aviso-X` found" / "failed to get | |
| # `aviso-X` as a dependency". | |
| # | |
| # shape B (every subsequent release): the leaf crate | |
| # exists, but the specific new version just pushed by | |
| # the previous job has not propagated to the index -- | |
| # "failed to select a version for the requirement | |
| # `aviso-X = ...`". Cargo also emits a "candidate | |
| # versions found which didn't match" continuation | |
| # line for shape B, but that line is NOT scoped to a | |
| # crate name and fires for any version-selection | |
| # failure, so it is intentionally NOT in the regex. | |
| # The "failed to select a version" line above always | |
| # co-emits, so shape B coverage is preserved. | |
| # | |
| # Each crate-name alternative uses `.?` to match an | |
| # optional opening quote/backtick/space character rather | |
| # than encoding cargo's current backtick style, so the | |
| # regex survives a future cargo output tweak. | |
| if grep -Eq '(no matching package named|failed to get|failed to select a version for the requirement) .?aviso-(validators|ecpds)|download of config\.json failed|spurious network error|Could not resolve host: index\.crates\.io' "${ERR_FILE}"; then | |
| echo "Dependency/index not ready yet (attempt ${attempt}/10); retrying in 30s..." | |
| sleep 30 | |
| continue | |
| fi | |
| cat "${ERR_FILE}" >&2 | |
| exit 1 | |
| done | |
| cat "${ERR_FILE}" >&2 | |
| echo "Timed out waiting for aviso-validators / aviso-ecpds to become available on crates.io." >&2 | |
| exit 1 |