Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
131 changes: 131 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,93 @@ jobs:
outputs:
version: ${{ needs.version.outputs.version }}

sign-cli-windows:
needs:
- build-cli
- version
runs-on: blacksmith-4vcpu-windows-2025
if: github.repository == 'anomalyco/opencode'
steps:
- uses: actions/checkout@v3

- uses: actions/setup-dotnet@v4
with:
dotnet-version: "10.0.x"

- name: Install sign tool
shell: pwsh
run: |
dotnet tool install --tool-path "$env:RUNNER_TEMP\sign" --prerelease sign
"$env:RUNNER_TEMP\sign" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append

- name: Azure login
uses: azure/login@v2
with:
client-id: ${{ vars.AZURE_CLIENT_ID || secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ vars.AZURE_TENANT_ID || secrets.AZURE_TENANT_ID }}
subscription-id: ${{ vars.AZURE_SUBSCRIPTION_ID || secrets.AZURE_SUBSCRIPTION_ID }}

- uses: actions/download-artifact@v4
with:
name: opencode-cli
path: packages/opencode/dist

- name: Sign Windows CLI binaries
shell: pwsh
env:
AZURE_TRUSTED_SIGNING_ACCOUNT_NAME: ${{ vars.AZURE_TRUSTED_SIGNING_ACCOUNT_NAME || secrets.AZURE_TRUSTED_SIGNING_ACCOUNT_NAME }}
AZURE_TRUSTED_SIGNING_CERTIFICATE_PROFILE: ${{ vars.AZURE_TRUSTED_SIGNING_CERTIFICATE_PROFILE || secrets.AZURE_TRUSTED_SIGNING_CERTIFICATE_PROFILE }}
AZURE_TRUSTED_SIGNING_ENDPOINT: ${{ vars.AZURE_TRUSTED_SIGNING_ENDPOINT || secrets.AZURE_TRUSTED_SIGNING_ENDPOINT }}
run: |
./script/sign-windows.ps1 `
"${{ github.workspace }}\packages\opencode\dist\opencode-windows-x64\bin\opencode.exe" `
"${{ github.workspace }}\packages\opencode\dist\opencode-windows-x64-baseline\bin\opencode.exe"

- name: Verify Windows CLI signatures
shell: pwsh
run: |
$files = @(
"${{ github.workspace }}\packages\opencode\dist\opencode-windows-x64\bin\opencode.exe",
"${{ github.workspace }}\packages\opencode\dist\opencode-windows-x64-baseline\bin\opencode.exe"
)

foreach ($file in $files) {
$sig = Get-AuthenticodeSignature $file
if ($sig.Status -ne "Valid") {
throw "Invalid signature for ${file}: $($sig.Status)"
}
}

- name: Repack Windows CLI archives
shell: pwsh
working-directory: packages/opencode/dist
run: |
Compress-Archive -Path "opencode-windows-x64\bin\*" -DestinationPath "opencode-windows-x64.zip" -Force
Compress-Archive -Path "opencode-windows-x64-baseline\bin\*" -DestinationPath "opencode-windows-x64-baseline.zip" -Force

- name: Upload signed Windows CLI release assets
if: needs.version.outputs.release != ''
shell: pwsh
env:
GH_TOKEN: ${{ github.token }}
run: |
gh release upload "v${{ needs.version.outputs.version }}" `
"${{ github.workspace }}\packages\opencode\dist\opencode-windows-x64.zip" `
"${{ github.workspace }}\packages\opencode\dist\opencode-windows-x64-baseline.zip" `
--clobber `
--repo "${{ needs.version.outputs.repo }}"

- uses: actions/upload-artifact@v4
with:
name: opencode-cli-signed-windows
path: |
packages/opencode/dist/opencode-windows-x64
packages/opencode/dist/opencode-windows-x64-baseline

build-tauri:
needs:
- build-cli
- sign-cli-windows
- version
continue-on-error: false
strategy:
Expand Down Expand Up @@ -150,6 +234,26 @@ jobs:

- uses: ./.github/actions/setup-bun

- uses: actions/setup-dotnet@v4
if: runner.os == 'Windows'
with:
dotnet-version: "10.0.x"

- name: Install sign tool
if: runner.os == 'Windows'
shell: pwsh
run: |
dotnet tool install --tool-path "$env:RUNNER_TEMP\sign" --prerelease sign
"$env:RUNNER_TEMP\sign" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append

- name: Azure login
if: runner.os == 'Windows'
uses: azure/login@v2
with:
client-id: ${{ vars.AZURE_CLIENT_ID || secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ vars.AZURE_TENANT_ID || secrets.AZURE_TENANT_ID }}
subscription-id: ${{ vars.AZURE_SUBSCRIPTION_ID || secrets.AZURE_SUBSCRIPTION_ID }}

- name: Cache apt packages
if: contains(matrix.settings.host, 'ubuntu')
uses: actions/cache@v4
Expand Down Expand Up @@ -184,6 +288,7 @@ jobs:
env:
OPENCODE_VERSION: ${{ needs.version.outputs.version }}
GITHUB_TOKEN: ${{ steps.committer.outputs.token }}
OPENCODE_CLI_ARTIFACT: ${{ (runner.os == 'Windows' && 'opencode-cli-signed-windows') || 'opencode-cli' }}
RUST_TARGET: ${{ matrix.settings.target }}
GH_TOKEN: ${{ github.token }}
GITHUB_RUN_ID: ${{ github.run_id }}
Expand Down Expand Up @@ -230,6 +335,9 @@ jobs:
releaseCommitish: ${{ github.sha }}
env:
GITHUB_TOKEN: ${{ steps.committer.outputs.token }}
AZURE_TRUSTED_SIGNING_ACCOUNT_NAME: ${{ vars.AZURE_TRUSTED_SIGNING_ACCOUNT_NAME || secrets.AZURE_TRUSTED_SIGNING_ACCOUNT_NAME }}
AZURE_TRUSTED_SIGNING_CERTIFICATE_PROFILE: ${{ vars.AZURE_TRUSTED_SIGNING_CERTIFICATE_PROFILE || secrets.AZURE_TRUSTED_SIGNING_CERTIFICATE_PROFILE }}
AZURE_TRUSTED_SIGNING_ENDPOINT: ${{ vars.AZURE_TRUSTED_SIGNING_ENDPOINT || secrets.AZURE_TRUSTED_SIGNING_ENDPOINT }}
TAURI_BUNDLER_NEW_APPIMAGE_FORMAT: true
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
Expand All @@ -240,10 +348,28 @@ jobs:
APPLE_API_KEY: ${{ secrets.APPLE_API_KEY }}
APPLE_API_KEY_PATH: ${{ runner.temp }}/apple-api-key.p8

- name: Verify signed Windows desktop artifacts
if: runner.os == 'Windows'
shell: pwsh
run: |
$files = @(
"${{ github.workspace }}\packages\desktop\src-tauri\sidecars\opencode-cli-${{ matrix.settings.target }}.exe",
"${{ github.workspace }}\packages\desktop\src-tauri\target\${{ matrix.settings.target }}\release\OpenCode.exe"
)
$files += Get-ChildItem "${{ github.workspace }}\packages\desktop\src-tauri\target\${{ matrix.settings.target }}\release\bundle\nsis\*.exe" | Select-Object -ExpandProperty FullName

foreach ($file in $files) {
$sig = Get-AuthenticodeSignature $file
if ($sig.Status -ne "Valid") {
throw "Invalid signature for ${file}: $($sig.Status)"
}
}

publish:
needs:
- version
- build-cli
- sign-cli-windows
- build-tauri
runs-on: blacksmith-4vcpu-ubuntu-2404
steps:
Expand Down Expand Up @@ -281,6 +407,11 @@ jobs:
name: opencode-cli
path: packages/opencode/dist

- uses: actions/download-artifact@v4
with:
name: opencode-cli-signed-windows
path: packages/opencode/dist

