Skip to content

Commit 66d91b9

Browse files
committed
ci: auto publish rust multi-platform packages to npm
1 parent c9ec3a5 commit 66d91b9

2 files changed

Lines changed: 183 additions & 87 deletions

File tree

.github/workflows/release.yml

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

.github/workflows/rust-release.yml

Lines changed: 183 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,26 @@ name: Rust Release
33
on:
44
push:
55
tags:
6-
- 'v*'
6+
- "v*"
77
workflow_dispatch:
8+
inputs:
9+
tag:
10+
description: "Tag to release (e.g. v2.0.0). Leave empty when triggered from tag push."
11+
required: false
12+
type: string
13+
14+
permissions:
15+
contents: read
16+
17+
env:
18+
CARGO_TERM_COLOR: always
819

920
jobs:
1021
build:
1122
name: Build ${{ matrix.platform }}
1223
runs-on: ${{ matrix.os }}
1324
strategy:
25+
fail-fast: false
1426
matrix:
1527
include:
1628
- os: ubuntu-latest
@@ -38,6 +50,25 @@ jobs:
3850
- name: Checkout
3951
uses: actions/checkout@v4
4052

53+
- name: Resolve release version
54+
id: version
55+
shell: bash
56+
run: |
57+
set -euo pipefail
58+
59+
TAG_INPUT="${{ inputs.tag }}"
60+
if [[ "${GITHUB_REF_TYPE}" == "tag" ]]; then
61+
VERSION="${GITHUB_REF_NAME#v}"
62+
elif [[ -n "${TAG_INPUT}" ]]; then
63+
VERSION="${TAG_INPUT#v}"
64+
else
65+
echo "::error::workflow_dispatch requires inputs.tag when not running on a tag ref."
66+
exit 1
67+
fi
68+
69+
echo "version=${VERSION}" >> "${GITHUB_OUTPUT}"
70+
echo "Release version: ${VERSION}"
71+
4172
- name: Setup Rust
4273
uses: dtolnay/rust-toolchain@stable
4374
with:
@@ -47,18 +78,84 @@ jobs:
4778
if: matrix.platform == 'linux-arm64'
4879
run: |
4980
sudo apt-get update
50-
sudo apt-get install -y gcc-aarch64-linux-gnu
81+
sudo apt-get install -y gcc-aarch64-linux-gnu libc6-dev-arm64-cross
82+
83+
- name: Configure linker (Linux ARM64)
84+
if: matrix.platform == 'linux-arm64'
85+
shell: bash
86+
run: |
87+
mkdir -p ~/.cargo
88+
cat >> ~/.cargo/config.toml <<EOF
89+
[target.aarch64-unknown-linux-gnu]
90+
linker = "aarch64-linux-gnu-gcc"
91+
EOF
5192
5293
- name: Build
5394
run: cargo build --release --target ${{ matrix.target }}
5495

