Skip to content

Commit 2249927

Browse files
committed
ci: [#448] add SDK crate release workflow
1 parent 0d93e58 commit 2249927

3 files changed

Lines changed: 141 additions & 2 deletions

File tree

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
# Crate publication workflow for Torrust Tracker Deployer SDK
2+
#
3+
# This workflow publishes the SDK crate when a release branch is pushed.
4+
# Trigger branch format: releases/vX.Y.Z
5+
6+
name: Publish Crate
7+
8+
on:
9+
push:
10+
branches:
11+
- "releases/**/*"
12+
paths:
13+
- "Cargo.toml"
14+
- "Cargo.lock"
15+
- "packages/sdk/**"
16+
- ".github/workflows/publish-crate.yaml"
17+
workflow_dispatch:
18+
19+
env:
20+
CARGO_TERM_COLOR: always
21+
CRATE_NAME: torrust-tracker-deployer-sdk
22+
23+
jobs:
24+
publish_sdk:
25+
name: Publish SDK Crate
26+
environment: crates-io
27+
runs-on: ubuntu-latest
28+
timeout-minutes: 30
29+
30+
steps:
31+
- name: Checkout Repository
32+
uses: actions/checkout@v5
33+
34+
- name: Setup Rust Toolchain
35+
uses: dtolnay/rust-toolchain@stable
36+
with:
37+
toolchain: stable
38+
39+
- name: Enable Workflow Cache
40+
uses: Swatinem/rust-cache@v2
41+
42+
- name: Extract Release Version
43+
id: release
44+
run: |
45+
if [[ "${{ github.ref_name }}" =~ ^releases/v(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)$ ]]; then
46+
version="${GITHUB_REF_NAME#releases/v}"
47+
echo "version=$version" >> "$GITHUB_OUTPUT"
48+
else
49+
echo "Invalid release branch name: ${{ github.ref_name }}" >&2
50+
echo "Expected format: releases/vX.Y.Z" >&2
51+
exit 1
52+
fi
53+
54+
- name: Verify Release Version Matches Cargo Manifests
55+
run: |
56+
root_version=$(grep '^version = ' Cargo.toml | head -1 | sed -E 's/version = "([^"]+)"/\1/')
57+
sdk_version=$(grep '^version = ' packages/sdk/Cargo.toml | head -1 | sed -E 's/version = "([^"]+)"/\1/')
58+
release_version="${{ steps.release.outputs.version }}"
59+
60+
if [[ "$root_version" != "$release_version" ]]; then
61+
echo "Root Cargo.toml version mismatch: $root_version != $release_version" >&2
62+
exit 1
63+
fi
64+
65+
if [[ "$sdk_version" != "$release_version" ]]; then
66+
echo "SDK Cargo.toml version mismatch: $sdk_version != $release_version" >&2
67+
exit 1
68+
fi
69+
70+
- name: Verify SDK Metadata
71+
run: |
72+
for field in description license repository readme; do
73+
if ! grep -q "^$field = " packages/sdk/Cargo.toml; then
74+
echo "Missing required field in packages/sdk/Cargo.toml: $field" >&2
75+
exit 1
76+
fi
77+
done
78+
79+
- name: Run SDK Tests
80+
run: cargo test -p ${{ env.CRATE_NAME }}
81+
82+
- name: Inspect Packaged Files
83+
run: cargo package --list -p ${{ env.CRATE_NAME }}
84+
85+
- name: Dry Run Publish
86+
env:
87+
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
88+
run: cargo publish --dry-run -p ${{ env.CRATE_NAME }}
89+
90+
- name: Check If Version Already Published
91+
run: |
92+
set +e
93+
http_status=$(curl -s -o /tmp/crate-version.json -w "%{http_code}" "https://crates.io/api/v1/crates/${{ env.CRATE_NAME }}/${{ steps.release.outputs.version }}")
94+
set -e
95+
96+
if [[ "$http_status" == "200" ]]; then
97+
echo "Crate version already published: ${{ env.CRATE_NAME }} ${{ steps.release.outputs.version }}" >&2
98+
echo "Do not republish. Cut a follow-up patch release instead." >&2
99+
exit 1
100+
fi
101+
102+
- name: Publish Crate
103+
env:
104+
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
105+
run: cargo publish -p ${{ env.CRATE_NAME }}
106+
107+
- name: Verify Crate Is Available
108+
run: |
109+
for attempt in 1 2 3 4 5; do
110+
status=$(curl -s -o /tmp/crate-publish-check.json -w "%{http_code}" "https://crates.io/api/v1/crates/${{ env.CRATE_NAME }}/${{ steps.release.outputs.version }}")
111+
if [[ "$status" == "200" ]]; then
112+
echo "Crate is available on crates.io"
113+
exit 0
114+
fi
115+
echo "Waiting for crates.io index update (attempt $attempt/5)..."
116+
sleep 10
117+
done
118+
119+
echo "Crate was published but not visible yet. Check crates.io manually." >&2
120+
exit 1
121+
122+
- name: Verify docs.rs Build
123+
run: |
124+
docs_url="https://docs.rs/${{ env.CRATE_NAME }}/${{ steps.release.outputs.version }}"
125+
for attempt in 1 2 3 4 5 6; do
126+
status=$(curl -s -o /tmp/docsrs-check.html -w "%{http_code}" "$docs_url")
127+
if [[ "$status" == "200" ]]; then
128+
echo "docs.rs page is available: $docs_url"
129+
exit 0
130+
fi
131+
echo "Waiting for docs.rs build (attempt $attempt/6)..."
132+
sleep 20
133+
done
134+
135+
echo "docs.rs page is not available yet: $docs_url" >&2
136+
echo "The crate may still be building on docs.rs; verify manually later." >&2
137+
exit 1

docs/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ Welcome to the Torrust Tracker Deployer documentation! This index helps you quic
1212
| Place code in the correct layer | [`contributing/ddd-layer-placement.md`](contributing/ddd-layer-placement.md) - **CRITICAL** decision flowchart |
1313
| Follow development principles | [`development-principles.md`](development-principles.md) - Observability, Testability, User Friendliness, Actionability |
1414
| Commit code | [`contributing/commit-process.md`](contributing/commit-process.md) - Pre-commit checks, conventional commits |
15+
| Cut a release | [`release-process.md`](release-process.md) - Standard release sequence, branch/tag rules, Docker + crate publication |
1516
| Handle errors properly | [`contributing/error-handling.md`](contributing/error-handling.md) - Explicit enums, actionable messages |
1617
| Handle output properly | [`contributing/output-handling.md`](contributing/output-handling.md) - **CRITICAL** UserOutput, never `println!` |
1718
| Organize Rust code | [`contributing/module-organization.md`](contributing/module-organization.md) - **CRITICAL** import conventions |
@@ -83,6 +84,7 @@ docs/
8384
| Write unit tests | [`contributing/testing/unit-testing.md`](contributing/testing/unit-testing.md) |
8485
| Understand a decision | [`decisions/README.md`](decisions/README.md) |
8586
| Plan a new feature | [`features/README.md`](features/README.md) |
87+
| Perform a release | [`release-process.md`](release-process.md) |
8688
| Fix external tool issues | [`external-issues/README.md`](external-issues/README.md) |
8789
| Work with templates | [`contributing/templates/`](contributing/templates/) |
8890
| Handle errors properly | [`contributing/error-handling.md`](contributing/error-handling.md) |

docs/release-process.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,6 @@ CI re-runs and audit trails.
264264

265265
- [Branching conventions](contributing/branching.md)
266266
- [Commit process](contributing/commit-process.md)
267-
- [Docker workflow](.github/workflows/container.yaml)
268-
- [Crate publish workflow](.github/workflows/publish-crate.yaml)
267+
- [Docker workflow](../.github/workflows/container.yaml)
268+
- [Crate publish workflow](../.github/workflows/publish-crate.yaml)
269269
- [Roadmap](roadmap.md)

0 commit comments

Comments
 (0)