55 tags :
66 - ' v*.*.*'
77
8- permissions :
9- contents : write
10- id-token : write # Required for trusted publishing to crates.io
11-
128env :
139 CARGO_TERM_COLOR : always
14- CARGO_INCREMENTAL : 0
15- CARGO_NET_RETRY : 10
16- RUSTUP_MAX_RETRIES : 10
10+
11+ permissions :
12+ contents : write
1713
1814jobs :
15+ # Create GitHub Release
1916 create-release :
2017 name : Create Release
2118 runs-on : ubuntu-latest
2219 outputs :
2320 upload_url : ${{ steps.create_release.outputs.upload_url }}
2421 version : ${{ steps.get_version.outputs.version }}
2522 steps :
23+ - uses : actions/checkout@v6
24+
2625 - name : Get version from tag
2726 id : get_version
2827 run : echo "version=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT
@@ -31,179 +30,220 @@ jobs:
3130 id : create_release
3231 uses : softprops/action-gh-release@v2
3332 with :
34- tag_name : ${{ github.ref }}
35- name : Release v${{ steps.get_version.outputs.version }}
3633 draft : false
3734 prerelease : false
3835 generate_release_notes : true
39- env :
40- GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
41-
42- publish-crate :
43- name : Publish to crates.io
44- runs-on : ubuntu-latest
45- timeout-minutes : 20
46- # Optional: use environment for additional protection
47- # environment: release
48- steps :
49- - uses : actions/checkout@v6
50-
51- - name : Install Rust stable
52- uses : dtolnay/rust-toolchain@stable
53-
54- - name : Cache Cargo
55- uses : Swatinem/rust-cache@v2
56- with :
57- shared-key : " publish"
58-
59- # Trusted Publishing: get short-lived token via OIDC
60- - name : Authenticate with crates.io
61- uses : rust-lang/crates-io-auth-action@v1
62-
63- - name : Publish mcpls-core
64- run : cargo publish --package mcpls-core
65-
66- - name : Wait for mcpls-core to be available on crates.io
67- run : sleep 60
36+ name : Release v${{ steps.get_version.outputs.version }}
6837
69- - name : Verify mcpls-core is indexed
70- run : |
71- for i in {1..10}; do
72- if cargo search mcpls-core | grep -q "mcpls-core"; then
73- echo "mcpls-core is indexed"
74- exit 0
75- fi
76- echo "Waiting for mcpls-core to be indexed (attempt $i/10)..."
77- sleep 30
78- done
79- echo "mcpls-core not indexed after 5 minutes, proceeding anyway"
80-
81- - name : Publish mcpls
82- run : cargo publish --package mcpls
83-
84- build-release :
85- name : Build Release Binary (${{ matrix.name }})
38+ # Build cross-platform binaries
39+ build-binaries :
40+ name : Build (${{ matrix.target }})
8641 needs : create-release
8742 runs-on : ${{ matrix.os }}
88- timeout-minutes : 30
43+ timeout-minutes : 45
8944 strategy :
9045 fail-fast : false
9146 matrix :
9247 include :
93- # Linux x86_64 (GNU)
94- - target : x86_64-unknown-linux-gnu
95- os : ubuntu-latest
96- name : linux-x86_64
97- archive_ext : tar.gz
98-
99- # Linux x86_64 (musl - static binary)
100- - target : x86_64-unknown-linux-musl
101- os : ubuntu-latest
102- name : linux-x86_64-musl
103- archive_ext : tar.gz
104-
105- # macOS x86_64 (Intel)
106- - target : x86_64-apple-darwin
107- os : macos-latest
108- name : macos-x86_64
109- archive_ext : tar.gz
110-
111- # macOS aarch64 (Apple Silicon )
112- - target : aarch64-apple-darwin
113- os : macos-latest
114- name : macos-aarch64
115- archive_ext : tar.gz
48+ # Linux x86_64
49+ - os : ubuntu-latest
50+ target : x86_64-unknown-linux-gnu
51+ archive : tar.gz
52+ use_cross : false
53+
54+ # Linux aarch64
55+ - os : ubuntu-latest
56+ target : aarch64-unknown-linux-gnu
57+ archive : tar.gz
58+ use_cross : true
59+
60+ # macOS x86_64
61+ - os : macos-latest
62+ target : x86_64-apple-darwin
63+ archive : tar.gz
64+ use_cross : false
65+
66+ # macOS aarch64 (M1/M2 )
67+ - os : macos-latest
68+ target : aarch64-apple-darwin
69+ archive : tar.gz
70+ use_cross : false
11671
11772 # Windows x86_64
118- - target : x86_64-pc-windows-msvc
119- os : windows-latest
120- name : windows-x86_64
121- archive_ext : zip
73+ - os : windows-latest
74+ target : x86_64-pc-windows-msvc
75+ archive : zip
76+ use_cross : false
77+
78+ # Windows aarch64 (ARM64)
79+ - os : windows-latest
80+ target : aarch64-pc-windows-msvc
81+ archive : zip
82+ use_cross : false
12283
12384 steps :
12485 - uses : actions/checkout@v6
12586
126- - name : Install Rust stable
87+ - name : Install Rust
12788 uses : dtolnay/rust-toolchain@stable
12889 with :
12990 targets : ${{ matrix.target }}
13091
92+ - name : Install cargo-binstall
93+ uses : cargo-bins/cargo-binstall@main
94+
95+ - name : Install cross (for cross-compilation)
96+ if : matrix.use_cross
97+ run : cargo binstall --no-confirm cross
98+
13199 - name : Cache Cargo
132100 uses : Swatinem/rust-cache@v2
133101 with :
134102 shared-key : " release-${{ matrix.target }}"
135103
136- - name : Install musl-tools (Linux musl)
137- if : matrix.target == 'x86_64-unknown-linux-musl'
138- run : sudo apt-get update && sudo apt-get install -y musl-tools
139-
140- - name : Build release binary
141- run : cargo build --release --target ${{ matrix.target }} --package mcpls
104+ - name : Build release (cross)
105+ if : matrix.use_cross
106+ run : cross build --package mcpls --release --target ${{ matrix.target }}
142107
143- - name : Strip binary (Unix )
144- if : runner.os != 'Windows'
145- run : strip target/ ${{ matrix.target }}/release/mcpls
108+ - name : Build release (native )
109+ if : " !matrix.use_cross "
110+ run : cargo build --package mcpls --release -- target ${{ matrix.target }}
146111
147112 - name : Get binary name
148- id : get_binary
149- shell : bash
113+ id : binary
150114 run : |
151- if [[ "${{ runner .os }}" == "Windows " ]]; then
152- echo "binary =mcpls.exe" >> $GITHUB_OUTPUT
115+ if [[ "${{ matrix .os }}" == "windows-latest " ]]; then
116+ echo "name =mcpls.exe" >> $GITHUB_OUTPUT
153117 else
154- echo "binary =mcpls" >> $GITHUB_OUTPUT
118+ echo "name =mcpls" >> $GITHUB_OUTPUT
155119 fi
156-
157- - name : Check binary size
158120 shell : bash
159- run : |
160- ls -lh target/${{ matrix.target }}/release/${{ steps.get_binary.outputs.binary }}
161- du -sh target/${{ matrix.target }}/release/${{ steps.get_binary.outputs.binary }}
121+
122+ - name : Strip binary (Linux/macOS, native only)
123+ if : matrix.os != 'windows-latest' && !matrix.use_cross
124+ run : strip target/${{ matrix.target }}/release/${{ steps.binary.outputs.name }}
162125
163126 - name : Create archive (Unix)
164- if : matrix.archive_ext == 'tar.gz'
127+ if : matrix.archive == 'tar.gz'
165128 run : |
166129 cd target/${{ matrix.target }}/release
167- tar czf mcpls-${{ needs.create-release.outputs.version }}-${{ matrix.name }}.tar.gz mcpls
168- mv mcpls-${{ needs.create-release.outputs.version }}-${{ matrix.name }}.tar.gz ../../..
130+ tar czf ../../../mcpls-${{ matrix.target }}.tar.gz ${{ steps.binary.outputs.name }}
131+ cd ../../..
132+ shasum -a 256 mcpls-${{ matrix.target }}.tar.gz > mcpls-${{ matrix.target }}.tar.gz.sha256
169133
170134 - name : Create archive (Windows)
171- if : matrix.archive_ext == 'zip'
172- shell : bash
135+ if : matrix.archive == 'zip'
173136 run : |
174137 cd target/${{ matrix.target }}/release
175- 7z a mcpls-${{ needs.create-release.outputs.version }}-${{ matrix.name }}.zip mcpls.exe
176- mv mcpls-${{ needs.create-release.outputs.version }}-${{ matrix.name }}.zip ../../../
177-
178- - name : Upload artifact to workflow
179- uses : actions/upload-artifact@v4
180- with :
181- name : mcpls-${{ needs.create-release.outputs.version }}-${{ matrix.name }}
182- path : mcpls-${{ needs.create-release.outputs.version }}-${{ matrix.name }}.${{ matrix.archive_ext }}
183- retention-days : 7
138+ 7z a ../../../mcpls-${{ matrix.target }}.zip ${{ steps.binary.outputs.name }}
139+ cd ../../..
140+ certUtil -hashfile mcpls-${{ matrix.target }}.zip SHA256 > mcpls-${{ matrix.target }}.zip.sha256
141+ shell : cmd
184142
185- - name : Upload to GitHub Release
143+ - name : Upload release archive
186144 uses : softprops/action-gh-release@v2
187145 with :
188- tag_name : ${{ github.ref }}
189- files : mcpls-${{ needs.create-release.outputs.version }}-${{ matrix.name }}.${{ matrix.archive_ext }}
190- env :
191- GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
192-
193- # All release jobs passed
194- release-success :
195- name : Release Success
196- needs : [create-release, publish-crate, build-release]
146+ files : |
147+ mcpls-${{ matrix.target }}.*
148+
149+ # Publish to crates.io using Trusted Publishing (OIDC)
150+ publish-crates :
151+ name : Publish to crates.io
152+ needs : [create-release, build-binaries]
197153 runs-on : ubuntu-latest
198- if : always()
154+ timeout-minutes : 20
155+ permissions :
156+ contents : read
157+ id-token : write
199158 steps :
200- - name : Check all jobs
159+ - uses : actions/checkout@v6
160+
161+ - name : Install Rust
162+ uses : dtolnay/rust-toolchain@stable
163+
164+ - name : Cache Cargo
165+ uses : Swatinem/rust-cache@v2
166+
167+ - name : Verify version matches tag
201168 run : |
202- if [[ "${{ needs.create-release.result }}" != "success" ]] || \
203- [[ "${{ needs.publish-crate.result }}" != "success" ]] || \
204- [[ "${{ needs.build-release.result }} " != "success" ] ]; then
205- echo "One or more release jobs failed "
169+ TAG_VERSION= "${GITHUB_REF#refs/tags/v}"
170+ CARGO_VERSION=$(grep '^version' Cargo.toml | head -1 | sed 's/.*"\(.*\)".*/\1/')
171+ if [ "$TAG_VERSION " != "$CARGO_VERSION" ]; then
172+ echo "Tag version ($TAG_VERSION) does not match Cargo.toml version ($CARGO_VERSION) "
206173 exit 1
207174 fi
208- echo "All release jobs passed successfully!"
209- echo "Version ${{ needs.create-release.outputs.version }} released!"
175+
176+ - name : Authenticate with crates.io
177+ id : crates-io-auth
178+ uses : rust-lang/crates-io-auth-action@v1
179+
180+ - name : Publish crates to crates.io
181+ uses : katyo/publish-crates@v2
182+ with :
183+ registry-token : ${{ steps.crates-io-auth.outputs.token }}
184+ ignore-unpublished-changes : true
185+ publish-delay : 10000
186+
187+ # Update release notes with installation instructions
188+ update-release-notes :
189+ name : Update Release Notes
190+ needs : [create-release, build-binaries, publish-crates]
191+ runs-on : ubuntu-latest
192+ steps :
193+ - uses : actions/checkout@v6
194+
195+ - name : Get version
196+ id : version
197+ run : echo "version=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT
198+
199+ - name : Update release with installation instructions
200+ uses : softprops/action-gh-release@v2
201+ with :
202+ append_body : true
203+ body : |
204+
205+ ## Installation
206+
207+ ### Binary Installation
208+
209+ Download the appropriate binary for your platform from the assets below:
210+
211+ - **Linux x86_64**: `mcpls-x86_64-unknown-linux-gnu.tar.gz`
212+ - **Linux aarch64**: `mcpls-aarch64-unknown-linux-gnu.tar.gz`
213+ - **macOS x86_64**: `mcpls-x86_64-apple-darwin.tar.gz`
214+ - **macOS ARM64**: `mcpls-aarch64-apple-darwin.tar.gz`
215+ - **Windows x64**: `mcpls-x86_64-pc-windows-msvc.zip`
216+ - **Windows ARM64**: `mcpls-aarch64-pc-windows-msvc.zip`
217+
218+ Extract and add to your PATH:
219+
220+ ```bash
221+ # Linux/macOS
222+ tar xzf mcpls-*.tar.gz
223+ sudo mv mcpls /usr/local/bin/
224+
225+ # Verify installation
226+ mcpls --version
227+ ```
228+
229+ ### Cargo Installation
230+
231+ ```bash
232+ cargo install mcpls
233+ ```
234+
235+ ### Claude Code Integration
236+
237+ Add to `~/.claude/claude_desktop_config.json`:
238+
239+ ```json
240+ {
241+ "mcpServers": {
242+ "mcpls": { "command": "mcpls", "args": [] }
243+ }
244+ }
245+ ```
246+
247+ ## Checksums
248+
249+ SHA256 checksums are available for all artifacts (`.sha256` files).
0 commit comments