Compare commits

...

2 Commits

Author SHA1 Message Date
Brendan Allan
28cb8efa4b Merge branch 'dev' into brendan/cli-codesign 2026-03-25 13:15:32 +08:00
Brendan Allan
b0bd728275 codesign cli on macos by building it on macos 2026-03-25 13:14:04 +08:00
3 changed files with 167 additions and 8 deletions

View File

@@ -67,7 +67,7 @@ jobs:
tag: ${{ steps.version.outputs.tag }}
repo: ${{ steps.version.outputs.repo }}
build-cli:
build-cli-linux-win:
needs: version
runs-on: blacksmith-4vcpu-ubuntu-2404
if: github.repository == 'anomalyco/opencode'
@@ -94,17 +94,111 @@ jobs:
OPENCODE_RELEASE: ${{ needs.version.outputs.release }}
GH_REPO: ${{ needs.version.outputs.repo }}
GH_TOKEN: ${{ steps.committer.outputs.token }}
OPENCODE_BUILD_OS: linux,win32
OPENCODE_SKIP_RELEASE_UPLOAD: "1"
- uses: actions/upload-artifact@v4
with:
name: opencode-cli-linux-win
path: packages/opencode/dist
build-cli-darwin:
needs: version
runs-on: macos-latest
if: github.repository == 'anomalyco/opencode'
steps:
- uses: actions/checkout@v3
with:
fetch-tags: true
- uses: ./.github/actions/setup-bun
- name: Setup git committer
id: committer
uses: ./.github/actions/setup-git-committer
with:
opencode-app-id: ${{ vars.OPENCODE_APP_ID }}
opencode-app-secret: ${{ secrets.OPENCODE_APP_SECRET }}
- uses: apple-actions/import-codesign-certs@v2
with:
keychain: build
p12-file-base64: ${{ secrets.APPLE_CERTIFICATE }}
p12-password: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
- name: Resolve signing identity
run: |
CERT_INFO=$(security find-identity -v -p codesigning build.keychain | grep "Developer ID Application")
CERT_ID=$(echo "$CERT_INFO" | awk -F'"' '{print $2}')
if [ -z "$CERT_ID" ]; then
echo "Developer ID Application identity not found"
exit 1
fi
echo "CERT_ID=$CERT_ID" >> $GITHUB_ENV
- name: Build
id: build
run: |
./packages/opencode/script/build.ts
env:
OPENCODE_VERSION: ${{ needs.version.outputs.version }}
OPENCODE_RELEASE: ${{ needs.version.outputs.release }}
GH_REPO: ${{ needs.version.outputs.repo }}
GH_TOKEN: ${{ steps.committer.outputs.token }}
APPLE_SIGNING_IDENTITY: ${{ env.CERT_ID }}
OPENCODE_BUILD_OS: darwin
OPENCODE_SKIP_RELEASE_UPLOAD: "1"
- name: Verify darwin signatures
run: |
for file in packages/opencode/dist/opencode-darwin-*/bin/opencode; do
codesign -vvv --verify "$file"
done
- uses: actions/upload-artifact@v4
with:
name: opencode-cli-darwin
path: packages/opencode/dist
build-cli-merge:
needs:
- version
- build-cli-linux-win
- build-cli-darwin
runs-on: blacksmith-4vcpu-ubuntu-2404
if: github.repository == 'anomalyco/opencode'
steps:
- uses: actions/checkout@v3
- uses: ./.github/actions/setup-bun
- name: Setup git committer
id: committer
uses: ./.github/actions/setup-git-committer
with:
opencode-app-id: ${{ vars.OPENCODE_APP_ID }}
opencode-app-secret: ${{ secrets.OPENCODE_APP_SECRET }}
- uses: actions/download-artifact@v4
with:
pattern: opencode-cli-*
path: packages/opencode/dist
merge-multiple: true
- name: Upload CLI release assets
if: needs.version.outputs.release
run: gh release upload v${{ needs.version.outputs.version }} ./packages/opencode/dist/*.zip ./packages/opencode/dist/*.tar.gz --clobber --repo ${{ needs.version.outputs.repo }}
env:
GH_TOKEN: ${{ steps.committer.outputs.token }}
- uses: actions/upload-artifact@v4
with:
name: opencode-cli
path: packages/opencode/dist
outputs:
version: ${{ needs.version.outputs.version }}
build-tauri:
needs:
- build-cli
- build-cli-merge
- version
continue-on-error: false
strategy:
@@ -248,7 +342,7 @@ jobs:
build-electron:
needs:
- build-cli
- build-cli-merge
- version
continue-on-error: false
strategy:
@@ -372,7 +466,7 @@ jobs:
publish:
needs:
- version
- build-cli
- build-cli-merge
- build-tauri
- build-electron
runs-on: blacksmith-4vcpu-ubuntu-2404

View File

@@ -63,6 +63,10 @@ console.log(`Loaded ${migrations.length} migrations`)
const singleFlag = process.argv.includes("--single")
const baselineFlag = process.argv.includes("--baseline")
const skipInstall = process.argv.includes("--skip-install")
const skipUpload = process.argv.includes("--skip-release-upload") || process.env.OPENCODE_SKIP_RELEASE_UPLOAD === "1"
const sign = process.env.APPLE_SIGNING_IDENTITY
const entitlements = process.env.OPENCODE_CODESIGN_ENTITLEMENTS || path.join(dir, "script/entitlements.plist")
const raw = process.env.OPENCODE_BUILD_OS?.trim()
const allTargets: {
os: string
@@ -148,6 +152,31 @@ const targets = singleFlag
})
: allTargets
const os = raw
? Array.from(
new Set(
raw
.split(",")
.map((x) => x.trim())
.filter(Boolean),
),
)
: undefined
if (os) {
const set = new Set(allTargets.map((item) => item.os))
const bad = os.filter((item) => !set.has(item))
if (bad.length > 0) {
throw new Error(`Invalid OPENCODE_BUILD_OS value: ${bad.join(", ")}`)
}
}
const list = os ? targets.filter((item) => os.includes(item.os)) : targets
if (list.length === 0) {
throw new Error("No build targets selected")
}
await $`rm -rf dist`
const binaries: Record<string, string> = {}
@@ -155,7 +184,7 @@ if (!skipInstall) {
await $`bun install --os="*" --cpu="*" @opentui/core@${pkg.dependencies["@opentui/core"]}`
await $`bun install --os="*" --cpu="*" @parcel/watcher@${pkg.dependencies["@parcel/watcher"]}`
}
for (const item of targets) {
for (const item of list) {
const name = [
pkg.name,
// changing to win32 flags npm for some reason
@@ -203,6 +232,24 @@ for (const item of targets) {
},
})
if (item.os === "darwin") {
if (Script.release && process.platform !== "darwin") {
throw new Error("darwin release binaries must be built on macOS runners")
}
if (Script.release && !sign) {
throw new Error("APPLE_SIGNING_IDENTITY is required for darwin release binaries")
}
if (process.platform === "darwin" && sign) {
if (!fs.existsSync(entitlements)) {
throw new Error(`Codesign entitlements file not found: ${entitlements}`)
}
const file = `dist/${name}/bin/opencode`
console.log(`codesigning ${name}`)
await $`codesign --entitlements ${entitlements} -vvvv --deep --sign ${sign} ${file} --force`
await $`codesign -vvv --verify ${file}`
}
}
// Smoke test: only run if binary is for current platform
if (item.os === process.platform && item.arch === process.arch && !item.abi) {
const binaryPath = `dist/${name}/bin/opencode`
@@ -240,7 +287,9 @@ if (Script.release) {
await $`zip -r ../../${key}.zip *`.cwd(`dist/${key}/bin`)
}
}
await $`gh release upload v${Script.version} ./dist/*.zip ./dist/*.tar.gz --clobber --repo ${process.env.GH_REPO}`
if (!skipUpload) {
await $`gh release upload v${Script.version} ./dist/*.zip ./dist/*.tar.gz --clobber --repo ${process.env.GH_REPO}`
}
}
export { binaries }

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
<key>com.apple.security.cs.disable-executable-page-protection</key>
<true/>
<key>com.apple.security.cs.allow-dyld-environment-variables</key>
<true/>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
</dict>
</plist>