diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..744e32d --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,49 @@ +name: Publish + +# Publish the owid crate to crates.io when main changes. The job only publishes +# when the version in Cargo.toml is not already on crates.io, so an ordinary +# push to main (docs, tests, a fix that does not bump the version) is a no-op. +# To release a new version, bump `version` in Cargo.toml and merge to main. + +on: + push: + branches: [main] + +# Never let two publish runs race; a second push waits for the first to finish. +concurrency: + group: publish-crates-io + cancel-in-progress: false + +jobs: + publish: + name: publish to crates.io + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + + # Verify the crate before publishing so a broken main never publishes. + - run: cargo test --all-features + + - name: Check whether this version is already on crates.io + id: check + run: | + version="$(cargo metadata --no-deps --format-version 1 \ + | jq -r '.packages[0].version')" + echo "version=$version" >> "$GITHUB_OUTPUT" + # The crates.io API returns 200 for a published version and 404 + # otherwise. A User-Agent is required by the API. + if curl -sf -H "User-Agent: owid-publish (github actions)" \ + "https://crates.io/api/v1/crates/owid/$version" > /dev/null; then + echo "owid $version is already on crates.io; nothing to publish." + echo "publish=false" >> "$GITHUB_OUTPUT" + else + echo "owid $version is not on crates.io; it will be published." + echo "publish=true" >> "$GITHUB_OUTPUT" + fi + + - name: Publish to crates.io + if: steps.check.outputs.publish == 'true' + env: + CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} + run: cargo publish