Bump opencode 1.14.44 -> 1.14.50; cut over to split-base pipeline
Validate / validate-omos-with-pi (push) Waiting to run
Validate / docs-check (push) Successful in 1m7s
Validate / validate-with-pi (push) Failing after 3m16s
Validate / validate-omos (push) Failing after 3m15s
Validate / validate-base (push) Failing after 6m31s
Publish Docker Image / base-decide (push) Failing after 11m59s
Publish Docker Image / build-base (push) Has been cancelled
Publish Docker Image / smoke-base (push) Has been cancelled
Publish Docker Image / smoke-omos (push) Has been cancelled
Publish Docker Image / smoke-with-pi (push) Has been cancelled
Publish Docker Image / smoke-omos-with-pi (push) Has been cancelled
Publish Docker Image / build-variant-base (push) Has been cancelled
Publish Docker Image / build-variant-omos (push) Has been cancelled
Publish Docker Image / build-variant-with-pi (push) Has been cancelled
Publish Docker Image / build-variant-omos-with-pi (push) Has been cancelled
Publish Docker Image / promote-base-latest (push) Has been cancelled
Publish Docker Image / update-description (push) Has been cancelled

- Bump OPENCODE_VERSION 1.14.44 -> 1.14.50 in Dockerfile.variant
- Cut over: docker-publish-split.yml now triggers on push: tags: v*
  (was workflow_dispatch only). RELEASE_TAG and PROMOTE_LATEST derived
  from github.ref_type/ref_name for tag-push; inputs still available
  for manual workflow_dispatch runs.
- Delete docker-publish.yml (retired, replaced by split-base pipeline)
- Delete Dockerfile (retired, replaced by Dockerfile.base + Dockerfile.variant)
- Update CHANGELOG: promote Unreleased -> v1.14.50
- Update AGENTS.md, .gitea/README.md, validate.yml: remove all references
  to the old single-Dockerfile pipeline and WIP migration plan
