-
-
Notifications
You must be signed in to change notification settings - Fork 2
215 lines (202 loc) · 7.95 KB
/
rust.yml
File metadata and controls
215 lines (202 loc) · 7.95 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
name: rust
on:
push:
branches: main
paths:
- 'rust/**'
- '.github/workflows/rust.yml'
pull_request:
paths:
- 'rust/**'
- '.github/workflows/rust.yml'
env:
CARGO_TOKEN: ${{ secrets.CARGO_TOKEN }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
defaults:
run:
working-directory: rust
jobs:
findChangedRustFiles:
runs-on: ubuntu-latest
timeout-minutes: 10
outputs:
isRustFilesChanged: ${{ steps.setIsRustFilesChangedOutput.outputs.isRustFilesChanged }}
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Get changed files using defaults
id: changed-files
uses: tj-actions/changed-files@v47
- name: Set output isRustFilesChanged
id: setIsRustFilesChangedOutput
run: |
isRustFilesChanged='false'
echo "Changed files: ${{ steps.changed-files.outputs.all_changed_files }}"
for changedFile in ${{ steps.changed-files.outputs.all_changed_files }}; do
if [[ $changedFile == rust/*.rs ]] || [[ $changedFile == rust/Cargo.toml ]] || [[ $changedFile == rust/Cargo.lock ]] || [[ $changedFile == rust/* ]] || [[ $changedFile == .github/workflows/rust.yml ]]; then
echo "isRustFilesChanged='true'"
isRustFilesChanged='true'
break
fi
done
echo "isRustFilesChanged=${isRustFilesChanged}" >> $GITHUB_OUTPUT
echo "isRustFilesChanged: ${isRustFilesChanged}"
lint:
needs: [findChangedRustFiles]
if: ${{ needs.findChangedRustFiles.outputs.isRustFilesChanged == 'true' }}
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v6
with:
submodules: true
- name: Setup Rust
uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt, clippy
- name: Cache Cargo registry
uses: actions/cache@v5
with:
path: ~/.cargo/registry
key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }}
- name: Cache Cargo index
uses: actions/cache@v5
with:
path: ~/.cargo/git
key: ${{ runner.os }}-cargo-index-${{ hashFiles('**/Cargo.lock') }}
- name: Check formatting
run: cargo fmt --all -- --check
- name: Run Clippy
run: cargo clippy --all-targets --all-features -- -D warnings
test:
needs: [findChangedRustFiles, lint]
if: ${{ needs.findChangedRustFiles.outputs.isRustFilesChanged == 'true' }}
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@v6
with:
submodules: true
- name: Setup Rust
uses: dtolnay/rust-toolchain@stable
- name: Cache Cargo registry
uses: actions/cache@v5
with:
path: ~/.cargo/registry
key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }}
- name: Cache Cargo index
uses: actions/cache@v5
with:
path: ~/.cargo/git
key: ${{ runner.os }}-cargo-index-${{ hashFiles('**/Cargo.lock') }}
- name: Cache Cargo build
uses: actions/cache@v5
with:
path: target
key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('**/Cargo.lock') }}
- name: Build
run: cargo build --release
- name: Test
run: cargo test
publishToCratesIO:
needs: [test, findChangedRustFiles]
if: ${{ needs.findChangedRustFiles.outputs.isRustFilesChanged == 'true' && github.event_name == 'push' && github.ref == 'refs/heads/main' }}
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@v6
with:
submodules: true
- name: Setup Rust
uses: dtolnay/rust-toolchain@stable
- name: Cache Cargo registry
uses: actions/cache@v5
with:
path: ~/.cargo/registry
key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }}
- name: Cache Cargo index
uses: actions/cache@v5
with:
path: ~/.cargo/git
key: ${{ runner.os }}-cargo-index-${{ hashFiles('**/Cargo.lock') }}
- name: Cache Cargo build
uses: actions/cache@v5
with:
path: target
key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('**/Cargo.lock') }}
- name: Build
run: cargo build --release
- name: Publish to Crates.io (with version check)
id: publish-crate
run: |
PACKAGE_NAME=$(grep '^name = ' Cargo.toml | head -1 | sed 's/name = "\(.*\)"/\1/')
PACKAGE_VERSION=$(grep '^version = ' Cargo.toml | head -1 | sed 's/version = "\(.*\)"/\1/')
echo "Package: $PACKAGE_NAME@$PACKAGE_VERSION"
echo "=== Attempting to publish to crates.io ==="
# Try to publish and capture the result
set +e # Don't exit on error
cargo publish --token ${{ secrets.CARGO_TOKEN }} --allow-dirty 2>&1 | tee publish_output.txt
PUBLISH_EXIT_CODE=$?
set -e # Re-enable exit on error
if [ $PUBLISH_EXIT_CODE -eq 0 ]; then
echo "✅ Successfully published $PACKAGE_NAME@$PACKAGE_VERSION to crates.io"
echo "publish_result=success" >> $GITHUB_OUTPUT
elif grep -q "already exists on crates.io index" publish_output.txt; then
echo "ℹ️ Version $PACKAGE_VERSION already exists on crates.io - this is OK"
echo "publish_result=already_exists" >> $GITHUB_OUTPUT
exit 0 # Don't fail the workflow
else
echo "❌ Failed to publish for unknown reason"
cat publish_output.txt
echo "publish_result=failed" >> $GITHUB_OUTPUT
exit 1
fi
- name: Report publish status
if: always()
run: |
if [ "${{ steps.publish-crate.outputs.publish_result }}" = "success" ]; then
echo "✅ Package was successfully published"
elif [ "${{ steps.publish-crate.outputs.publish_result }}" = "already_exists" ]; then
echo "ℹ️ Package version already exists - no action needed"
else
echo "❌ Publishing failed - please check the logs"
fi
publishRelease:
runs-on: ubuntu-latest
timeout-minutes: 10
needs: [publishToCratesIO]
if: ${{ needs.findChangedRustFiles.outputs.isRustFilesChanged == 'true' && needs.publishToCratesIO.result == 'success' && github.event_name == 'push' && github.ref == 'refs/heads/main' }}
steps:
- uses: actions/checkout@v6
with:
submodules: true
- name: Setup Rust
uses: dtolnay/rust-toolchain@stable
- name: Check if GitHub release already exists
id: release-check
run: |
PACKAGE_VERSION=$(grep '^version = ' Cargo.toml | head -1 | sed 's/version = "\(.*\)"/\1/')
TAG_NAME="rust_$PACKAGE_VERSION"
echo "Checking if release $TAG_NAME already exists"
# Check if release exists
if gh release view "$TAG_NAME" >/dev/null 2>&1; then
echo "Release $TAG_NAME already exists"
echo "should_create_release=false" >> $GITHUB_OUTPUT
else
echo "Release $TAG_NAME does not exist"
echo "should_create_release=true" >> $GITHUB_OUTPUT
fi
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Create GitHub release
if: steps.release-check.outputs.should_create_release == 'true'
run: |
PACKAGE_NAME=$(grep '^name = ' Cargo.toml | head -1 | sed 's/name = "\(.*\)"/\1/')
PACKAGE_VERSION=$(grep '^version = ' Cargo.toml | head -1 | sed 's/version = "\(.*\)"/\1/')
# Create release with consistent tag format: rust_version
gh release create "rust_${PACKAGE_VERSION}" \
--title "[Rust] $PACKAGE_VERSION" \
--notes "https://crates.io/crates/$PACKAGE_NAME"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}