diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 16d95dd..dbd56dc 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -1,20 +1,79 @@ -name: Publish to Crates.io +name: Release and Publish on: - release: - types: [published] + push: + branches: + - release + +permissions: + contents: write jobs: publish: - name: Publish on release + name: Create release and publish crate runs-on: ubuntu-latest + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} + steps: - - uses: actions/checkout@v4 - - uses: actions-rs/toolchain@v1 + - name: Checkout code + uses: actions/checkout@v4 with: - toolchain: stable - override: true + fetch-depth: 0 + + - name: Install Rust toolchain + uses: dtolnay/rust-toolchain@stable + + - name: Read package metadata + shell: bash + run: | + python - <<'PY' >> "$GITHUB_ENV" + import pathlib + import tomllib + + cargo_toml = tomllib.loads(pathlib.Path("Cargo.toml").read_text(encoding="utf-8")) + package = cargo_toml["package"] + name = package["name"] + version = package["version"] + + print(f"PACKAGE_NAME={name}") + print(f"PACKAGE_VERSION={version}") + print(f"RELEASE_TAG={name}-v{version}") + print(f"RELEASE_TITLE={name} v{version}") + PY + + - name: Create GitHub release + shell: bash + run: | + if gh release view "$RELEASE_TAG" >/dev/null 2>&1; then + echo "Release $RELEASE_TAG already exists." + else + gh release create "$RELEASE_TAG" \ + --target "$GITHUB_SHA" \ + --title "$RELEASE_TITLE" \ + --generate-notes + fi + + - name: Check crates.io for published version + id: crates + shell: bash + run: | + status="$(curl -s -o /dev/null -w "%{http_code}" "https://crates.io/api/v1/crates/$PACKAGE_NAME/$PACKAGE_VERSION")" + + case "$status" in + 200) + echo "already_published=true" >> "$GITHUB_OUTPUT" + ;; + 404) + echo "already_published=false" >> "$GITHUB_OUTPUT" + ;; + *) + echo "Unexpected crates.io response: $status" + exit 1 + ;; + esac + - name: Publish to crates.io - run: cargo publish --token ${{ secrets.CARGO_REGISTRY_TOKEN }} - env: - CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} + if: steps.crates.outputs.already_published != 'true' + run: cargo publish --locked --package "$PACKAGE_NAME" --token "$CARGO_REGISTRY_TOKEN"