This commit is contained in:
@@ -7,7 +7,32 @@ on:
|
||||
- 'opencode/*'
|
||||
- '.gitea/workflows/build-opencode.yaml'
|
||||
jobs:
|
||||
"Build opencode docker images":
|
||||
# "Build opencode docker images":
|
||||
# runs-on: hostinger
|
||||
# steps:
|
||||
# -
|
||||
# name: Login to Gitea container registry
|
||||
# uses: docker/login-action@v3
|
||||
# with:
|
||||
# registry: gitea.woggioni.net
|
||||
# username: woggioni
|
||||
# password: ${{ secrets.PUBLISHER_TOKEN }}
|
||||
# -
|
||||
# name: Build and push opencode images
|
||||
# uses: docker/build-push-action@v6
|
||||
# with:
|
||||
# builder: multiplatform-builder
|
||||
# context: "{{defaultContext}}:opencode"
|
||||
# build-args: |
|
||||
# OPENCODE_VERSION=1.18.4
|
||||
# platforms: |
|
||||
# linux/amd64
|
||||
# push: true
|
||||
# pull: true
|
||||
# tags: |
|
||||
# "gitea.woggioni.net/woggioni/opencode:1.18.4"
|
||||
# "gitea.woggioni.net/woggioni/opencode:latest"
|
||||
build-from-source:
|
||||
runs-on: hostinger
|
||||
steps:
|
||||
-
|
||||
@@ -23,13 +48,13 @@ jobs:
|
||||
with:
|
||||
builder: multiplatform-builder
|
||||
context: "{{defaultContext}}:opencode"
|
||||
file: from-source.dockerfile
|
||||
ssh: default=/var/lib/gitea-runner/.ssh/id_ed25519
|
||||
build-args: |
|
||||
OPENCODE_VERSION=1.18.4
|
||||
VERSION=1.18.4
|
||||
platforms: |
|
||||
linux/amd64
|
||||
push: true
|
||||
pull: true
|
||||
tags: |
|
||||
"gitea.woggioni.net/woggioni/opencode:1.18.4"
|
||||
"gitea.woggioni.net/woggioni/opencode:latest"
|
||||
|
||||
"gitea.woggioni.net/woggioni/opencode:test"
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@ COPY mirrorlist /etc/pacman.d/mirrolist
|
||||
RUN pacman-key --init
|
||||
#RUN pacman-key --refresh-keys
|
||||
|
||||
ADD https://gitea.woggioni.net/api/packages/woggioni/arch/repository.key ./repository.key
|
||||
ADD --keep-git-dir=true https://gitea.woggioni.net/api/packages/woggioni/arch/repository.key ./repository.key
|
||||
|
||||
RUN pacman-key --add repository.key
|
||||
RUN pacman-key --lsign-key 0D28BF66FDB45D18D8EBEE5D4C91DADCD00B3F77
|
||||
|
||||
Executable
+219
@@ -0,0 +1,219 @@
|
||||
#!/usr/bin/env bun
|
||||
|
||||
import { $ } from "bun"
|
||||
import path from "path"
|
||||
import { fileURLToPath } from "url"
|
||||
import { createSolidTransformPlugin } from "@opentui/solid/bun-plugin"
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url)
|
||||
const __dirname = path.dirname(__filename)
|
||||
const dir = path.resolve(__dirname, "..")
|
||||
|
||||
process.chdir(dir)
|
||||
|
||||
const generated = await import("./generate.ts")
|
||||
|
||||
import { Script } from "@opencode-ai/script"
|
||||
import pkg from "../package.json"
|
||||
|
||||
const singleFlag = process.argv.includes("--single")
|
||||
const baselineFlag = process.argv.includes("--baseline")
|
||||
const skipInstall = process.argv.includes("--skip-install")
|
||||
const sourcemapsFlag = process.argv.includes("--sourcemaps")
|
||||
const plugin = createSolidTransformPlugin()
|
||||
const skipEmbedWebUi = process.argv.includes("--skip-embed-web-ui")
|
||||
|
||||
const createEmbeddedWebUIBundle = async () => {
|
||||
console.log(`Building Web UI to embed in the binary`)
|
||||
const appDir = path.join(import.meta.dirname, "../../app")
|
||||
const dist = path.join(appDir, "dist")
|
||||
await $`OPENCODE_CHANNEL=${Script.channel} bun run --cwd ${appDir} build`
|
||||
const files = (await Array.fromAsync(new Bun.Glob("**/*").scan({ cwd: dist })))
|
||||
.map((file) => file.replaceAll("\\", "/"))
|
||||
.filter((file) => !file.endsWith(".map"))
|
||||
.sort()
|
||||
const imports = files.map((file, i) => {
|
||||
const spec = path.relative(dir, path.join(dist, file)).replaceAll("\\", "/")
|
||||
return `import file_${i} from ${JSON.stringify(spec.startsWith(".") ? spec : `./${spec}`)} with { type: "file" };`
|
||||
})
|
||||
const entries = files.map((file, i) => ` ${JSON.stringify(file)}: file_${i},`)
|
||||
return [
|
||||
`// Import all files as file_$i with type: "file"`,
|
||||
...imports,
|
||||
`// Export with original mappings`,
|
||||
`export default {`,
|
||||
...entries,
|
||||
`}`,
|
||||
].join("\n")
|
||||
}
|
||||
|
||||
const embeddedFileMap = skipEmbedWebUi ? null : await createEmbeddedWebUIBundle()
|
||||
const treeSitterWorker = await Bun.file(fileURLToPath(import.meta.resolve("@opentui/core/parser.worker"))).text()
|
||||
|
||||
const allTargets: {
|
||||
os: string
|
||||
arch: "arm64" | "x64"
|
||||
abi?: "musl"
|
||||
avx2?: false
|
||||
}[] = [
|
||||
{
|
||||
os: "linux",
|
||||
arch: "arm64",
|
||||
},
|
||||
{
|
||||
os: "linux",
|
||||
arch: "x64",
|
||||
},
|
||||
{
|
||||
os: "linux",
|
||||
arch: "x64",
|
||||
avx2: false,
|
||||
},
|
||||
{
|
||||
os: "linux",
|
||||
arch: "arm64",
|
||||
abi: "musl",
|
||||
},
|
||||
{
|
||||
os: "linux",
|
||||
arch: "x64",
|
||||
abi: "musl",
|
||||
},
|
||||
{
|
||||
os: "linux",
|
||||
arch: "x64",
|
||||
abi: "musl",
|
||||
avx2: false,
|
||||
}
|
||||
]
|
||||
|
||||
const targets = singleFlag
|
||||
? allTargets.filter((item) => {
|
||||
if (item.os !== process.platform || item.arch !== process.arch) {
|
||||
return false
|
||||
}
|
||||
|
||||
// When building for the current platform, prefer a single native binary by default.
|
||||
// Baseline binaries require additional Bun artifacts and can be flaky to download.
|
||||
if (item.avx2 === false) {
|
||||
return baselineFlag
|
||||
}
|
||||
|
||||
// also skip abi-specific builds for the same reason
|
||||
if (item.abi !== undefined) {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
})
|
||||
: allTargets
|
||||
|
||||
await $`rm -rf dist`
|
||||
|
||||
const binaries: Record<string, string> = {}
|
||||
if (!skipInstall) {
|
||||
await $`bun install --os="*" --cpu="*" @opentui/core@${pkg.dependencies["@opentui/core"]}`
|
||||
await $`bun install --os="*" --cpu="*" @parcel/watcher@${pkg.dependencies["@parcel/watcher"]}`
|
||||
await $`bun install --os="*" --cpu="*" @ff-labs/fff-bun@${pkg.dependencies["@ff-labs/fff-bun"]}`
|
||||
}
|
||||
for (const item of targets) {
|
||||
const name = [
|
||||
pkg.name,
|
||||
// changing to win32 flags npm for some reason
|
||||
item.os === "win32" ? "windows" : item.os,
|
||||
item.arch,
|
||||
item.avx2 === false ? "baseline" : undefined,
|
||||
item.abi === undefined ? undefined : item.abi,
|
||||
]
|
||||
.filter(Boolean)
|
||||
.join("-")
|
||||
console.log(`building ${name}`)
|
||||
await $`mkdir -p dist/${name}/bin`
|
||||
|
||||
const workerPath = "./src/cli/tui/worker.ts"
|
||||
const treeSitterWorkerPath = "opentui-tree-sitter-worker.js"
|
||||
const bunfsRoot = item.os === "win32" ? "B:/~BUN/root/" : "/$bunfs/root/"
|
||||
|
||||
await Bun.build({
|
||||
conditions: ["bun", "node"],
|
||||
tsconfig: "./tsconfig.json",
|
||||
plugins: [plugin],
|
||||
external: ["node-gyp"],
|
||||
format: "esm",
|
||||
minify: true,
|
||||
sourcemap: sourcemapsFlag ? "linked" : "none",
|
||||
splitting: true,
|
||||
compile: {
|
||||
autoloadBunfig: false,
|
||||
autoloadDotenv: false,
|
||||
autoloadTsconfig: true,
|
||||
autoloadPackageJson: true,
|
||||
target: name.replace(pkg.name, "bun") as any,
|
||||
outfile: `dist/${name}/bin/opencode`,
|
||||
execArgv: [`--user-agent=opencode/${Script.version}`, "--use-system-ca", "--"],
|
||||
windows: {},
|
||||
},
|
||||
files: {
|
||||
[treeSitterWorkerPath]: treeSitterWorker,
|
||||
...(embeddedFileMap ? { "opencode-web-ui.gen.ts": embeddedFileMap } : {}),
|
||||
},
|
||||
entrypoints: [
|
||||
"./src/index.ts",
|
||||
workerPath,
|
||||
treeSitterWorkerPath,
|
||||
...(embeddedFileMap ? ["opencode-web-ui.gen.ts"] : []),
|
||||
],
|
||||
define: {
|
||||
FFF_LIBC: JSON.stringify(item.abi === "musl" ? "musl" : "gnu"),
|
||||
OPENCODE_VERSION: `'${Script.version}'`,
|
||||
OPENCODE_MODELS_DEV: generated.modelsData,
|
||||
OTUI_TREE_SITTER_WORKER_PATH: bunfsRoot + treeSitterWorkerPath,
|
||||
OPENCODE_WORKER_PATH: workerPath,
|
||||
OPENCODE_CHANNEL: `'${Script.channel}'`,
|
||||
OPENCODE_LIBC: item.os === "linux" ? `'${item.abi ?? "glibc"}'` : "",
|
||||
...(item.os === "linux" ? { "process.env.OPENTUI_LIBC": JSON.stringify(item.abi ?? "glibc") } : {}),
|
||||
},
|
||||
})
|
||||
|
||||
// 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`
|
||||
console.log(`Running smoke test: ${binaryPath} --version`)
|
||||
try {
|
||||
const versionOutput = await $`${binaryPath} --version`.text()
|
||||
console.log(`Smoke test passed: ${versionOutput.trim()}`)
|
||||
} catch (e) {
|
||||
console.error(`Smoke test failed for ${name}:`, e)
|
||||
process.exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
await $`rm -rf ./dist/${name}/bin/tui`
|
||||
await Bun.file(`dist/${name}/package.json`).write(
|
||||
JSON.stringify(
|
||||
{
|
||||
name,
|
||||
version: Script.version,
|
||||
preferUnplugged: true,
|
||||
os: [item.os],
|
||||
cpu: [item.arch],
|
||||
...(item.abi ? { libc: [item.abi] } : {}),
|
||||
},
|
||||
null,
|
||||
2,
|
||||
),
|
||||
)
|
||||
binaries[name] = Script.version
|
||||
}
|
||||
|
||||
if (Script.release) {
|
||||
for (const key of Object.keys(binaries)) {
|
||||
if (key.includes("linux")) {
|
||||
await $`tar -czf ../../${key}.tar.gz *`.cwd(`dist/${key}/bin`)
|
||||
} else {
|
||||
await $`zip -r ../../${key}.zip *`.cwd(`dist/${key}/bin`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export { binaries }
|
||||
@@ -0,0 +1,51 @@
|
||||
FROM oven/bun:1.3.14-alpine AS builder
|
||||
|
||||
#FROM node:25-alpine AS builder
|
||||
ARG VERSION
|
||||
ENTRYPOINT sh
|
||||
RUN apk update
|
||||
RUN --mount=type=cache,target=/var/cache/apk apk update
|
||||
RUN --mount=type=cache,target=/var/cache/apk apk add python3 make g++ npm zip git
|
||||
RUN adduser -D -h /home/builder -u 1126 builder
|
||||
USER builder
|
||||
WORKDIR /home/builder
|
||||
ADD --chown=builder:builder git@github.com:anomalyco/opencode.git#v${VERSION} opencode
|
||||
WORKDIR /home/builder/opencode
|
||||
# RUN bun install
|
||||
|
||||
RUN --mount=type=cache,target=/home/builder/.bun/install/cache,uid=1126 bun install
|
||||
# WORKDIR /home/builder/opencode/packages/opencode
|
||||
# ENV OPENCODE_CHANNEL=latest
|
||||
# ENV OPENCODE_VERSION=${VERSION}
|
||||
# ENV OPENCODE_RELEASE=${VERSION}
|
||||
#bun run ./script/build.ts --single
|
||||
# RUN --mount=type=cache,target=/home/builder/.bun/install/cache,uid=1126 ./packages/opencode/script/build.ts
|
||||
ADD --chown=builder:builder ./build.ts ./packages/opencode/script/build.ts
|
||||
# RUN --mount=type=cache,target=/home/builder/.bun/install/cache,uid=1126 bun build --compile \
|
||||
# --target="bun-linux-x64-musl" \
|
||||
# --outfile="dist/opencode-linux-x64-musl/bin/opencode" \
|
||||
# --external="node-gyp" \
|
||||
# --sourcemap=none \
|
||||
# --minify \
|
||||
# --splitting \
|
||||
# --conditions="bun" \
|
||||
# --conditions="node" \
|
||||
# --format="esm" \
|
||||
# --tsconfig-override="./packages/opencode/tsconfig.json" \
|
||||
# --define="FFF_LIBC=\"musl\"" \
|
||||
# --define="OPENCODE_LIBC=\"musl\"" \
|
||||
# --define="OPENCODE_CHANNEL=\"latest\"" \
|
||||
# --define="OPENCODE_VERSION=\"${VERSION}\"" \
|
||||
# --define="OTUI_TREE_SITTER_WORKER_PATH=/\$bunfs/root/opentui-tree-sitter-worker.js" \
|
||||
# --define="OPENCODE_WORKER_PATH=./packages/opencode/src/cli/tui/worker.ts" \
|
||||
# --define="process.env.OPENTUI_LIBC=\"musl\"" \
|
||||
# ./packages/opencode/src/index.ts \
|
||||
# ./packages/opencode/src/cli/tui/worker.ts
|
||||
|
||||
RUN --mount=type=cache,target=/home/builder/.bun/install/cache,uid=1126 ./packages/opencode/script/build.ts
|
||||
|
||||
#RUN rm ./opencode.tgz
|
||||
|
||||
# RUN adduser -D -h /var/lib/opencode opencode
|
||||
# USER opencode
|
||||
# WORKDIR /var/lib/opencode
|
||||
Reference in New Issue
Block a user