- name: Cache apt packages (AUR)
uses: actions/cache@v4
with:
Expand Down
54 changes: 0 additions & 54 deletions .github/workflows/sign-cli.yml

This file was deleted.

3 changes: 2 additions & 1 deletion packages/desktop/scripts/prepare.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@ await Bun.write("./package.json", JSON.stringify(pkg, null, 2) + "\n")
console.log(`Updated package.json version to ${Script.version}`)

const sidecarConfig = getCurrentSidecar()
const artifact = Bun.env.OPENCODE_CLI_ARTIFACT ?? "opencode-cli"

const dir = "src-tauri/target/opencode-binaries"

await $`mkdir -p ${dir}`
await $`gh run download ${Bun.env.GITHUB_RUN_ID} -n opencode-cli`.cwd(dir)
await $`gh run download ${Bun.env.GITHUB_RUN_ID} -n ${artifact}`.cwd(dir)

await copyBinaryToSidecarFolder(windowsify(`${dir}/${sidecarConfig.ocBinary}/bin/opencode`))
4 changes: 4 additions & 0 deletions packages/desktop/src-tauri/tauri.beta.conf.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
"icons/beta/icon.ico"
],
"windows": {
"signCommand": {
"cmd": "powershell",
"args": ["-ExecutionPolicy", "Bypass", "-File", "../../../script/sign-windows.ps1", "%1"]
},
"nsis": {
"installerIcon": "icons/beta/icon.ico"
}
Expand Down
4 changes: 4 additions & 0 deletions packages/desktop/src-tauri/tauri.conf.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@
"entitlements": "./entitlements.plist"
},
"windows": {
"signCommand": {
"cmd": "powershell",
"args": ["-ExecutionPolicy", "Bypass", "-File", "../../../script/sign-windows.ps1", "%1"]
},
"nsis": {
"installerIcon": "icons/dev/icon.ico",
"headerImage": "assets/nsis-header.bmp",
Expand Down
4 changes: 4 additions & 0 deletions packages/desktop/src-tauri/tauri.prod.conf.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
"icons/prod/icon.ico"
],
"windows": {
"signCommand": {
"cmd": "powershell",
"args": ["-ExecutionPolicy", "Bypass", "-File", "../../../script/sign-windows.ps1", "%1"]
},
"nsis": {
"installerIcon": "icons/prod/icon.ico"
}
Expand Down
51 changes: 51 additions & 0 deletions script/sign-windows.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
param(
[Parameter(ValueFromRemainingArguments = $true)]
[string[]] $Path
)

$ErrorActionPreference = "Stop"

if (-not $Path -or $Path.Count -eq 0) {
throw "At least one path is required"
}

$vars = @{
endpoint = $env:AZURE_TRUSTED_SIGNING_ENDPOINT
account = $env:AZURE_TRUSTED_SIGNING_ACCOUNT_NAME
profile = $env:AZURE_TRUSTED_SIGNING_CERTIFICATE_PROFILE
}

if ($vars.Values | Where-Object { -not $_ }) {
Write-Host "Skipping Windows signing because Trusted Signing is not configured"
exit 0
}

if (-not (Get-Command sign -ErrorAction SilentlyContinue)) {
Write-Host "Skipping Windows signing because sign was not found on PATH"
exit 0
}

$files = $Path | ForEach-Object { Resolve-Path $_ } | Select-Object -ExpandProperty Path -Unique

if (-not $files -or $files.Count -eq 0) {
throw "No files matched the requested paths"
}

$groups = $files | Group-Object { Split-Path $_ -Parent }

foreach ($group in $groups) {
$dir = $group.Name
$names = $group.Group | ForEach-Object { Split-Path $_ -Leaf }

& sign code trusted-signing `
-b $dir `
-tse $vars.endpoint `
-tscp $vars.profile `
-tsa $vars.account `
@names `
-v Information

if ($LASTEXITCODE -ne 0) {
throw "Trusted Signing failed for $($group.Name)"
}
}
Loading