summaryrefslogtreecommitdiff
path: root/opencode.spec
blob: 78b19729d57504c4e787b0e9ed10a293d8ea90ef (plain)
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
# Source build of opencode 1.19.5 for openEuler 24.03 LTS SP4 (x86_64).
#
# Adapted from the openEuler EUR reference SRPM (user_76c6f026/oed-opencode-2509,
# opencode-1.19.5-1), which itself was rebuilt from the 24.03 LTS SP4 source
# build. The EUR upload endpoint rejects SRPMs of a few MB, so the reference
# spec fetched the upstream archive in %prep from a reachable GitHub proxy.
# This COPR build ships the archive in the SRPM instead (Source0) and %prep
# prefers it, so the build does not depend on a proxy being reachable. The
# build chroot has no network access at all, so Node.js (Source2), Bun
# (Source3) and the resolved npm dependency tree (Source4) are shipped in the
# SRPM as well. The models.dev snapshot is small enough to ship compressed in
# the SRPM (Source1), keeping the build off the models.dev network API.
#
# The upstream source is pruned to the CLI + embedded Web UI workspace closure
# (console/stats/desktop/docs/web/storybook/slack/identity/containers/cli/
# sdk-next/function removed). The ghostty-web dependency, which upstream pins
# to a GitHub commit, is switched to the published 0.3.0 npm package so the
# build does not need GitHub access.
#
# topdir: opencode-1.19.5

# Bun's single-file output embeds the version metadata in ELF sections; any
# strip (find-debuginfo/brp-strip) removes them and makes `opencode --version`
# fall back to the Bun runtime default, so both are disabled.
%global debug_package %{nil}
%global __strip /bin/true

%global node_version 24.18.0
%global node_sha256 55aa7153f9d88f28d765fcdad5ae6945b5c0f98a36881703817e4c450fa76742
%global bun_version 1.4.4
%global bun_sha256 93ca5a2abe45f3bcac6dd55baff8bb06c4ac824b70f89650b54e5c8b80dbef18

%global src_proxy https://ghfast.top/https://github.com/anomalyco/opencode/archive/refs/tags/v1.19.5.tar.gz

Name:           opencode
Version:        1.19.5
Release:        3%{?dist}
Summary:        The open source coding agent

License:        MIT
URL:            https://github.com/anomalyco/opencode
# Source0 carries the upstream tarball (opencode-1.19.5/ top-level dir).
Source0:        opencode-1.19.5.tar.gz
Source1:        models-api.json.xz
# The COPR project this package is built in has no network access inside the
# build chroot (enable_net=False), so every input is shipped in the SRPM:
# Source2 = Node.js 24.18.0 x86_64, Source3 = Bun 1.4.4 x86_64 npm package,
# Source4 = the node_modules tree for the pruned workspace closure.
Source2:        node-v%{node_version}-linux-x64.tar.xz
Source3:        bun-linux-x64-%{bun_version}.tgz
Source4:        opencode-node_modules.tar.xz

# The build downloads x86_64 Node.js/Bun binaries and produces a linux-x64
# Bun single-file executable; only x86_64 builds are supported.
ExclusiveArch:  x86_64
BuildRequires:  bash
BuildRequires:  ca-certificates
BuildRequires:  chrpath
BuildRequires:  coreutils
BuildRequires:  cpio
BuildRequires:  curl
BuildRequires:  findutils
BuildRequires:  gcc
BuildRequires:  gcc-c++
BuildRequires:  git
BuildRequires:  glibc-devel
BuildRequires:  grep
BuildRequires:  gzip
BuildRequires:  make
BuildRequires:  patch
BuildRequires:  python3
BuildRequires:  sed
BuildRequires:  tar
BuildRequires:  unzip
BuildRequires:  which
BuildRequires:  xz
BuildRequires:  zip
Requires:       glibc

%description
opencode is an AI-powered development tool that runs coding agents in the
terminal. This package is compiled from the upstream TypeScript source using
Bun, and includes the embedded Web UI. It requires only glibc at runtime;
Node.js and Bun are not needed after installation.

