Skip to content

Commit 79d12aa

Browse files
frostebiteclaude
andcommitted
feat(cli): add release workflow, install scripts, and self-update command
Replace the npm-only publish-cli.yml with a comprehensive release-cli.yml that builds standalone binaries via pkg for all platforms (Linux/macOS/Windows, x64/arm64), uploads them as GitHub Release assets with SHA256 checksums, and retains npm publish as an optional job. Add curl-pipe-sh installer (install.sh) and PowerShell installer (install.ps1) for one-liner installation from GitHub Releases. Both scripts auto-detect platform/architecture, verify checksums, and guide PATH configuration. Add `game-ci update` command for self-updating standalone binaries: checks GitHub releases for newer versions, downloads the correct platform binary, verifies it, and atomically replaces the running executable. Distribution strategy: GitHub Releases (primary), npm (optional), with winget/Homebrew/Chocolatey/Scoop as future providers. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 5bdcf12 commit 79d12aa

File tree

12 files changed

+1573
-335
lines changed

12 files changed

+1573
-335
lines changed

.github/workflows/publish-cli.yml

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

.github/workflows/release-cli.yml

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
name: Release CLI
2+
3+
on:
4+
release:
5+
types: [published]
6+
workflow_dispatch:
7+
inputs:
8+
tag:
9+
description: 'Release tag to build (e.g., v2.0.0). Uses latest release if empty.'
10+
required: false
11+
type: string
12+
publish-npm:
13+
description: 'Publish to npm'
14+
required: false
15+
default: false
16+
type: boolean
17+
18+
concurrency:
19+
group: ${{ github.workflow }}-${{ github.event.release.tag_name || inputs.tag || github.ref }}
20+
cancel-in-progress: true
21+
22+
jobs:
23+
build-binaries:
24+
name: Build ${{ matrix.target }}
25+
runs-on: ${{ matrix.os }}
26+
strategy:
27+
fail-fast: false
28+
matrix:
29+
include:
30+
- target: linux-x64
31+
os: ubuntu-latest
32+
pkg-target: node20-linux-x64
33+
binary-name: game-ci-linux-x64
34+
- target: linux-arm64
35+
os: ubuntu-latest
36+
pkg-target: node20-linux-arm64
37+
binary-name: game-ci-linux-arm64
38+
- target: macos-x64
39+
os: macos-latest
40+
pkg-target: node20-macos-x64
41+
binary-name: game-ci-macos-x64
42+
- target: macos-arm64
43+
os: macos-latest
44+
pkg-target: node20-macos-arm64
45+
binary-name: game-ci-macos-arm64
46+
- target: windows-x64
47+
os: windows-latest
48+
pkg-target: node20-win-x64
49+
binary-name: game-ci-windows-x64.exe
50+
steps:
51+
- uses: actions/checkout@v4
52+
with:
53+
ref: ${{ github.event.release.tag_name || inputs.tag || github.ref }}
54+
55+
- uses: actions/setup-node@v4
56+
with:
57+
node-version: '20'
58+
59+
- name: Install dependencies
60+
run: yarn install --frozen-lockfile
61+
62+
- name: Build TypeScript
63+
run: yarn build
64+
65+
- name: Verify CLI before packaging
66+
run: node lib/cli.js version
67+
68+
- name: Build standalone binary
69+
run: npx pkg lib/cli.js --target ${{ matrix.pkg-target }} --output ${{ matrix.binary-name }} --compress GZip
70+
71+
- name: Verify standalone binary (non-cross-compiled)
72+
if: |
73+
(matrix.target == 'linux-x64' && runner.os == 'Linux') ||
74+
(matrix.target == 'macos-arm64' && runner.os == 'macOS' && runner.arch == 'ARM64') ||
75+
(matrix.target == 'macos-x64' && runner.os == 'macOS' && runner.arch == 'X64') ||
76+
(matrix.target == 'windows-x64' && runner.os == 'Windows')
77+
run: ./${{ matrix.binary-name }} version
78+
shell: bash
79+
80+
- uses: actions/upload-artifact@v4
81+
with:
82+
name: binary-${{ matrix.target }}
83+
path: ${{ matrix.binary-name }}
84+
retention-days: 5
85+
86+
create-checksums-and-upload:
87+
name: Checksums and release upload
88+
needs: build-binaries
89+
runs-on: ubuntu-latest
90+
permissions:
91+
contents: write
92+
steps:
93+
- uses: actions/download-artifact@v4
94+
with:
95+
path: binaries
96+
pattern: binary-*
97+
merge-multiple: true
98+
99+
- name: List binaries
100+
run: ls -la binaries/
101+
102+
- name: Generate SHA256 checksums
103+
run: |
104+
cd binaries
105+
sha256sum game-ci-* > checksums.txt
106+
echo "=== checksums.txt ==="
107+
cat checksums.txt
108+
109+
- name: Determine release tag
110+
id: tag
111+
run: |
112+
if [ "${{ github.event_name }}" = "release" ]; then
113+
echo "tag=${{ github.event.release.tag_name }}" >> "$GITHUB_OUTPUT"
114+
elif [ -n "${{ inputs.tag }}" ]; then
115+
echo "tag=${{ inputs.tag }}" >> "$GITHUB_OUTPUT"
116+
else
117+
echo "No release tag available. Skipping upload."
118+
echo "tag=" >> "$GITHUB_OUTPUT"
119+
fi
120+
121+
- name: Upload binaries to release
122+
if: steps.tag.outputs.tag != ''
123+
env:
124+
GH_TOKEN: ${{ github.token }}
125+
run: |
126+
cd binaries
127+
for f in game-ci-* checksums.txt; do
128+
echo "Uploading $f..."
129+
gh release upload "${{ steps.tag.outputs.tag }}" "$f" \
130+
--repo "${{ github.repository }}" \
131+
--clobber
132+
done
133+
134+
publish-npm:
135+
name: Publish to npm
136+
needs: build-binaries
137+
runs-on: ubuntu-latest
138+
if: >-
139+
(github.event_name == 'release') || (github.event_name == 'workflow_dispatch' && inputs.publish-npm)
140+
permissions:
141+
contents: read
142+
id-token: write
143+
steps:
144+
- uses: actions/checkout@v4
145+
with:
146+
ref: ${{ github.event.release.tag_name || inputs.tag || github.ref }}
147+
148+
- uses: actions/setup-node@v4
149+
with:
150+
node-version: '20'
151+
registry-url: 'https://registry.npmjs.org'
152+
153+
- name: Install dependencies
154+
run: yarn install --frozen-lockfile
155+
156+
- name: Build
157+
run: yarn build
158+
159+
- name: Run tests
160+
run: yarn test
161+
162+
- name: Verify CLI
163+
run: |
164+
node lib/cli.js version
165+
node lib/cli.js --help
166+
167+
- name: Publish to npm
168+
run: npm publish --provenance --access public
169+
env:
170+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

0 commit comments

Comments
 (0)