ci: migrate binaries to GitHub Release + Actions CI
- Add .github/workflows/build-binaries.yml (Go cross-compile → preset release) - installer.ts: download from GitHub Release, fallback to local bin/ - package.json: exclude binaries from npm (16.3MB → 161KB) - .gitignore: stop tracking bin/codeagent-wrapper-* - git rm --cached 6 pre-compiled binaries
This commit is contained in:
1 parent
5769a1dbe6
commit
968cbedb8a
4 files changed
+130
-12
No files matched your search
@@ -0,0 +1,74 @@
|
||||
name: Build codeagent-wrapper binaries
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- 'codeagent-wrapper/**'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '1.21'
|
||||
|
||||
- name: Cross-compile binaries
|
||||
working-directory: codeagent-wrapper
|
||||
run: |
|
||||
set -e
|
||||
mkdir -p ../artifacts
|
||||
|
||||
declare -a targets=(
|
||||
"darwin:amd64:"
|
||||
"darwin:arm64:"
|
||||
"linux:amd64:"
|
||||
"linux:arm64:"
|
||||
"windows:amd64:.exe"
|
||||
"windows:arm64:.exe"
|
||||
)
|
||||
|
||||
for target in "${targets[@]}"; do
|
||||
IFS=':' read -r os arch ext <<< "$target"
|
||||
output="codeagent-wrapper-${os}-${arch}${ext}"
|
||||
echo "::group::Building ${output}"
|
||||
GOOS=$os GOARCH=$arch go build -ldflags="-s -w" -o "../artifacts/${output}" .
|
||||
echo "::endgroup::"
|
||||
done
|
||||
|
||||
echo "### Build artifacts" >> $GITHUB_STEP_SUMMARY
|
||||
ls -lh ../artifacts/ | awk 'NR>1{printf "- `%s` (%s)\n", $NF, $5}' >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
- name: Delete existing preset release
|
||||
run: gh release delete preset --yes --cleanup-tag 2>/dev/null || true
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
|
||||
- name: Create preset release
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
tag_name: preset
|
||||
name: "Pre-built Binaries (codeagent-wrapper)"
|
||||
body: |
|
||||
Pre-compiled `codeagent-wrapper` binaries for all supported platforms.
|
||||
Automatically downloaded during `npx ccg-workflow` installation.
|
||||
|
||||
| File | Platform | Architecture |
|
||||
|------|----------|-------------|
|
||||
| `codeagent-wrapper-darwin-amd64` | macOS | Intel x64 |
|
||||
| `codeagent-wrapper-darwin-arm64` | macOS | Apple Silicon |
|
||||
| `codeagent-wrapper-linux-amd64` | Linux | x64 |
|
||||
| `codeagent-wrapper-linux-arm64` | Linux | ARM64 |
|
||||
| `codeagent-wrapper-windows-amd64.exe` | Windows | x64 |
|
||||
| `codeagent-wrapper-windows-arm64.exe` | Windows | ARM64 |
|
||||
|
||||
> This release is automatically updated when `codeagent-wrapper/` source changes.
|
||||
files: artifacts/*
|
||||
prerelease: true
|
||||
make_latest: false
|
||||
+3
-3
@@ -2,10 +2,10 @@
|
||||
codeagent-wrapper/codeagent-wrapper
|
||||
codeagent-wrapper/*.exe
|
||||
*.exe
|
||||
|
||||
# 但是允许 bin/ 目录下的预编译二进制文件
|
||||
!bin/*.exe
|
||||
dist/
|
||||
|
||||
# Pre-compiled binaries (hosted on GitHub Release, not tracked in git)
|
||||
bin/codeagent-wrapper-*
|
||||
node_modules/
|
||||
|
||||
# Python
|
||||
|
||||
+1
-1
@@ -25,7 +25,7 @@
|
||||
"module": "dist/index.mjs",
|
||||
"types": "dist/index.d.mts",
|
||||
"files": [
|
||||
"bin",
|
||||
"bin/ccg.mjs",
|
||||
"dist",
|
||||
"templates/commands/analyze.md",
|
||||
"templates/commands/backend.md",
|
||||
|
||||
+52
-8
@@ -7,6 +7,11 @@ import { parse as parseToml, stringify as stringifyToml } from 'smol-toml'
|
||||
import { backupClaudeCodeConfig, buildMcpServerConfig, fixWindowsMcpConfig, mergeMcpServers, readClaudeCodeConfig, writeClaudeCodeConfig } from './mcp'
|
||||
import { isWindows } from './platform'
|
||||
|
||||
// GitHub Release download config
|
||||
const GITHUB_REPO = 'fengshao1227/ccg-workflow'
|
||||
const RELEASE_TAG = 'preset'
|
||||
const BINARY_DOWNLOAD_URL = `https://github.com/${GITHUB_REPO}/releases/download/${RELEASE_TAG}`
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url)
|
||||
const __dirname = dirname(__filename)
|
||||
|
||||
@@ -24,6 +29,31 @@ function findPackageRoot(startDir: string): string {
|
||||
|
||||
const PACKAGE_ROOT = findPackageRoot(__dirname)
|
||||
|
||||
/**
|
||||
* Download codeagent-wrapper binary from GitHub Release.
|
||||
* Uses the fixed `preset` tag release for pre-compiled binaries.
|
||||
* Supports redirect-following (GitHub releases redirect to CDN).
|
||||
*/
|
||||
async function downloadBinaryFromRelease(binaryName: string, destPath: string): Promise<boolean> {
|
||||
const url = `${BINARY_DOWNLOAD_URL}/${binaryName}`
|
||||
|
||||
// Use dynamic import for https to follow redirects manually (Node.js fetch follows automatically)
|
||||
const response = await fetch(url, { redirect: 'follow' })
|
||||
if (!response.ok) {
|
||||
return false
|
||||
}
|
||||
|
||||
const buffer = Buffer.from(await response.arrayBuffer())
|
||||
await fs.writeFile(destPath, buffer)
|
||||
|
||||
// Set executable permission on Unix-like systems
|
||||
if (process.platform !== 'win32') {
|
||||
await fs.chmod(destPath, 0o755)
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// All available commands (20 total after adding spec commands)
|
||||
const ALL_COMMANDS = [
|
||||
'workflow', // 完整6阶段开发工作流
|
||||
@@ -813,16 +843,30 @@ ${workflow.description}
|
||||
return result
|
||||
}
|
||||
|
||||
const srcBinary = join(PACKAGE_ROOT, 'bin', binaryName)
|
||||
const destBinary = join(binDir, platform === 'win32' ? 'codeagent-wrapper.exe' : 'codeagent-wrapper')
|
||||
|
||||
if (await fs.pathExists(srcBinary)) {
|
||||
await fs.copy(srcBinary, destBinary)
|
||||
// Set executable permission on Unix-like systems
|
||||
if (platform !== 'win32') {
|
||||
await fs.chmod(destBinary, 0o755)
|
||||
}
|
||||
// Strategy 1: Download from GitHub Release (preferred)
|
||||
let installed = false
|
||||
try {
|
||||
installed = await downloadBinaryFromRelease(binaryName, destBinary)
|
||||
}
|
||||
catch {
|
||||
// Download failed, will try fallback
|
||||
}
|
||||
|
||||
// Strategy 2: Fallback to local bin/ (development or offline)
|
||||
if (!installed) {
|
||||
const srcBinary = join(PACKAGE_ROOT, 'bin', binaryName)
|
||||
if (await fs.pathExists(srcBinary)) {
|
||||
await fs.copy(srcBinary, destBinary)
|
||||
if (platform !== 'win32') {
|
||||
await fs.chmod(destBinary, 0o755)
|
||||
}
|
||||
installed = true
|
||||
}
|
||||
}
|
||||
|
||||
if (installed) {
|
||||
// Verify installation by running --version
|
||||
try {
|
||||
const { execSync } = await import('node:child_process')
|
||||
@@ -836,7 +880,7 @@ ${workflow.description}
|
||||
}
|
||||
}
|
||||
else {
|
||||
result.errors.push(`Binary not found in package: ${binaryName}`)
|
||||
result.errors.push(`Failed to obtain binary: ${binaryName} (download failed, no local fallback)`)
|
||||
result.success = false
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user