55-
- name: Copy binary to platform package
96+
- name: Prepare platform package
5697
shell: bash
5798
run: |
58-
mkdir -p npm-platform/${{ matrix.platform }}/bin
59-
cp target/${{ matrix.target }}/release/${{ matrix.binary }} npm-platform/${{ matrix.platform }}/bin/
99+
set -euo pipefail
100+
101+
case "${{ matrix.platform }}" in
102+
linux-x64)
103+
NPM_OS="linux"
104+
NPM_CPU="x64"
105+
;;
106+
linux-arm64)
107+
NPM_OS="linux"
108+
NPM_CPU="arm64"
109+
;;
110+
darwin-x64)
111+
NPM_OS="darwin"
112+
NPM_CPU="x64"
113+
;;
114+
darwin-arm64)
115+
NPM_OS="darwin"
116+
NPM_CPU="arm64"
117+
;;
118+
win32-x64)
119+
NPM_OS="win32"
120+
NPM_CPU="x64"
121+
;;
122+
*)
123+
echo "Unsupported platform: ${{ matrix.platform }}"
124+
exit 1
125+
;;
126+
esac
127+
128+
PACKAGE_DIR="npm-platform/${{ matrix.platform }}"
129+
mkdir -p "${PACKAGE_DIR}/bin"
130+
cp "target/${{ matrix.target }}/release/${{ matrix.binary }}" "${PACKAGE_DIR}/bin/"
131+
132+
cat > "${PACKAGE_DIR}/package.json" <<JSON
133+
{
134+
"name": "@dongowu/git-ai-cli-${{ matrix.platform }}",
135+
"version": "${{ steps.version.outputs.version }}",
136+
"description": "Platform binary for @dongowu/git-ai-cli (${{ matrix.platform }})",
137+
"license": "Apache-2.0",
138+
"repository": {
139+
"type": "git",
140+
"url": "https://github.com/dongowu/git-ai-cli"
141+
},
142+
"os": ["${NPM_OS}"],
143+
"cpu": ["${NPM_CPU}"],
144+
"files": ["bin/${{ matrix.binary }}"],
145+
"publishConfig": {
146+
"access": "public"
147+
}
148+
}
149+
JSON
150+
151+
cat > "${PACKAGE_DIR}/README.md" <<EOF
152+
# @dongowu/git-ai-cli-${{ matrix.platform }}
60153
61-
- name: Upload artifact
154+
Platform-specific binary package for \
155+
[@dongowu/git-ai-cli](https://www.npmjs.com/package/@dongowu/git-ai-cli).
156+
EOF
157+
158+
- name: Upload platform package artifact
62159
uses: actions/upload-artifact@v4
63160
with:
64161
name: ${{ matrix.platform }}
@@ -68,52 +165,113 @@ jobs:
68165
name: Publish to npm
69166
needs: build
70167
runs-on: ubuntu-latest
71-
if: startsWith(github.ref, 'refs/tags/v')
168+
permissions:
169+
contents: write
170+
id-token: write
72171

73172
steps:
74173
- name: Checkout
75174
uses: actions/checkout@v4
76175

176+
- name: Resolve release version
177+
id: version
178+
shell: bash
179+
run: |
180+
set -euo pipefail
181+
182+
TAG_INPUT="${{ inputs.tag }}"
183+
if [[ "${GITHUB_REF_TYPE}" == "tag" ]]; then
184+
VERSION="${GITHUB_REF_NAME#v}"
185+
elif [[ -n "${TAG_INPUT}" ]]; then
186+
VERSION="${TAG_INPUT#v}"
187+
else
188+
echo "::error::workflow_dispatch requires inputs.tag when not running on a tag ref."
189+
exit 1
190+
fi
191+
192+
echo "version=${VERSION}" >> "${GITHUB_OUTPUT}"
193+
echo "Release version: ${VERSION}"
194+
77195
- name: Setup Node.js
78196
uses: actions/setup-node@v4
79197
with:
80-
node-version: '18'
81-
registry-url: 'https://registry.npmjs.org'
198+
node-version: "20"
199+
registry-url: "https://registry.npmjs.org"
82200

83-
- name: Download all artifacts
201+
- name: Download all platform artifacts
84202
uses: actions/download-artifact@v4
85203
with:
86204
path: npm-platform
87205

206+
- name: Align root package version with tag
207+
env:
208+
RELEASE_VERSION: ${{ steps.version.outputs.version }}
209+
run: |
210+
node <<"NODE"
211+
const fs = require("fs");
212+
213+
const version = process.env.RELEASE_VERSION;
214+
const pkgPath = "package.json";
215+
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
216+
217+
pkg.version = version;
218+
pkg.optionalDependencies = pkg.optionalDependencies || {};
219+
220+
for (const platform of ["linux-x64", "linux-arm64", "darwin-x64", "darwin-arm64", "win32-x64"]) {
221+
pkg.optionalDependencies[`@dongowu/git-ai-cli-${platform}`] = version;
222+
}
223+
224+
fs.writeFileSync(pkgPath, `${JSON.stringify(pkg, null, 2)}\n`);
225+
NODE
226+
88227
- name: Publish platform packages
89228
env:
90229
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
230+
shell: bash
91231
run: |
92-
for platform in linux-x64 linux-arm64 darwin-x64 darwin-arm64 win32-x64; do
93-
cd npm-platform/$platform
94-
npm publish --access public
95-
cd ../..
232+
set -euo pipefail
233+
234+
for package_dir in npm-platform/*; do
235+
if [[ ! -d "${package_dir}" || ! -f "${package_dir}/package.json" ]]; then
236+
continue
237+
fi
238+
239+
package_name=$(node -e "console.log(require(process.argv[1]).name)" "${package_dir}/package.json")
240+
package_version=$(node -e "console.log(require(process.argv[1]).version)" "${package_dir}/package.json")
241+
242+
if npm view "${package_name}@${package_version}" version >/dev/null 2>&1; then
243+
echo "Skipping ${package_name}@${package_version} (already published)."
244+
continue
245+
fi
246+
247+
echo "Publishing ${package_name}@${package_version}"
248+
npm publish "${package_dir}" --access public --provenance
96249
done
97250
98251
- name: Publish main package
99252
env:
100253
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
254+
shell: bash
101255
run: |
102-
cd npm
103-
npm publish --access public
256+
set -euo pipefail
257+
258+
package_name=$(node -e "console.log(require(process.argv[1]).name)" "./package.json")
259+
package_version=$(node -e "console.log(require(process.argv[1]).version)" "./package.json")
260+
261+
if npm view "${package_name}@${package_version}" version >/dev/null 2>&1; then
262+
echo "Skipping ${package_name}@${package_version} (already published)."
263+
exit 0
264+
fi
265+
266+
echo "Publishing ${package_name}@${package_version}"
267+
npm publish --access public --provenance
104268
105269
- name: Create GitHub Release
106-
uses: softprops/action-gh-release@v1
270+
uses: softprops/action-gh-release@v2
107271
with:
272+
tag_name: v${{ steps.version.outputs.version }}
273+
generate_release_notes: true
108274
files: |
109275
npm-platform/*/bin/*
110-
body: |
111-
## Installation
112-
```bash
113-
npm install -g @dongowu/git-ai-cli
114-
```
115-
116-
## What's Changed
117-
See commit history for details.
118276
env:
119277
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

0 commit comments

Comments
 (0)