-
Notifications
You must be signed in to change notification settings - Fork 1
335 lines (302 loc) · 13.6 KB
/
Copy pathrelease-fork.yml
File metadata and controls
335 lines (302 loc) · 13.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
# ============================================================================
# 📦 Release · Fork Build
# ----------------------------------------------------------------------------
# Purpose : Build opencode CLI binaries (linux / macos / windows) for the
# LeXwDeX/opencode fork. Stripped-down version of upstream
# publish.yml — removes repo guard, Blacksmith runners, code
# signing, npm publish, and Tauri desktop.
# Trigger : Manual workflow_dispatch (PRIMARY) — pick main or dev
# Push to main/dev ONLY registers the workflow in the Actions UI
# (the build job is gated on `github.event_name == 'workflow_dispatch'`)
# Version : Independent GraphAgent SemVer derived only from graphagent-v* tags.
# dev builds the next stable version as X.Y.Z-dev.N; main publishes
# X.Y.Z and marks it Latest. OpenCode package versions are ignored.
# Inputs : create_release — when true, create a GitHub Release with the
# built binaries + SHA256SUMS attached. Builds
# from `dev` are marked prerelease (test build);
# `main` builds are formal and become Latest.
# platforms — comma-separated subset of linux,macos,windows
# to build. Leave blank to build all three.
# Jobs : package-templates — package latest reference templates from the
# opencode-dag-config repo into a release asset
# build-cli — 3-OS matrix, bundles ripgrep + single-file binary
# release — optional, creates GitHub Release from build-cli artifacts
# register — no-op for push triggers, just registers in Actions UI
# Output : Artifacts: opencode-{linux,macos,windows}.{tar.gz,zip} +
# dag-templates.tar.gz + SHA256SUMS
# ============================================================================
name: 📦 Release · Fork Build
on:
# Manual trigger — the primary way to build releases
workflow_dispatch:
inputs:
create_release:
description: "Create a GitHub Release with the built binaries"
required: false
type: boolean
default: true
platforms:
description: "Platforms to build, comma-separated (linux,macos,windows). Leave blank for all."
required: false
type: string
# Also run on push to main/dev so the workflow registers in Actions UI
push:
branches:
- main
- dev
paths:
- ".github/workflows/release-fork.yml"
permissions:
contents: write
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: false
concurrency:
group: release-fork
cancel-in-progress: false
jobs:
version:
name: Resolve GraphAgent Version
if: github.event_name == 'workflow_dispatch'
runs-on: ubuntu-latest
outputs:
channel: ${{ steps.release-version.outputs.channel }}
version: ${{ steps.release-version.outputs.version }}
tag: ${{ steps.release-version.outputs.tag }}
prerelease: ${{ steps.release-version.outputs.prerelease }}
latest: ${{ steps.release-version.outputs.latest }}
previous_tag: ${{ steps.release-version.outputs.previous_tag }}
steps:
- name: Checkout Repository
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Bun
uses: ./.github/actions/setup-bun
with:
save-cache: false
- name: Resolve Version
id: release-version
run: bun run ./packages/opencode/script/release-version.ts
# Package the latest reference templates from the dedicated config repo
# (LeXwDeX/opencode-dag-config) into a release asset. dev/main do not manage
# these templates anymore — the config repo is the single source of truth.
# Read-only: no commits, no pushes, so branch protection never blocks it.
#
# Validate-before-package: the releasing runtime commit runs its directory
# validator against the config repo HEAD BEFORE any copy/package step. Any
# invalid template — or an unavailable validator — fails the job (fail
# closed), so an unchecked archive can never be uploaded or embedded.
package-templates:
name: Package Reference Templates
if: github.event_name == 'workflow_dispatch'
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout Runtime (releasing commit)
uses: actions/checkout@v4
- name: Clone Config Repo
uses: actions/checkout@v4
with:
repository: LeXwDeX/opencode-dag-config
path: dag-config
- name: Setup Bun
uses: ./.github/actions/setup-bun
with:
save-cache: false
- name: Install Runtime Dependencies
run: bun install --frozen-lockfile
- name: Validate and Package Templates (fail closed)
working-directory: packages/opencode
run: |
echo "Packaging config commit $(git -C "$GITHUB_WORKSPACE/dag-config" rev-parse HEAD) with runtime commit $(git rev-parse HEAD)"
bun run script/package-dag-templates.ts "$GITHUB_WORKSPACE/dag-config" "$GITHUB_WORKSPACE/dag-templates.tar.gz"
- name: Upload Templates Artifact
uses: actions/upload-artifact@v4
with:
name: dag-templates
path: dag-templates.tar.gz
retention-days: 7
build-cli:
name: Build CLI (${{ matrix.name }})
needs: [version, package-templates]
# Skip the actual build when triggered by push (registration-only). Per-
# matrix-entry platform filtering can't live here — `matrix` isn't in
# scope for a job-level `if:` — so it's applied to each step below instead.
if: github.event_name == 'workflow_dispatch'
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-latest
name: linux
- os: macos-latest
name: macos
- os: windows-latest
name: windows
runs-on: ${{ matrix.os }}
defaults:
run:
shell: bash
steps:
- name: Checkout Repository
if: inputs.platforms == '' || contains(inputs.platforms, matrix.name)
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Bun
if: inputs.platforms == '' || contains(inputs.platforms, matrix.name)
uses: ./.github/actions/setup-bun
with:
# Linux and Windows bun caches are each owned by a single saver
# elsewhere (ci-typecheck.yml linux, ci-test.yml e2e windows) to
# avoid racing on the same {OS}-bun-{hash} key when this manual
# release build runs concurrently with a push-triggered CI run.
# macOS has no other job in the repo, so it's safe to save here.
save-cache: ${{ matrix.name == 'macos' }}
# Embed a models.dev catalog snapshot into the binary so air-gapped
# users can start opencode without reaching https://models.dev at
# runtime (see packages/opencode/script/generate.ts fallback order).
- name: Fetch models.dev Snapshot
if: inputs.platforms == '' || contains(inputs.platforms, matrix.name)
run: |
snapshot_path="$RUNNER_TEMP/models-dev-api.json"
if command -v cygpath &>/dev/null; then
snapshot_path="$(cygpath -m "$snapshot_path")"
fi
for attempt in 1 2 3; do
if curl -fsSL --max-time 30 https://models.dev/api.json -o "$snapshot_path"; then
echo "models.dev snapshot downloaded (attempt $attempt)"
echo "MODELS_DEV_API_JSON=$snapshot_path" >> "$GITHUB_ENV"
exit 0
fi
echo "models.dev download failed (attempt $attempt), retrying..."
sleep 5
done
echo "::warning::Failed to download models.dev api.json; build will fall back to @opencode-ai/models snapshot or an empty catalog"
# Embed the latest DAG reference templates into the binary so air-gapped
# installs ship the curated workflows (see dag/workflows.ts builtin scope
# and script/generate.ts DAG_TEMPLATES_DIR loading).
- name: Download Templates Artifact
if: inputs.platforms == '' || contains(inputs.platforms, matrix.name)
uses: actions/download-artifact@v4
with:
name: dag-templates
path: dag-templates-artifact
- name: Extract Templates
if: inputs.platforms == '' || contains(inputs.platforms, matrix.name)
run: |
mkdir -p dag-templates-src
tar -xzf dag-templates-artifact/dag-templates.tar.gz -C dag-templates-src
templates_dir="$GITHUB_WORKSPACE/dag-templates-src"
if command -v cygpath &>/dev/null; then
templates_dir="$(cygpath -m "$templates_dir")"
fi
echo "DAG_TEMPLATES_DIR=$templates_dir" >> "$GITHUB_ENV"
- name: Build CLI
if: inputs.platforms == '' || contains(inputs.platforms, matrix.name)
run: ./packages/opencode/script/build.ts --single --skip-install
env:
OPENCODE_CHANNEL: ${{ needs.version.outputs.channel == 'main' && 'latest' || 'dev' }}
OPENCODE_VERSION: ${{ needs.version.outputs.version }}
# Bundle ripgrep into each dist/opencode-*/bin so air-gapped users do not
# hit the runtime download in packages/core/src/ripgrep/binary.ts.
- name: Prefetch Ripgrep
if: inputs.platforms == '' || contains(inputs.platforms, matrix.name)
run: bun run ./packages/opencode/script/prefetch-ripgrep.ts
- name: Package Artifacts
if: inputs.platforms == '' || contains(inputs.platforms, matrix.name)
working-directory: packages/opencode/dist
run: |
for dir in opencode-*/; do
base="${dir%/}"
if [[ "$base" == *linux* ]]; then
bun run ../script/package-cli-artifact.ts "$base" "${base}.tar.gz"
else
bun run ../script/package-cli-artifact.ts "$base" "${base}.zip"
fi
done
# #498 B2: macOS release acceptance — after the installer-style xattr +
# ad-hoc re-sign mutation, assert codesign validity and executable smoke.
# The installed binary's hash is intentionally NOT compared to the
# archive payload (ad-hoc re-signing can rewrite bytes, so byte equality
# is not a stable signature-validity boundary and differing hashes are
# legitimate); no post-sign digest.
- name: macOS Install Acceptance
if: matrix.name == 'macos' && (inputs.platforms == '' || contains(inputs.platforms, matrix.name))
run: bash script/oc-macos-acceptance.test.sh packages/opencode/dist/opencode-darwin-arm64.zip
timeout-minutes: 10
- name: Upload Artifacts
if: inputs.platforms == '' || contains(inputs.platforms, matrix.name)
uses: actions/upload-artifact@v4
with:
name: opencode-${{ matrix.name }}
path: |
packages/opencode/dist/*.tar.gz
packages/opencode/dist/*.zip
release:
name: Create GitHub Release
needs: [version, build-cli, package-templates]
if: inputs.create_release
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Download Artifacts
uses: actions/download-artifact@v4
with:
path: release-assets
merge-multiple: true
- name: Generate SHA256SUMS
working-directory: release-assets
run: |
shasum -a 256 * > SHA256SUMS || sha256sum * > SHA256SUMS
echo "--- SHA256SUMS ---"
cat SHA256SUMS
- name: Setup Bun
uses: ./.github/actions/setup-bun
with:
save-cache: false
# Render + validate the per-series notes file (.github/releases/vX.Y.Z.md)
# BEFORE creating the release. Fail closed: a missing or invalid series
# file stops the job here, so a release can never ship with placeholder
# notes. The script derives the series filename from --version; the
# workflow passes only primitives. Rendered notes go to RUNNER_TEMP and
# are never attached as a release asset.
- name: Render Release Notes (fail closed)
run: |
bun run ./packages/opencode/script/release-notes.ts \
--notes-dir ".github/releases" \
--version "${{ needs.version.outputs.version }}" \
--channel "${{ needs.version.outputs.channel }}" \
--branch "${{ github.ref_name }}" \
--tag "${{ needs.version.outputs.tag }}" \
--previous-tag "${{ needs.version.outputs.previous_tag }}" \
--repo "${{ github.repository }}" \
--out "$RUNNER_TEMP/RELEASE_NOTES.md"
- name: Create GitHub Release
env:
GH_TOKEN: ${{ github.token }}
# dev releases are prereleases and can never become Latest. main
# releases are formal and are explicitly promoted to Latest.
run: |
EXTRA_FLAGS=()
if [ "${{ needs.version.outputs.channel }}" = "main" ]; then
EXTRA_FLAGS+=(--latest)
else
EXTRA_FLAGS+=(--prerelease --latest=false)
fi
gh release create "${{ needs.version.outputs.tag }}" \
--title "OpenCode GraphAgent v${{ needs.version.outputs.version }}" \
--notes-file "$RUNNER_TEMP/RELEASE_NOTES.md" \
--target "${{ github.sha }}" \
"${EXTRA_FLAGS[@]}" \
release-assets/*
# No-op job for push-triggered runs — just registers the workflow in Actions UI
register:
name: Register Workflow
if: github.event_name == 'push'
runs-on: ubuntu-latest
steps:
- name: Register Workflow
run: echo "Workflow registered in Actions UI"