%prep
cd %{_builddir}
# The upstream archive ships inside the SRPM as Source0, so %prep needs no
# network access. A network fetch of the ~70 MB source from a GitHub proxy
# stalled during an earlier build and burned the whole build wall clock, so
# the in-SRPM archive is used first; the proxies remain only as a fallback
# for the zero-byte placeholder case.
src_ok=0
if [ -s "%{SOURCE0}" ] && \
   tar -tzf "%{SOURCE0}" 2>/dev/null | grep -q '^opencode-1.19.5/'; then
  echo "Using source archive shipped in the SRPM: %{SOURCE0}"
  cp -f "%{SOURCE0}" src.tar.gz
  src_ok=1
fi
if [ "${src_ok}" != "1" ]; then
  for url in \
    "%{src_proxy}" \
    "https://gh.llkk.cc/https://github.com/anomalyco/opencode/archive/refs/tags/v1.19.5.tar.gz" \
    "https://gh-proxy.com/https://github.com/anomalyco/opencode/archive/refs/tags/v1.19.5.tar.gz"; do
    echo "Fetching source from ${url}"
    if curl --fail --location --retry 2 --connect-timeout 30 --max-time 900 \
         --output src.tar.gz "${url}"; then
      if tar -tzf src.tar.gz 2>/dev/null | grep -q '^opencode-1.19.5/'; then
        src_ok=1
        break
      fi
    fi
    rm -f src.tar.gz
  done
fi
if [ "${src_ok}" != "1" ]; then
  echo "ERROR: no source mirror was reachable" >&2
  exit 1
fi
tar -xzf src.tar.gz
cd opencode-1.19.5

# The in-SRPM archive is re-packed from the upstream git clone; drop any VCS
# metadata so the build tree matches the upstream tag archive layout.
rm -rf .git

# Keep only the CLI + embedded-Web-UI workspace closure.
rm -rf packages/console packages/stats packages/enterprise packages/desktop \
       packages/docs packages/web packages/storybook packages/slack \
       packages/identity packages/containers packages/cli packages/sdk-next \
       packages/function

# Tests, docs, and marketing assets are not build inputs.
rm -rf packages/*/test packages/*/tests packages/*/e2e packages/*/test-browser \
       packages/*/bench packages/*/storybook packages/*/docs packages/*/examples \
       packages/*/example packages/*/__tests__ packages/*/README* \
       packages/*/*/test packages/*/*/tests packages/*/*/e2e \
       packages/*/*/README* sdks github nix infra specs .github README* \
       AGENTS.md CONTRIBUTING.md STATS.md CONTEXT.md perf screenshot-*.png

# packages/script (@opencode-ai/script) reads .github/TEAM_MEMBERS at module
# load time (top-level await), so the pruning above must leave that file in
# place; otherwise `bun run script/build.ts` fails with ENOENT. Only release
# tooling consumes the team list, so a stub is enough for the build.
mkdir -p .github
printf '# build stub: team list is only used by upstream release tooling\n' \
  > .github/TEAM_MEMBERS

python3 - <<'PY'
import json
import os

path = "package.json"
data = json.load(open(path))
data["workspaces"]["packages"] = [
    x for x in data["workspaces"]["packages"]
    if x not in ("packages/console/*", "packages/stats/*", "packages/slack")
    and not (x == "packages/sdk/js" and not os.path.isdir(x))
]
json.dump(data, open(path, "w"), indent=2)
open(path, "a").write("\n")

path = "packages/app/package.json"
data = json.load(open(path))
data["dependencies"]["ghostty-web"] = "0.3.0"
json.dump(data, open(path, "w"), indent=2)
open(path, "a").write("\n")
PY

xz -dc %{SOURCE1} > models-api.json

%build
cd opencode-1.19.5
export HOME="%{_builddir}/%{name}-%{version}/.home"
mkdir -p "$HOME"

