1- # Crate publication workflow for Torrust Tracker Deployer SDK
1+ # Crate publication workflow for Torrust Tracker Deployer
2+ #
3+ # Publishes all four workspace crates in dependency order when a release branch is pushed:
4+ # 1. torrust-deployer-types (no internal deps)
5+ # 2. torrust-dependency-installer (no internal deps)
6+ # 3. torrust-tracker-deployer (depends on 1 and 2)
7+ # 4. torrust-tracker-deployer-sdk (depends on 1 and 3)
28#
3- # This workflow publishes the SDK crate when a release branch is pushed.
49# Trigger branch format: releases/vX.Y.Z or releases/vX.Y.Z-pre.N (pre-release)
510
611name : Publish Crate
1318
1419env :
1520 CARGO_TERM_COLOR : always
16- CRATE_NAME : torrust-tracker-deployer-sdk
21+ DEPLOYER_TYPES_CRATE : torrust-deployer-types
22+ DEPENDENCY_INSTALLER_CRATE : torrust-dependency-installer
23+ MAIN_CRATE : torrust-tracker-deployer
24+ SDK_CRATE : torrust-tracker-deployer-sdk
1725
1826jobs :
19- publish_sdk :
20- name : Publish SDK Crate
27+ publish_all :
28+ name : Publish All Crates
2129 environment : crates-io
2230 runs-on : ubuntu-latest
23- timeout-minutes : 30
31+ timeout-minutes : 60
2432
2533 steps :
2634 - name : Checkout Repository
@@ -46,77 +54,157 @@ jobs:
4654 exit 1
4755 fi
4856
49- - name : Verify Release Version Matches Cargo Manifests
57+ - name : Verify Release Version Matches All Cargo Manifests
5058 run : |
59+ release_version="${{ steps.release.outputs.version }}"
60+
5161 root_version=$(grep '^version = ' Cargo.toml | head -1 | sed -E 's/version = "([^"]+)"/\1/')
5262 sdk_version=$(grep '^version = ' packages/sdk/Cargo.toml | head -1 | sed -E 's/version = "([^"]+)"/\1/')
53- release_version="${{ steps.release.outputs.version }}"
63+ types_version=$(grep '^version = ' packages/deployer-types/Cargo.toml | head -1 | sed -E 's/version = "([^"]+)"/\1/')
64+ installer_version=$(grep '^version = ' packages/dependency-installer/Cargo.toml | head -1 | sed -E 's/version = "([^"]+)"/\1/')
65+
66+ for pair in "Root:$root_version" "SDK:$sdk_version" "DeployerTypes:$types_version" "DependencyInstaller:$installer_version"; do
67+ label="${pair%%:*}"
68+ version="${pair#*:}"
69+ if [[ "$version" != "$release_version" ]]; then
70+ echo "$label Cargo.toml version mismatch: $version != $release_version" >&2
71+ exit 1
72+ fi
73+ done
5474
55- if [[ "$root_version" != "$release_version" ]]; then
56- echo "Root Cargo.toml version mismatch: $root_version != $release_version" >&2
57- exit 1
58- fi
75+ - name : Verify Crates.io Metadata for All Crates
76+ run : |
77+ for manifest in Cargo.toml packages/sdk/Cargo.toml packages/deployer-types/Cargo.toml packages/dependency-installer/Cargo.toml; do
78+ for field in description license repository readme; do
79+ if ! grep -q "^$field = " "$manifest"; then
80+ echo "Missing required field '$field' in $manifest" >&2
81+ exit 1
82+ fi
83+ done
84+ done
5985
60- if [[ "$sdk_version" != "$release_version" ]]; then
61- echo "SDK Cargo.toml version mismatch: $sdk_version != $release_version" >&2
62- exit 1
63- fi
86+ - name : Run All Tests
87+ run : cargo test
6488
65- - name : Verify SDK Metadata
89+ - name : Inspect Packaged Files
6690 run : |
67- for field in description license repository readme; do
68- if ! grep -q "^$field = " packages/sdk/Cargo.toml; then
69- echo "Missing required field in packages/sdk/Cargo.toml: $field" >&2
91+ for crate in \
92+ "${{ env.DEPLOYER_TYPES_CRATE }}" \
93+ "${{ env.DEPENDENCY_INSTALLER_CRATE }}" \
94+ "${{ env.MAIN_CRATE }}" \
95+ "${{ env.SDK_CRATE }}"; do
96+ echo "=== Packaged files for $crate ==="
97+ cargo package --list -p "$crate"
98+ done
99+
100+ - name : Dry Run Publish All Crates
101+ env :
102+ CARGO_REGISTRY_TOKEN : ${{ secrets.CARGO_REGISTRY_TOKEN }}
103+ run : |
104+ for crate in \
105+ "${{ env.DEPLOYER_TYPES_CRATE }}" \
106+ "${{ env.DEPENDENCY_INSTALLER_CRATE }}" \
107+ "${{ env.MAIN_CRATE }}" \
108+ "${{ env.SDK_CRATE }}"; do
109+ echo "=== Dry run publish for $crate ==="
110+ cargo publish --dry-run -p "$crate"
111+ done
112+
113+ - name : Check If Versions Already Published
114+ run : |
115+ release_version="${{ steps.release.outputs.version }}"
116+ for crate in \
117+ "${{ env.DEPLOYER_TYPES_CRATE }}" \
118+ "${{ env.DEPENDENCY_INSTALLER_CRATE }}" \
119+ "${{ env.MAIN_CRATE }}" \
120+ "${{ env.SDK_CRATE }}"; do
121+ set +e
122+ http_status=$(curl -s -o /tmp/crate-check.json -w "%{http_code}" "https://crates.io/api/v1/crates/$crate/$release_version")
123+ set -e
124+ if [[ "$http_status" == "200" ]]; then
125+ echo "Already published: $crate $release_version — do not republish, cut a patch release instead." >&2
70126 exit 1
71127 fi
72128 done
73129
74- - name : Run SDK Tests
75- run : cargo test -p ${{ env.CRATE_NAME }}
130+ - name : Publish torrust-deployer-types
131+ env :
132+ CARGO_REGISTRY_TOKEN : ${{ secrets.CARGO_REGISTRY_TOKEN }}
133+ run : cargo publish -p ${{ env.DEPLOYER_TYPES_CRATE }}
76134
77- - name : Inspect Packaged Files
78- run : cargo package --list -p ${{ env.CRATE_NAME }}
135+ - name : Wait for torrust-deployer-types to Be Indexed
136+ run : |
137+ release_version="${{ steps.release.outputs.version }}"
138+ for attempt in 1 2 3 4 5 6; do
139+ status=$(curl -s -o /tmp/crate-check.json -w "%{http_code}" "https://crates.io/api/v1/crates/${{ env.DEPLOYER_TYPES_CRATE }}/$release_version")
140+ if [[ "$status" == "200" ]]; then
141+ echo "${{ env.DEPLOYER_TYPES_CRATE }} $release_version is indexed on crates.io"
142+ break
143+ fi
144+ echo "Waiting for crates.io index (attempt $attempt/6)..."
145+ sleep 15
146+ done
79147
80- - name : Dry Run Publish
148+ - name : Publish torrust-dependency-installer
81149 env :
82150 CARGO_REGISTRY_TOKEN : ${{ secrets.CARGO_REGISTRY_TOKEN }}
83- run : cargo publish --dry-run - p ${{ env.CRATE_NAME }}
151+ run : cargo publish -p ${{ env.DEPENDENCY_INSTALLER_CRATE }}
84152
85- - name : Check If Version Already Published
153+ - name : Wait for torrust-dependency-installer to Be Indexed
86154 run : |
87- set +e
88- 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 }}")
89- set -e
155+ release_version="${{ steps.release.outputs.version }}"
156+ for attempt in 1 2 3 4 5; do
157+ status=$(curl -s -o /tmp/crate-check.json -w "%{http_code}" "https://crates.io/api/v1/crates/${{ env.DEPENDENCY_INSTALLER_CRATE }}/$release_version")
158+ if [[ "$status" == "200" ]]; then
159+ echo "${{ env.DEPENDENCY_INSTALLER_CRATE }} $release_version is indexed on crates.io"
160+ break
161+ fi
162+ echo "Waiting for crates.io index update (attempt $attempt/5)..."
163+ sleep 15
164+ done
90165
91- if [[ "$http_status" == "200" ]]; then
92- echo "Crate version already published: ${{ env.CRATE_NAME }} ${{ steps.release.outputs.version }}" >&2
93- echo "Do not republish. Cut a follow-up patch release instead." >&2
94- exit 1
95- fi
166+ - name : Publish torrust-tracker-deployer
167+ env :
168+ CARGO_REGISTRY_TOKEN : ${{ secrets.CARGO_REGISTRY_TOKEN }}
169+ run : cargo publish -p ${{ env.MAIN_CRATE }}
170+
171+ - name : Wait for torrust-tracker-deployer to Be Indexed
172+ run : |
173+ release_version="${{ steps.release.outputs.version }}"
174+ for attempt in 1 2 3 4 5; do
175+ status=$(curl -s -o /tmp/crate-check.json -w "%{http_code}" "https://crates.io/api/v1/crates/${{ env.MAIN_CRATE }}/$release_version")
176+ if [[ "$status" == "200" ]]; then
177+ echo "${{ env.MAIN_CRATE }} $release_version is indexed on crates.io"
178+ break
179+ fi
180+ echo "Waiting for crates.io index update (attempt $attempt/5)..."
181+ sleep 15
182+ done
96183
97- - name : Publish Crate
184+ - name : Publish torrust-tracker-deployer-sdk
98185 env :
99186 CARGO_REGISTRY_TOKEN : ${{ secrets.CARGO_REGISTRY_TOKEN }}
100- run : cargo publish -p ${{ env.CRATE_NAME }}
187+ run : cargo publish -p ${{ env.SDK_CRATE }}
101188
102- - name : Verify Crate Is Available
189+ - name : Verify SDK Is Available on crates.io
103190 run : |
191+ release_version="${{ steps.release.outputs.version }}"
104192 for attempt in 1 2 3 4 5; do
105- 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 }} ")
193+ status=$(curl -s -o /tmp/crate-publish-check.json -w "%{http_code}" "https://crates.io/api/v1/crates/${{ env.SDK_CRATE }}/$release_version ")
106194 if [[ "$status" == "200" ]]; then
107- echo "Crate is available on crates.io"
195+ echo "SDK crate is available on crates.io"
108196 exit 0
109197 fi
110198 echo "Waiting for crates.io index update (attempt $attempt/5)..."
111199 sleep 10
112200 done
113201
114- echo "Crate was published but not visible yet. Check crates.io manually." >&2
202+ echo "SDK crate was published but not visible yet. Check crates.io manually." >&2
115203 exit 1
116204
117- - name : Verify docs.rs Build
205+ - name : Verify docs.rs Build for SDK
118206 run : |
119- docs_url="https://docs.rs/${{ env.CRATE_NAME }}/${{ steps.release.outputs.version }}"
207+ docs_url="https://docs.rs/${{ env.SDK_CRATE }}/${{ steps.release.outputs.version }}"
120208 for attempt in 1 2 3 4 5 6; do
121209 status=$(curl -s -o /tmp/docs-rs-check.html -w "%{http_code}" "$docs_url")
122210 if [[ "$status" == "200" ]]; then
0 commit comments