Skip to content

Commit 0ef1366

Browse files
authored
Merge pull request #14 from link-foundation/issue-8-8f8d9acce5f1
Support Rust with CI/CD and Release Infrastructure
2 parents ff88c8e + 52faec8 commit 0ef1366

File tree

16 files changed

+2967
-66
lines changed

16 files changed

+2967
-66
lines changed

.github/workflows/rust.yml

Lines changed: 287 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,287 @@
1+
name: Rust CI/CD
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
paths:
8+
- 'rust/**'
9+
- '.github/workflows/rust.yml'
10+
pull_request:
11+
types: [opened, synchronize, reopened]
12+
paths:
13+
- 'rust/**'
14+
- '.github/workflows/rust.yml'
15+
workflow_dispatch:
16+
inputs:
17+
bump_type:
18+
description: 'Version bump type'
19+
required: true
20+
type: choice
21+
options:
22+
- patch
23+
- minor
24+
- major
25+
description:
26+
description: 'Release description (optional)'
27+
required: false
28+
type: string
29+
30+
concurrency:
31+
group: ${{ github.workflow }}-${{ github.ref }}
32+
cancel-in-progress: true
33+
34+
jobs:
35+
# Linting and formatting
36+
lint:
37+
name: Lint and Format Check
38+
runs-on: ubuntu-latest
39+
steps:
40+
- uses: actions/checkout@v4
41+
42+
- name: Set up Rust
43+
uses: dtolnay/rust-toolchain@stable
44+
with:
45+
components: rustfmt, clippy
46+
47+
- name: Cache cargo dependencies
48+
uses: actions/cache@v4
49+
with:
50+
path: |
51+
~/.cargo/bin/
52+
~/.cargo/registry/index/
53+
~/.cargo/registry/cache/
54+
~/.cargo/git/db/
55+
rust/target/
56+
key: ${{ runner.os }}-cargo-${{ hashFiles('rust/Cargo.lock') }}
57+
58+
- name: Check formatting
59+
working-directory: ./rust
60+
run: cargo fmt --check
61+
62+
- name: Run clippy
63+
working-directory: ./rust
64+
run: cargo clippy --all-targets --all-features -- -D warnings
65+
66+
# Test matrix: Rust on multiple OS
67+
test:
68+
name: Test (Rust on ${{ matrix.os }})
69+
runs-on: ${{ matrix.os }}
70+
strategy:
71+
fail-fast: false
72+
matrix:
73+
os: [ubuntu-latest, macos-latest, windows-latest]
74+
steps:
75+
- uses: actions/checkout@v4
76+
77+
- name: Set up Rust
78+
uses: dtolnay/rust-toolchain@stable
79+
80+
- name: Cache cargo dependencies
81+
uses: actions/cache@v4
82+
with:
83+
path: |
84+
~/.cargo/bin/
85+
~/.cargo/registry/index/
86+
~/.cargo/registry/cache/
87+
~/.cargo/git/db/
88+
rust/target/
89+
key: ${{ runner.os }}-cargo-${{ hashFiles('rust/Cargo.lock') }}
90+
91+
- name: Run tests
92+
working-directory: ./rust
93+
run: cargo test --verbose
94+
95+
- name: Run example
96+
working-directory: ./rust
97+
run: cargo run --example basic_usage
98+
99+
# Build package - only runs if lint and test pass
100+
build:
101+
name: Build Package
102+
runs-on: ubuntu-latest
103+
needs: [lint, test]
104+
steps:
105+
- uses: actions/checkout@v4
106+
107+
- name: Set up Rust
108+
uses: dtolnay/rust-toolchain@stable
109+
110+
- name: Cache cargo dependencies
111+
uses: actions/cache@v4
112+
with:
113+
path: |
114+
~/.cargo/bin/
115+
~/.cargo/registry/index/
116+
~/.cargo/registry/cache/
117+
~/.cargo/git/db/
118+
rust/target/
119+
key: ${{ runner.os }}-cargo-${{ hashFiles('rust/Cargo.lock') }}
120+
121+
- name: Build release
122+
working-directory: ./rust
123+
run: cargo build --release
124+
125+
- name: Package crate
126+
working-directory: ./rust
127+
run: cargo package --allow-dirty
128+
129+
# Check for changelog fragments in PRs
130+
changelog:
131+
name: Changelog Fragment Check
132+
runs-on: ubuntu-latest
133+
if: github.event_name == 'pull_request'
134+
steps:
135+
- uses: actions/checkout@v4
136+
with:
137+
fetch-depth: 0
138+
139+
- name: Check for changelog fragments
140+
working-directory: ./rust
141+
run: |
142+
# Get list of fragment files (excluding README and template)
143+
FRAGMENTS=$(find changelog.d -name "*.md" ! -name "README.md" ! -name "*.j2" 2>/dev/null | wc -l)
144+
145+
# Get changed files in PR
146+
CHANGED_FILES=$(git diff --name-only origin/${{ github.base_ref }}...HEAD)
147+
148+
# Check if any source files changed (excluding docs and config)
149+
SOURCE_CHANGED=$(echo "$CHANGED_FILES" | grep -E "^rust/(src/|tests/|examples/)" | wc -l)
150+
151+
if [ "$SOURCE_CHANGED" -gt 0 ] && [ "$FRAGMENTS" -eq 0 ]; then
152+
echo "::warning::No changelog fragment found. Please add a changelog fragment in rust/changelog.d/"
153+
echo ""
154+
echo "To create a changelog fragment:"
155+
echo " cd rust/changelog.d"
156+
echo " Create a file: YYYYMMDD_HHMMSS_description.md"
157+
echo ""
158+
echo "See rust/changelog.d/README.md for more information."
159+
# Note: This is a warning, not a failure, to allow flexibility
160+
exit 0
161+
fi
162+
163+
echo "✓ Changelog check passed"
164+
165+
# Automatic release on push to main (if version changed)
166+
auto-release:
167+
name: Auto Release
168+
needs: [lint, test, build]
169+
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
170+
runs-on: ubuntu-latest
171+
permissions:
172+
contents: write
173+
steps:
174+
- uses: actions/checkout@v4
175+
with:
176+
fetch-depth: 0
177+
178+
- name: Set up Rust
179+
uses: dtolnay/rust-toolchain@stable
180+
181+
- name: Setup Node.js
182+
uses: actions/setup-node@v4
183+
with:
184+
node-version: '22'
185+
186+
- name: Check if version changed
187+
id: version_check
188+
working-directory: ./rust
189+
run: |
190+
# Get current version from Cargo.toml
191+
CURRENT_VERSION=$(grep -Po '(?<=^version = ")[^"]*' Cargo.toml)
192+
echo "current_version=$CURRENT_VERSION" >> $GITHUB_OUTPUT
193+
194+
# Check if tag exists
195+
if git rev-parse "rust-v$CURRENT_VERSION" >/dev/null 2>&1; then
196+
echo "Tag rust-v$CURRENT_VERSION already exists, skipping release"
197+
echo "should_release=false" >> $GITHUB_OUTPUT
198+
else
199+
echo "New version detected: $CURRENT_VERSION"
200+
echo "should_release=true" >> $GITHUB_OUTPUT
201+
fi
202+
203+
- name: Publish to crates.io
204+
if: steps.version_check.outputs.should_release == 'true'
205+
working-directory: ./rust
206+
env:
207+
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
208+
run: |
209+
if [ -z "$CARGO_REGISTRY_TOKEN" ]; then
210+
echo "::warning::CARGO_REGISTRY_TOKEN not set, skipping publish to crates.io"
211+
else
212+
cargo publish
213+
fi
214+
215+
- name: Create GitHub Release
216+
if: steps.version_check.outputs.should_release == 'true'
217+
env:
218+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
219+
working-directory: ./rust
220+
run: |
221+
node scripts/create-github-release.mjs \
222+
--version "${{ steps.version_check.outputs.current_version }}" \
223+
--repository "${{ github.repository }}" \
224+
--tag-prefix "rust-v"
225+
226+
# Manual release via workflow_dispatch
227+
manual-release:
228+
name: Manual Release
229+
needs: [lint, test, build]
230+
if: github.event_name == 'workflow_dispatch'
231+
runs-on: ubuntu-latest
232+
permissions:
233+
contents: write
234+
steps:
235+
- uses: actions/checkout@v4
236+
with:
237+
fetch-depth: 0
238+
token: ${{ secrets.GITHUB_TOKEN }}
239+
240+
- name: Set up Rust
241+
uses: dtolnay/rust-toolchain@stable
242+
243+
- name: Setup Node.js
244+
uses: actions/setup-node@v4
245+
with:
246+
node-version: '22'
247+
248+
- name: Configure git
249+
run: |
250+
git config user.name "github-actions[bot]"
251+
git config user.email "github-actions[bot]@users.noreply.github.com"
252+
253+
- name: Version and commit
254+
id: version
255+
working-directory: ./rust
256+
run: |
257+
node scripts/version-and-commit.mjs \
258+
--bump-type "${{ github.event.inputs.bump_type }}" \
259+
--description "${{ github.event.inputs.description }}"
260+
261+
- name: Build release
262+
if: steps.version.outputs.version_committed == 'true' || steps.version.outputs.already_released == 'true'
263+
working-directory: ./rust
264+
run: cargo build --release
265+
266+
- name: Publish to crates.io
267+
if: steps.version.outputs.version_committed == 'true' || steps.version.outputs.already_released == 'true'
268+
working-directory: ./rust
269+
env:
270+
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
271+
run: |
272+
if [ -z "$CARGO_REGISTRY_TOKEN" ]; then
273+
echo "::warning::CARGO_REGISTRY_TOKEN not set, skipping publish to crates.io"
274+
else
275+
cargo publish
276+
fi
277+
278+
- name: Create GitHub Release
279+
if: steps.version.outputs.version_committed == 'true' || steps.version.outputs.already_released == 'true'
280+
env:
281+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
282+
working-directory: ./rust
283+
run: |
284+
node scripts/create-github-release.mjs \
285+
--version "${{ steps.version.outputs.new_version }}" \
286+
--repository "${{ github.repository }}" \
287+
--tag-prefix "rust-v"

.github/workflows/test.yml

Lines changed: 0 additions & 63 deletions
This file was deleted.

0 commit comments

Comments
 (0)