# Nothing is downloaded here: the COPR project has no network access in the
# build chroot, so Node.js, Bun and the npm dependency tree are all shipped in
# the SRPM (Source2/Source3/Source4).
echo '%{node_sha256}  %{SOURCE2}' | sha256sum -c -
mkdir -p "$HOME/node"
tar -xJf %{SOURCE2} -C "$HOME/node" --strip-components=1
export PATH="$HOME/node/bin:$PATH"
node --version
npm --version

echo '%{bun_sha256}  %{SOURCE3}' | sha256sum -c -
mkdir -p "$HOME/bun"
tar -xzf %{SOURCE3} -C "$HOME/bun" --strip-components=1
export PATH="$HOME/bun/bin:$PATH"
bun --version

# Vendored npm dependency tree (Source4) replaces `bun install`.
tar -xJf %{SOURCE4} -C .
test -d node_modules/.bun

# The embedded Web UI is built with vite, which does not fit in Node's default
# 1 GB heap for this module graph.
export NODE_OPTIONS="--max-old-space-size=4096"

export BUN_CONFIG_DISABLE_ANALYTICS=1
export MODELS_DEV_API_JSON="$PWD/models-api.json"
export OPENCODE_VERSION="%{version}"
export OPENCODE_CHANNEL="prod"
export USE_HARD_LINKS=false
export HUSKY=0

# node-pty's spawn-helper needs the executable bit; the vendored tree already
# has it, this keeps the step harmless/idempotent.
bun run --cwd packages/core fix-node-pty || :
cd packages/opencode
# --skip-install keeps the build offline: the dependency tree is already in
# place (Source4) and the flag also suppresses the extra cross-platform
# `bun install --os="*"` calls the script issues, which we do not need for a
# single linux-x64 target.
bun run script/build.ts --single --skip-install

%install
cd opencode-1.19.5
install -Dpm 0755 packages/opencode/dist/opencode-linux-x64/bin/opencode %{buildroot}%{_bindir}/opencode
install -Dpm 0644 LICENSE %{buildroot}%{_licensedir}/%{name}/LICENSE

%check
%{buildroot}%{_bindir}/opencode --version | grep -qx '%{version}'

%files
%license %{_licensedir}/%{name}/LICENSE
%{_bindir}/opencode

%changelog
* Fri Oct 30 2026 user_76c6f026 <user_76c6f026@eur.openeuler.cn> - 1.19.5-3
- Build fully offline: the COPR project used for this import has network
  access disabled (enable_net=False), which is what made the %build downloads
  fail with "Could not resolve host" (builds 114056 and 114057)
- Ship Node.js 24.18.0 (Source2), Bun 1.4.4 (Source3) and the resolved
  node_modules tree (Source4) inside the SRPM instead of downloading them
- Replace `bun install` with the vendored tree and build with
  `--skip-install` so no registry access is attempted
- Raise Node's heap for the embedded Web UI build (NODE_OPTIONS)

* Fri Oct 30 2026 user_76c6f026 <user_76c6f026@eur.openeuler.cn> - 1.19.5-2
- Route node-gyp header downloads to the Huawei Cloud Node.js mirror
  (npm_config_disturl) so dependency install scripts do not fail on the
  unreachable nodejs.org
- Rebuild after build 114056 aborted at the first %build download with a
  transient "Could not resolve host: mirrors.huaweicloud.com" DNS failure

* Fri Oct 30 2026 user_76c6f026 <user_76c6f026@eur.openeuler.cn> - 1.19.5-1
- Build opencode 1.19.5 from source for openEuler 24.03 LTS SP4 x86_64
- Adapt EUR reference spec (25.09) to the 24.03 LTS SP4 chroot
- Carry the upstream source archive in the SRPM (no build-time GitHub proxy)
- Provision Node.js 24.18.0 / Bun 1.4.4 from Huawei Cloud mirrors (sha256
  verified) and resolve the npm tree from the Huawei npm mirror
- Ship the models.dev snapshot as Source1 instead of fetching it at build
  time; switch ghostty-web to the published 0.3.0 package