Merge pull request 'docs: add dependency management section — renovate must track all pinned Dockerfile packages' (#8) from docs/agents-md-renovate-convention into main
Docker Build and Push / build (push) Successful in 3m49s

Reviewed-on: #8
This commit was merged in pull request #8.
This commit is contained in:
2026-06-09 12:46:56 -04:00
+18 -11
View File
@@ -2,33 +2,40 @@
## Project overview
This repository builds and publishes a Docker image for [OpenCode](https://opencode.ai), the open source AI coding agent. The image runs OpenCode in headless server mode (`opencode serve`) and is automatically rebuilt and pushed to Docker Hub (`jcabillot/opencode`) every night by a Jenkins pipeline.
This repository builds and publishes a Docker image for [OpenCode](https://opencode.ai), the open source AI coding agent. The image runs OpenCode in headless server mode (`opencode serve`) and is automatically rebuilt and pushed to Docker Hub (`jcabillot/opencode`) every night by a Gitea Actions pipeline.
## Repository structure
```
.
├── Dockerfile # Image definition
├── Jenkinsfile # CI/CD pipeline (nightly build + Docker Hub push)
├── opencode-attach # Helper script for attaching to a running server
── README.md # Usage documentation
├── Dockerfile # Image definition
├── .gitea/workflows/docker-build.yaml # CI/CD pipeline (Gitea Actions)
├── renovate.json # Dependency update automation (Renovatebot)
── opencode-attach # Helper script for attaching to a running server
└── README.md # Usage documentation
```
## Dependency management
- **Always pin versions** in the Dockerfile `npm install` command (e.g. `opencode-ai@1.16.2 n2-soul@9.0.9`). Never leave packages unpinned.
- **Update renovate customManagers** when adding, removing, or renaming a dependency tracked in the Dockerfile. Each pinned package must have a corresponding `customManager` entry in `renovate.json` with a regex `matchStrings` pattern that captures the version. If a dependency is added without a renovate entry, Renovatebot will not open automated PRs for it.
- **apt packages** (apt-get install lines in Dockerfile) and **COPY --from** image references are not currently tracked by Renovate. Pinning these manually is acceptable for now but adding renovate managers for them is encouraged.
## Dockerfile conventions
- **Base image**: `node:24` — Debian-based Node.js image (not Alpine, needed for apt packages).
- **Install**: `npm i -g opencode-ai n2-soul@<version>` — installs OpenCode and Soul globally.
- **Install**: `npm i -g opencode-ai@<version> n2-soul@<version>` — installs OpenCode and Soul globally, both pinned.
- **Version check**: `RUN opencode --version` after install to validate the build and record the installed version in build logs.
- **Dedicated user**: a non-root `opencode` user and group are created with `groupadd`/`useradd` (UID/GID 1000). All runtime steps run as this user.
- **Cluster tooling**: `kubectl` is copied from the official `registry.k8s.io/kubectl` image (multi-stage COPY).
- **Entrypoint**: `["opencode"]` — arguments are passed at runtime (e.g. `serve`).
## Jenkinsfile conventions
## CI/CD conventions (Gitea Actions)
- The pipeline runs on a `@midnight` cron trigger for nightly rebuilds.
- Build uses `--no-cache --pull` to always fetch the latest base image and package version.
- Docker Hub credentials are stored under the `dockerhub_jcabillot` Jenkins credential ID.
- The image is published as `jcabillot/opencode` (no explicit tag = `latest`).
- Pipeline triggers on push to `main`, PRs targeting `main`, and a nightly cron (`cron: '0 0 * * *'`).
- Image is pushed to Docker Hub only on non-PR events (main branch pushes and cron runs).
- Docker Hub credentials are stored in Gitea Actions secrets (`DOCKERHUB_USERNAME`, `DOCKERHUB_TOKEN`).
- The image is published as `jcabillot/opencode:latest` with digest and branch tags.
## Useful commands