Skip to content

Commit 36c2b96

Browse files
committed
feat(cli): make bitfun the cross-platform primary command
1 parent cff39a1 commit 36c2b96

44 files changed

Lines changed: 1425 additions & 329 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.github/workflows/ci.yml‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,11 @@ jobs:
169169
- name: Check core boundaries
170170
run: node --test scripts/check-core-boundaries.test.mjs
171171

172+
- name: Validate CLI install and package contracts
173+
run: |
174+
node scripts/install-cli.test.mjs
175+
node scripts/cli/package-contract.test.mjs
176+
172177
- name: Install dependencies
173178
run: pnpm install --frozen-lockfile
174179

‎.github/workflows/cli-package-manual.yml‎

Lines changed: 44 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,10 @@ on:
1313
- linux-x64
1414
- macos-arm64
1515
- macos-x64
16+
- windows-x64
1617
- all
1718
ubuntu_version:
18-
description: "Ubuntu runner baseline for Linux builds. Ignored for macOS."
19+
description: "Ubuntu runner baseline for Linux builds. Ignored for macOS and Windows."
1920
required: true
2021
default: "22.04"
2122
type: choice
@@ -83,19 +84,22 @@ jobs:
8384
8485
case "${INPUT_PLATFORM}" in
8586
linux-arm64)
86-
MATRIX="{\"platform\":[{\"os\":\"${LINUX_ARM64_RUNNER}\",\"name\":\"linux-arm64-${LINUX_NAME_SUFFIX}\",\"target\":\"aarch64-unknown-linux-gnu\",\"can_smoke_test\":true}]}"
87+
MATRIX="{\"platform\":[{\"os\":\"${LINUX_ARM64_RUNNER}\",\"name\":\"linux-arm64-${LINUX_NAME_SUFFIX}\",\"target\":\"aarch64-unknown-linux-gnu\"}]}"
8788
;;
8889
linux-x64)
89-
MATRIX="{\"platform\":[{\"os\":\"${LINUX_X64_RUNNER}\",\"name\":\"linux-x64-${LINUX_NAME_SUFFIX}\",\"target\":\"x86_64-unknown-linux-gnu\",\"can_smoke_test\":true}]}"
90+
MATRIX="{\"platform\":[{\"os\":\"${LINUX_X64_RUNNER}\",\"name\":\"linux-x64-${LINUX_NAME_SUFFIX}\",\"target\":\"x86_64-unknown-linux-gnu\"}]}"
9091
;;
9192
macos-arm64)
92-
MATRIX='{"platform":[{"os":"macos-15","name":"macos-arm64","target":"aarch64-apple-darwin","can_smoke_test":true}]}'
93+
MATRIX='{"platform":[{"os":"macos-15","name":"macos-arm64","target":"aarch64-apple-darwin"}]}'
9394
;;
9495
macos-x64)
95-
MATRIX='{"platform":[{"os":"macos-15-intel","name":"macos-x64","target":"x86_64-apple-darwin","can_smoke_test":true}]}'
96+
MATRIX='{"platform":[{"os":"macos-15-intel","name":"macos-x64","target":"x86_64-apple-darwin"}]}'
97+
;;
98+
windows-x64)
99+
MATRIX='{"platform":[{"os":"windows-latest","name":"windows-x64","target":"x86_64-pc-windows-msvc"}]}'
96100
;;
97101
all)
98-
MATRIX="{\"platform\":[{\"os\":\"macos-15\",\"name\":\"macos-arm64\",\"target\":\"aarch64-apple-darwin\",\"can_smoke_test\":true},{\"os\":\"macos-15-intel\",\"name\":\"macos-x64\",\"target\":\"x86_64-apple-darwin\",\"can_smoke_test\":true},{\"os\":\"${LINUX_X64_RUNNER}\",\"name\":\"linux-x64-${LINUX_NAME_SUFFIX}\",\"target\":\"x86_64-unknown-linux-gnu\",\"can_smoke_test\":true},{\"os\":\"${LINUX_ARM64_RUNNER}\",\"name\":\"linux-arm64-${LINUX_NAME_SUFFIX}\",\"target\":\"aarch64-unknown-linux-gnu\",\"can_smoke_test\":true}]}"
102+
MATRIX="{\"platform\":[{\"os\":\"macos-15\",\"name\":\"macos-arm64\",\"target\":\"aarch64-apple-darwin\"},{\"os\":\"macos-15-intel\",\"name\":\"macos-x64\",\"target\":\"x86_64-apple-darwin\"},{\"os\":\"${LINUX_X64_RUNNER}\",\"name\":\"linux-x64-${LINUX_NAME_SUFFIX}\",\"target\":\"x86_64-unknown-linux-gnu\"},{\"os\":\"${LINUX_ARM64_RUNNER}\",\"name\":\"linux-arm64-${LINUX_NAME_SUFFIX}\",\"target\":\"aarch64-unknown-linux-gnu\"},{\"os\":\"windows-latest\",\"name\":\"windows-x64\",\"target\":\"x86_64-pc-windows-msvc\"}]}"
99103
;;
100104
*)
101105
echo "Unsupported platform: ${INPUT_PLATFORM}" >&2
@@ -148,87 +152,63 @@ jobs:
148152
shared-key: "cli-manual-v1-${{ matrix.platform.name }}"
149153
cache-bin: false
150154

