Skip to content
Merged
Show file tree
Hide file tree
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
116 changes: 116 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
name: Release

on:
release:
types: [published]
workflow_dispatch:
inputs:
tag:
description: "Release tag to publish, for example v0.6.0"
required: true
type: string

permissions:
contents: read

concurrency:
group: release-${{ github.event.release.tag_name || inputs.tag }}
cancel-in-progress: false

env:
CARGO_TERM_COLOR: always
RELEASE_TAG: ${{ github.event.release.tag_name || inputs.tag }}

jobs:
publish:
name: Publish crates.io packages
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.event.release.tag_name || inputs.tag }}

- uses: dtolnay/rust-toolchain@stable

- name: Validate release version
run: |
set -euo pipefail

version="${RELEASE_TAG#v}"
metadata="$(cargo metadata --no-deps --format-version 1)"
lib_version="$(jq -r '.packages[] | select(.name == "office2pdf") | .version' <<<"${metadata}")"
cli_version="$(jq -r '.packages[] | select(.name == "office2pdf-cli") | .version' <<<"${metadata}")"
cli_dependency="$(jq -r '.packages[] | select(.name == "office2pdf-cli") | .dependencies[] | select(.name == "office2pdf") | .req' <<<"${metadata}")"

if [[ "${lib_version}" != "${version}" ]]; then
echo "::error::office2pdf version ${lib_version} does not match ${RELEASE_TAG}"
exit 1
fi

if [[ "${cli_version}" != "${version}" ]]; then
echo "::error::office2pdf-cli version ${cli_version} does not match ${RELEASE_TAG}"
exit 1
fi

case "${cli_dependency}" in
"${version}"|"^${version}") ;;
*)
echo "::error::office2pdf-cli depends on office2pdf ${cli_dependency}, expected ${version}"
exit 1
;;
esac

- name: Check crates.io token
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
run: |
set -euo pipefail
if [[ -z "${CARGO_REGISTRY_TOKEN}" ]]; then
echo "::error::CARGO_REGISTRY_TOKEN secret is required to publish crates"
exit 1
fi

- name: Publish office2pdf
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
run: |
set -euo pipefail

version="${RELEASE_TAG#v}"
if cargo search office2pdf --limit 1 | grep -F "office2pdf = \"${version}\"" > /dev/null; then
echo "office2pdf ${version} is already published"
exit 0
fi

cargo publish -p office2pdf --token "${CARGO_REGISTRY_TOKEN}"

- name: Wait for office2pdf index update
run: |
set -euo pipefail

version="${RELEASE_TAG#v}"
for attempt in {1..30}; do
if cargo search office2pdf --limit 1 | grep -F "office2pdf = \"${version}\"" > /dev/null; then
exit 0
fi

echo "office2pdf ${version} is not visible in the crates.io index yet; retry ${attempt}/30"
sleep 10
done

echo "::error::office2pdf ${version} did not appear in the crates.io index"
exit 1

- name: Publish office2pdf-cli
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
run: |
set -euo pipefail

version="${RELEASE_TAG#v}"
if cargo search office2pdf-cli --limit 1 | grep -F "office2pdf-cli = \"${version}\"" > /dev/null; then
echo "office2pdf-cli ${version} is already published"
exit 0
fi

cargo publish -p office2pdf-cli --token "${CARGO_REGISTRY_TOKEN}"
6 changes: 3 additions & 3 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ When asked to "release", always perform **both** GitHub Release and crates.io pu
1. **Version bump** — Create a PR (`chore/publish-<version>`) that bumps `version` in both `crates/office2pdf/Cargo.toml` and `crates/office2pdf-cli/Cargo.toml`, and updates the CLI's `office2pdf` dependency version. Merge via standard PR workflow.
2. **GitHub Release** — `gh release create v<version>` with changelog and contributors section.
- Use `git log <prev-tag>..HEAD --format='%an' | sort -u` to find contributors. List each with their GitHub profile link.
3. **crates.io publish** — Publish lib first, then CLI:
- `cargo publish -p office2pdf`
- `cargo publish -p office2pdf-cli`
3. **crates.io publish** — `.github/workflows/release.yml` publishes lib first, then CLI. It requires the `CARGO_REGISTRY_TOKEN` repo secret.
- New releases publish automatically on `release.published`.
- Existing releases can be published with `gh workflow run release.yml -f tag=v<version>`.
4. **Tag alignment** — Ensure the GitHub release tag (`v<version>`) and Cargo.toml versions match.
Loading