This commit is contained in:
2026-05-14 19:39:45 +02:00
parent 7dc836ab66
commit 07e07ec611
8 changed files with 47 additions and 1113 deletions
+7 -8
View File
@@ -2,12 +2,12 @@
## Project overview
Docker image packaging [opencode](https://opencode.ai) into a production-ready dev container. Two image variants (base and omos) are published to Docker Hub via Gitea Actions CI. Not a library or application — this is infrastructure (Dockerfile, entrypoint scripts, docker-compose, documentation).
Docker image packaging [opencode](https://opencode.ai) into a production-ready dev container. Image variants are published to Docker Hub via Gitea Actions CI. Not a library or application — this is infrastructure (Dockerfiles, entrypoint scripts, docker-compose, documentation).
## File roles
- `Dockerfile` — production single-Dockerfile build. Variants are gated by build args: `INSTALL_OMOS` (Bun + multi-agent layer), `INSTALL_OPENCODE` (default true), `INSTALL_PI` (default false), `INSTALL_MEMPALACE` (default true). All GitHub-sourced binaries are pinned with version ARGs.
- `Dockerfile.base` and `Dockerfile.variant`**WIP, branch `feat/split-build` only.** Two-Dockerfile split-base build: base contains all variant-independent layers; variant `FROM`s the base and adds only opencode/omos/pi installs. Used by `docker-publish-split.yml` (workflow_dispatch only) for parallel testing alongside the production pipeline. See CHANGELOG `Unreleased` for the migration plan and trade-offs.
- `Dockerfile.base` — variant-independent layers (apt, locales, AWS CLI, Node.js, mempalace, gitea-mcp, user setup, chromadb prewarm, ENVs, entrypoints). Published as `joakimp/opencode-devbox:base-<sha12>`. Rebuilt only when its content hash changes.
- `Dockerfile.variant` `FROM`s the base and adds only opencode/omos/pi installs gated by build args: `INSTALL_OPENCODE` (default true), `INSTALL_OMOS`, `INSTALL_PI`, and `INSTALL_MEMPALACE`. All GitHub-sourced binaries are pinned with version ARGs.
- `entrypoint.sh` — runs as root: UID/GID adjustment, SSH permissions, volume ownership fixes (skipped via `.devbox-owner` sentinel when ownership is already correct). Then drops to developer via gosu. Volume ownership loop covers `~/.pi/` when `INSTALL_PI=true`.
- `entrypoint-user.sh` — runs as developer: git config, opencode.jsonc generation (delegated to `generate-config.py`), pi-toolkit + pi-extensions deploy (when pi installed), pi settings.json bootstrap, mempalace pi-bridge symlink, skillset auto-deploy from mounted skillset repo, OMOS setup.
- `rootfs/usr/local/lib/opencode-devbox/generate-config.py` — generates `~/.config/opencode/opencode.jsonc` from env vars. Never overwrites an existing config (checks both `.json` and `.jsonc`). Auto-registers MCP servers for detected tools (mempalace via `mempalace-mcp`, gitea-mcp, context7 remote endpoint).
@@ -17,21 +17,20 @@ Docker image packaging [opencode](https://opencode.ai) into a production-ready d
- `README.md` — authoritative source documentation for everything in this repo. Independent of `DOCKER_HUB.md`: the Hub doc is hand-maintained in the generator's `HUB_TEMPLATE` and intentionally slim, linking back to the gitea README for depth.
- `.gitea/README.md`**read this first** if you're touching CI. Architectural overview of the build pipeline (production vs split-base), wall-clock estimates, NPM_CONFIG_PREFIX gotcha, runner expectations, migration plan.
- `.gitea/workflows/validate.yml` — lightweight amd64 build + smoke test on push to main and PRs. Also runs the DOCKER_HUB.md sync check.
- `.gitea/workflows/docker-publish.yml` — production CI pipeline on tag push: smoke-test each variant on amd64, then full multi-arch (amd64 + arm64) build-and-push, then update Docker Hub description.
- `.gitea/workflows/docker-publish-split.yml`**WIP, branch `feat/split-build` only.** Two-phase split-base pipeline. Triggers on `workflow_dispatch` only so it runs alongside the production pipeline without conflict. Pushes to user-supplied `release_tag` input (e.g. `v0.0.0-split-test`); `latest*` aliases only updated when `promote_latest: true`. Compute base hash, conditionally build base, then 4 variant deltas in parallel.
- `.gitea/workflows/docker-publish-split.yml` — production CI pipeline on tag push (`v*`). Two-phase split-base: computes base hash, conditionally builds base, runs 4 parallel smoke tests, then 4 parallel multi-arch variant builds, promotes `base-latest` alias, updates Docker Hub description.
## Versioning scheme
Tags follow `v{opencode_version}[letter]` — e.g. `v1.14.20` for the first build on a new opencode release, and `v1.14.20b`, `v1.14.20c`, … for subsequent rebuilds on the same opencode version.
- The number tracks the opencode npm version (see `OPENCODE_VERSION` ARG in `Dockerfile`).
- The number tracks the opencode npm version (see `OPENCODE_VERSION` ARG in `Dockerfile.variant`).
- **No letter suffix** on the first build of a new opencode version — the bare `v{opencode_version}` tag is the canonical release.
- **Letter suffix is the build ordinal**, starting at `b` for the second build. The letter `a` is **never used** — think of the suffix as counting rebuilds: `b = 2nd, c = 3rd, d = 4th, …`. For opencode version `1.14.20`: first build `v1.14.20`, second `v1.14.20b`, third `v1.14.20c`, and so on.
- A letter suffix is only used for container-level rebuilds — tooling changes, CVE fixes, doc-driven rebuilds, entrypoint bugfixes — that don't change the underlying opencode version.
CI produces eight Docker Hub tags per release: `vX.Y.Z[n]`, `latest`, `vX.Y.Z[n]-omos`, `latest-omos`, `vX.Y.Z[n]-with-pi`, `latest-with-pi`, `vX.Y.Z[n]-omos-with-pi`, `latest-omos-with-pi` — one tag pair (versioned + floating alias) per build variant.
When bumping the opencode version, also bump `OPENCODE_VERSION` in `Dockerfile` and update the comment in `.env.example` if it names a specific model/version for context.
When bumping the opencode version, bump `OPENCODE_VERSION` in `Dockerfile.variant` and update the comment in `.env.example` if it names a specific model/version for context.
## Critical conventions
@@ -66,7 +65,7 @@ When bumping the opencode version, also bump `OPENCODE_VERSION` in `Dockerfile`
- **`docker/build-push-action@v7` with `platforms: linux/amd64,linux/arm64` handles multi-arch push natively in a single job** — produces a proper manifest list, no matrix or merge step needed. An earlier revision split into per-arch matrix jobs with digest artifacts, but that pattern requires `actions/{upload,download}-artifact@v4+` which Gitea Actions doesn't support (see below).
- **`actions/upload-artifact` and `actions/download-artifact` must stay at @v3 on Gitea.** v4+ uses a GitHub-Enterprise-specific Artifact API; runs fail with `GHESNotSupportedError`. If you need artifacts for a new reason (build logs, SBOMs, etc.), pin @v3 explicitly.
- **Step scripts run under `/bin/sh` (dash), not bash.** Avoid bash-isms like `${VAR//a/b}` parameter-pattern substitution; use POSIX alternatives (`tr`, `sed`) or declare `shell: bash` on the step.
- **`BUILDKIT_PROGRESS=plain`** is set at workflow level on `docker-publish.yml` so arm64-under-QEMU builds log each layer line-by-line. The default collapsed progress UI hides which step is stalled, which made diagnosing earlier hangs expensive.
- **`BUILDKIT_PROGRESS=plain`** is set at workflow level on `docker-publish-split.yml` so arm64-under-QEMU builds log each layer line-by-line. The default collapsed progress UI hides which step is stalled, which made diagnosing earlier hangs expensive.
## Testing changes