151-
- name: Build bitfun-cli
155+
- name: Build CLI (Unix)
156+
if: runner.os != 'Windows'
152157
shell: bash
153158
run: |
154159
set -euo pipefail
155160
cargo build --release \
156161
--target ${{ matrix.platform.target }} \
157162
-p bitfun-cli
158163
159-
- name: Smoke test (--version)
160-
if: matrix.platform.can_smoke_test == true
164+
- name: Build CLI (Windows)
165+
if: runner.os == 'Windows'
166+
shell: pwsh
167+
env:
168+
RUSTFLAGS: -C target-feature=+crt-static
169+
run: cargo build --release --target ${{ matrix.platform.target }} -p bitfun-cli
170+
171+
- name: Test installer (Unix)
172+
if: runner.os != 'Windows'
161173
shell: bash
162-
run: |
163-
set -euo pipefail
164-
BIN="target/${{ matrix.platform.target }}/release/bitfun-cli"
165-
"$BIN" --version
166-
"$BIN" --help > /dev/null
174+
env:
175+
CARGO_BUILD_TARGET: ${{ matrix.platform.target }}
176+
run: bash scripts/cli/test-install-unix.sh "${{ matrix.platform.target }}"
167177

168-
- name: Stage tarball
178+
- name: Test installer (Windows)
179+
if: runner.os == 'Windows'
180+
shell: pwsh
181+
env:
182+
CARGO_BUILD_TARGET: ${{ matrix.platform.target }}
183+
RUSTFLAGS: -C target-feature=+crt-static
184+
run: ./scripts/cli/test-install-windows.ps1 -Target $env:CARGO_BUILD_TARGET
185+
186+
- name: Package and smoke test (Unix)
187+
if: runner.os != 'Windows'
169188
id: stage
170189
shell: bash
171190
env:
172191
VERSION: ${{ needs.prepare.outputs.version }}
173192
TARGET: ${{ matrix.platform.target }}
174193
run: |
175194
set -euo pipefail
195+
bash scripts/cli/package-unix.sh "$VERSION" "$TARGET"
176196
177-
STAGE_DIR="$(pwd)/dist-cli/bitfun-cli-${VERSION}-${TARGET}"
178-
mkdir -p "$STAGE_DIR"
179-
180-
cp "target/${TARGET}/release/bitfun-cli" "$STAGE_DIR/"
181-
cp LICENSE "$STAGE_DIR/" || true
182-
cp README.md "$STAGE_DIR/" || true
183-
184-
if [[ -d "src/apps/cli/themes" ]]; then
185-
cp -R "src/apps/cli/themes" "$STAGE_DIR/themes"
186-
fi
187-
if [[ -d "src/apps/cli/prompts" ]]; then
188-
cp -R "src/apps/cli/prompts" "$STAGE_DIR/prompts"
189-
fi
190-
191-
ARCHIVE="bitfun-cli-${VERSION}-${TARGET}.tar.gz"
192-
tar -C "$(dirname "$STAGE_DIR")" -czf "$ARCHIVE" "$(basename "$STAGE_DIR")"
193-
194-
if command -v sha256sum >/dev/null 2>&1; then
195-
sha256sum "$ARCHIVE" > "${ARCHIVE}.sha256"
196-
else
197-
shasum -a 256 "$ARCHIVE" > "${ARCHIVE}.sha256"
198-
fi
199-
200-
echo "archive=$ARCHIVE" >> "$GITHUB_OUTPUT"
201-
echo "checksum=${ARCHIVE}.sha256" >> "$GITHUB_OUTPUT"
202-
203-
- name: Smoke test packaged archive
204-
shell: bash
197+
- name: Package and smoke test (Windows)
198+
if: runner.os == 'Windows'
199+
id: stage-windows
200+
shell: pwsh
205201
env:
206-
ARCHIVE: ${{ steps.stage.outputs.archive }}
207-
CHECKSUM: ${{ steps.stage.outputs.checksum }}
202+
VERSION: ${{ needs.prepare.outputs.version }}
203+
TARGET: ${{ matrix.platform.target }}
208204
run: |
209-
set -euo pipefail
210-
211-
if command -v sha256sum >/dev/null 2>&1; then
212-
sha256sum -c "$CHECKSUM"
213-
else
214-
shasum -a 256 -c "$CHECKSUM"
215-
fi
216-
217-
EXTRACT_DIR="$(mktemp -d)"
218-
trap 'rm -rf "$EXTRACT_DIR"' EXIT
219-
tar -xzf "$ARCHIVE" -C "$EXTRACT_DIR"
220-
221-
shopt -s nullglob
222-
BIN_CANDIDATES=("$EXTRACT_DIR"/*/bitfun-cli)
223-
[[ "${#BIN_CANDIDATES[@]}" -eq 1 ]]
224-
"${BIN_CANDIDATES[0]}" --version
225-
"${BIN_CANDIDATES[0]}" --help > /dev/null
205+
./scripts/cli/package-windows.ps1 -Version $env:VERSION -Target $env:TARGET
226206
227207
- name: Upload artifact
228208
uses: actions/upload-artifact@v6
229209
with:
230210
name: bitfun-cli-${{ needs.prepare.outputs.version }}-${{ needs.prepare.outputs.short_sha }}-${{ matrix.platform.name }}
231211
if-no-files-found: error
232212
path: |
233-
${{ steps.stage.outputs.archive }}
234-
${{ steps.stage.outputs.checksum }}
213+
${{ steps.stage.outputs.archive || steps.stage-windows.outputs.archive }}
214+
${{ steps.stage.outputs.checksum || steps.stage-windows.outputs.checksum }}

0 commit comments

Comments
 (0)