diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..2c5ebc6 Binary files /dev/null and b/.DS_Store differ diff --git a/forgerunner.src/AGENT.md b/forgerunner.src/AGENT.md new file mode 100644 index 0000000..4ffbd69 --- /dev/null +++ b/forgerunner.src/AGENT.md @@ -0,0 +1,591 @@ +# AGENT.md + +## Project + +**Name:** custom-gitea-runner + +**Purpose:** +Build a self-owned, versioned, Docker-first Gitea Actions runner platform that avoids opaque upstream behavior, is easy to debug, and is safe to operate on Unraid and general Linux hosts. This project should produce a maintainable runner image, startup logic, configuration templates, and documentation that make runner behavior explicit and reproducible. + +This project exists because the stock/self-hosted runner path introduced hard-to-diagnose issues around nested containers, action runtime dependencies, container image behavior, and host/runtime compatibility. The replacement should favor observability, deterministic builds, explicit tooling, and low-surprise operations. + +--- + +## Mission + +Create a production-ready custom Gitea runner solution that: + +- Runs reliably in Docker on Unraid and standard Linux hosts. +- Supports JavaScript-based actions by shipping the required runtime dependencies explicitly. +- Supports Docker build/push workflows without hidden image assumptions. +- Uses pinned versions wherever practical. +- Separates image build concerns from runtime registration/config concerns. +- Makes debugging first-class through logs, health checks, self-tests, and clear failure modes. +- Keeps all project knowledge versioned in-repo through AGENT.md, README.md, ROADMAP.md, CHANGELOG.md, and example configs. + +--- + +## Product goals + +1. Build a custom Docker image for a Gitea-compatible runner. +2. Provide an entrypoint/bootstrap script that prepares the runtime deterministically. +3. Support runner registration through environment variables and/or mounted config. +4. Support common CI workloads for the target environment: checkout, Node-based actions, Docker login, Docker build, Docker push, shell scripts, and future extensibility for additional tooling. +5. Provide a clean path for image tagging, publishing, rollback, and host deployment. +6. Minimize dependence on mutable upstream defaults like `latest`, floating action images, or runtime package installs during startup. +7. Make the image and scripts inspectable, testable, and easy to extend. + +--- + +## Non-goals + +- Do not build a full replacement for the Gitea server. +- Do not invent a proprietary CI protocol if standard Gitea runner registration is sufficient. +- Do not optimize first for Kubernetes. +- Do not assume multi-tenant hostile workloads at v1; this is a controlled self-hosted environment. +- Do not rely on runtime `apk add` or ad hoc container mutation as a permanent solution. + +--- + +## Development philosophy + +Treat this like an internal platform product, not a one-off container hack. + +Principles: + +- **Version everything.** Image versions, dependency versions, docs, sample configs, and release notes should all be explicit. +- **Document while building.** If behavior changes, update README.md and ROADMAP.md in the same workstream. +- **Prefer deterministic builds.** Install dependencies at image build time, not container startup. +- **Prefer explicit over magical.** If Node, Git, Docker CLI, certificates, or helper binaries are required, declare and verify them. +- **Design for diagnosis.** Every major startup step should emit useful logs. +- **Keep the bootstrap thin.** Complex logic should live in versioned scripts/modules, not giant one-line container commands. +- **Bias for maintainability.** Small, composable scripts beat clever entrypoints. + +--- + +## User and environment assumptions + +Primary operator profile: + +- Advanced technical operator. +- Comfortable with Docker, Unraid, Node.js/TypeScript, Bash, and self-hosted infrastructure. +- Prefers documented roadmaps, structured project files, and reusable internal tooling. + +Primary target environment: + +- Unraid Docker host first. +- Standard Linux Docker host second. +- Gitea instance is self-hosted. +- Registry may be self-hosted Gitea Container Registry. +- Project repositories are hosted in Gitea. + +--- + +## Required deliverables + +The agent should scaffold and maintain at minimum: + +```text +custom-gitea-runner/ +├── AGENT.md +├── README.md +├── ROADMAP.md +├── CHANGELOG.md +├── LICENSE +├── .gitignore +├── .env.example +├── docker/ +│ ├── runner/ +│ │ ├── Dockerfile +│ │ ├── docker-entrypoint.sh +│ │ ├── healthcheck.sh +│ │ └── smoke-test.sh +│ └── compose/ +│ ├── docker-compose.example.yml +│ └── unraid-template-notes.md +├── config/ +│ ├── runner.example.yaml +│ ├── labels.example.env +│ └── trusted-ca/ +├── scripts/ +│ ├── register-runner.sh +│ ├── deregister-runner.sh +│ ├── verify-runtime.sh +│ ├── build-image.sh +│ ├── publish-image.sh +│ └── test-local-runner.sh +├── docs/ +│ ├── architecture.md +│ ├── operations.md +│ ├── troubleshooting.md +│ ├── unraid.md +│ └── decisions/ +│ └── 0001-base-image.md +├── test/ +│ ├── fixtures/ +│ ├── sample-workflows/ +│ └── smoke/ +└── src/ + └── optional/ +``` + +Notes: + +- `src/` is optional unless the project grows into a TypeScript control plane or helper CLI. +- If a CLI/helper app is introduced, prefer TypeScript for maintainability and consistency with the project stack. + +--- + +## Recommended architecture + +### Baseline architecture + +Start with a Docker image that wraps or embeds the official `act_runner` binary but controls: + +- base image selection, +- runtime package set, +- startup/registration flow, +- mounted config handling, +- Docker socket strategy, +- health checks, +- and diagnostics. + +### Preferred v1 design + +- Debian or Ubuntu slim base image, not an ultra-minimal image that requires runtime mutation. +- Install at build time: + - ca-certificates + - bash + - curl + - git + - jq + - nodejs + - npm + - docker CLI + - tini + - timezone data +- Copy in a pinned `act_runner` binary or install from a pinned release artifact. +- Use `tini` as PID 1. +- Use a real multi-line `docker-entrypoint.sh`. +- Validate runtime prerequisites before daemon start. +- Prefer mounted `/var/run/docker.sock` for v1 if the host is trusted and this matches the deployment model. +- Expose health check status through a lightweight script. + +### Why this design + +This directly addresses the observed failure class: + +- runtime packages missing in the runner image, +- overreliance on upstream defaults, +- brittle nested-container behavior, +- and low observability when setup fails. + +--- + +## Runner behavior requirements + +The custom runner must: + +1. Start deterministically with a documented set of environment variables. +2. Fail fast when required inputs are missing. +3. Verify and log the presence of key tools: + - `git` + - `node` + - `npm` + - `docker` + - `act_runner` +4. Emit version information at startup. +5. Support both pre-registered config files and first-boot registration flows. +6. Avoid mutating the filesystem in surprising ways at runtime beyond known writable paths. +7. Support Docker-based build/push jobs cleanly. +8. Provide optional label mapping guidance for common targets like `ubuntu-latest`. +9. Make workspace and temp directories explicit and configurable. +10. Provide a smoke-test path that validates the runner image before production use. + +--- + +## Configuration model + +Support two modes. + +### Mode A: Pre-generated config + +Operator mounts: + +- runner config yaml +- optional registration metadata +- optional CA bundle + +This is the preferred stable production mode. + +### Mode B: Bootstrap registration + +Operator provides env vars such as: + +- `GITEA_INSTANCE_URL` +- `GITEA_RUNNER_TOKEN` +- `GITEA_RUNNER_NAME` +- `GITEA_RUNNER_LABELS` +- `GITEA_RUNNER_WORKDIR` +- `GITEA_RUNNER_CONFIG_PATH` + +Entrypoint performs: + +1. validation, +2. one-time registration if config absent, +3. daemon startup. + +The agent should design this so reboots are idempotent. + +--- + +## Docker and security model + +### v1 security posture + +This runner is intended for a trusted, self-hosted environment. Simplicity and reliability are more important than extreme sandbox isolation in v1. + +### v1 approach + +- Support Docker socket mount for build/push workloads. +- Document the trust implications clearly. +- Keep the runner container itself as minimal and explicit as possible. +- Avoid privileged mode unless a specific feature requires it. +- Prefer read-only mounts where practical except for config/work directories. +- Run as non-root where feasible, but do not force complexity if Docker socket access or upstream tooling makes that unrealistic in v1. + +### Future hardening track + +Document as roadmap items: + +- rootless variants, +- DinD variant, +- dedicated buildkit integration, +- ephemeral one-job runners, +- restricted labels by repo or org, +- network isolation strategies. + +--- + +## Documentation requirements + +The agent must keep these files current as the project evolves. + +### README.md + +Should include: + +- project purpose, +- why this exists, +- supported features, +- architecture overview, +- quick start, +- environment variables, +- Docker compose example, +- Unraid deployment notes, +- sample workflow guidance, +- troubleshooting links, +- versioning and release model. + +### ROADMAP.md + +Must track phases, status, and next actions. + +Recommended sections: + +- Phase 0: Research and design +- Phase 1: Base image and bootstrap +- Phase 2: Registration/config flows +- Phase 3: Docker workflow support +- Phase 4: Test harness and smoke validation +- Phase 5: Unraid packaging and docs +- Phase 6: Hardening and enhancements + +### CHANGELOG.md + +Use Keep a Changelog style: + +- Added +- Changed +- Fixed +- Removed + +### docs/troubleshooting.md + +Must be practical and symptom-driven. + +Include sections for issues like: + +- runner not registering, +- `node` not found, +- Docker socket permission errors, +- workflow checkout failures, +- registry login failures, +- container job image issues, +- CA/certificate trust issues, +- Unraid-specific gotchas. + +--- + +## Functional scope for v1 + +### Must support + +- `actions/checkout` +- `docker/login-action` +- `docker build` +- `docker push` +- shell-based build scripts +- Gitea registry auth patterns +- branch/tag based image builds + +### Nice to support in v1 if straightforward + +- `buildx` +- cache mounts +- custom CA installation +- repo/org label strategies +- self-test action workflow + +### Defer unless easy + +- autoscaling +- UI dashboard +- metrics exporter +- multi-runner orchestrator +- web control plane + +--- + +## Testing strategy + +The project should include real validation, not just build success. + +### Required tests + +1. **Image build test** + - Docker image builds successfully from scratch. + +2. **Runtime verification test** + - Container starts and confirms key binaries exist. + +3. **Registration smoke test** + - Runner can register against a test Gitea instance or mocked flow. + +4. **Workflow smoke tests** + - checkout-only workflow, + - Node-based action workflow, + - Docker login workflow, + - Docker build/push workflow against a test registry. + +5. **Regression tests** + - specifically capture previously observed failure classes around missing Node and fragile container behavior. + +### Testing philosophy + +Every bug that costs real debugging time should become: + +- a documented issue, +- a troubleshooting entry, +- and ideally a regression test. + +--- + +## Logging and observability + +Startup logs should clearly print: + +- image version, +- git commit if embedded, +- act_runner version, +- node version, +- docker version, +- registration mode, +- config path, +- work directory, +- labels, +- target Gitea URL. + +Do not log secrets. + +Health check should verify at minimum: + +- runner process exists, +- config is present, +- Docker socket availability if required, +- core binaries exist. + +Optional future enhancements: + +- structured JSON logs, +- `/healthz` sidecar or helper, +- metrics export. + +--- + +## Versioning and release policy + +Use semantic-ish tags for the custom image. + +Recommended tagging: + +- `v0.1.0` +- `v0.1.1` +- `v0.2.0` +- `latest` only as a convenience alias to the newest stable release + +Rules: + +- Never deploy unpinned `latest` in production docs as the primary recommendation. +- Every release should map to a Git tag and CHANGELOG entry. +- Embed image metadata labels such as version, vcs ref, build date, and source URL. + +--- + +## Agent operating instructions + +When working on this project, the agent must: + +1. Update `ROADMAP.md` when a phase changes or a major task is added/closed. +2. Update `README.md` when usage, env vars, image behavior, or deployment steps change. +3. Update `CHANGELOG.md` for user-visible changes. +4. Prefer small, reviewable commits/changesets. +5. Ask for clarification before making irreversible architecture choices when multiple valid paths exist. +6. Keep scripts POSIX/Bash-friendly and easy to audit. +7. Avoid hidden runtime package installation unless explicitly implementing a temporary debug path. +8. Prefer pinned versions in Dockerfile and examples. +9. Add troubleshooting notes whenever a new failure mode is discovered. +10. Preserve portability between Unraid and standard Linux where reasonable. + +--- + +## Implementation preferences + +Preferred languages and tooling: + +- Bash for bootstrap and operational scripts. +- Dockerfile for image definition. +- TypeScript only if a helper CLI/control plane becomes necessary. +- Markdown for all project documentation. +- Git-based versioning hosted in Gitea. + +Preferred project style: + +- Modular files. +- Clean naming. +- Self-explanatory scripts. +- No giant inline command strings in container templates. +- Examples should be copy-paste friendly. + +--- + +## Suggested first milestones + +### Milestone 1: Foundation + +- Initialize repository structure. +- Write README.md skeleton. +- Write ROADMAP.md. +- Write Dockerfile using pinned base image. +- Write entrypoint with startup validation. +- Add healthcheck script. + +### Milestone 2: Registration and config + +- Add env-driven bootstrap registration flow. +- Add mounted-config mode. +- Add `.env.example`. +- Add example runner config. + +### Milestone 3: CI workload support + +- Ensure Node, Git, Docker CLI, CA certs all present. +- Validate `actions/checkout` and `docker/login-action` support. +- Build sample workflow fixtures. + +### Milestone 4: Unraid packaging + +- Create compose example. +- Document Unraid template fields and recommended mounts. +- Add upgrade and rollback instructions. + +### Milestone 5: Quality and regression safety + +- Add smoke-test script. +- Add local test harness. +- Add troubleshooting guide. +- Capture prior bug classes as regression cases. + +--- + +## Decision log expectations + +Create ADR-style notes under `docs/decisions/` for major decisions such as: + +- base image choice, +- root vs non-root default, +- socket mount vs DinD, +- bootstrap registration design, +- bundled tools list, +- release strategy. + +Each decision note should include: + +- context, +- decision, +- consequences, +- alternatives considered. + +--- + +## Success criteria + +This project is successful when: + +- a fresh operator can build and run the image with documented steps, +- the runner reliably executes checkout + Docker login + build + push workflows, +- Node-based actions work without runtime hacks, +- failures are diagnosable from logs and docs, +- upgrades are explicit and reversible, +- and the entire runner behavior is version-controlled and understandable. + +--- + +## Open questions for early clarification + +Before heavy implementation, clarify: + +1. Should v1 wrap the official `act_runner` binary or fork/build from source? +2. Is the preferred base image Debian slim or Ubuntu minimal? +3. Should v1 default to socket mount only, or support both socket mount and DinD variants from day one? +4. Should the repository include an Unraid XML/template artifact, or just docs plus compose examples? +5. Should the first release include a small helper CLI for registration/testing, or keep everything shell-only? +6. Should runner labels be opinionated by default, or minimal and operator-supplied? +7. Should custom CA trust be a first-class feature in v1? + +If these are unanswered, the agent should pause and ask before overcommitting to a direction. + +--- + +## Build order + +When starting implementation, follow this order: + +1. AGENT.md +2. README.md +3. ROADMAP.md +4. Dockerfile +5. entrypoint/bootstrap scripts +6. healthcheck/smoke tests +7. config examples +8. compose/unraid examples +9. troubleshooting docs +10. regression fixtures/tests + +--- + +## Final instruction + +Optimize for reliability, debuggability, and maintainability over cleverness. + +This project should feel like a stable internal platform component that the operator can trust, inspect, extend, and version for years. diff --git a/forgerunner.src/README.md b/forgerunner.src/README.md new file mode 100644 index 0000000..ff67725 --- /dev/null +++ b/forgerunner.src/README.md @@ -0,0 +1,421 @@ +
+ +# custom-gitea-runner + +A versioned, Docker-first, self-owned Gitea Actions runner platform for Unraid and Linux hosts. + +[Overview](#overview) • [Goals](#goals) • [Architecture](#architecture) • [Repository-layout](#repository-layout) • [Quick-start](#quick-start) • [Environment](#environment) • [Roadmap](#roadmap) • [Operations](#operations) + +
+ +--- + +## Overview + +`custom-gitea-runner` is a controlled replacement for opaque runner setups that are difficult to debug, mutate at startup, or break unexpectedly when upstream images or runtime assumptions change. + +The project packages a Gitea-compatible runner into a predictable Docker image with pinned dependencies, explicit startup logic, clean documentation, and testable operational workflows. The goal is to make the runner understandable, inspectable, and easy to version over time. + +This repository is designed for self-hosted environments where the operator wants direct control over: + +- base image selection, +- bundled tooling, +- startup and registration flow, +- Docker socket/build behavior, +- release/version policy, +- troubleshooting and rollback. + +--- + +## Why this exists + +This project exists to eliminate common self-hosted runner pain points such as: + +- missing runtime dependencies like Node.js, Git, or Docker CLI, +- fragile startup behavior that depends on mutable package installs, +- difficult-to-diagnose nested container failures, +- unclear registration/config persistence, +- and weak operational visibility when jobs fail early. + +Instead of treating the runner like a disposable black box, this repository treats it like an internal platform component. + +--- + +## Goals + +### Primary goals + +- Build a custom Docker image for a Gitea-compatible runner. +- Bundle required CI dependencies at image build time. +- Support checkout, Node-based actions, Docker login, Docker build, and Docker push workflows. +- Provide deterministic bootstrap and registration behavior. +- Provide clean deployment guidance for Unraid and standard Linux Docker hosts. +- Keep all operational knowledge versioned in-repo. + +### Secondary goals + +- Support custom CA trust. +- Support opinionated label templates. +- Support smoke testing and regression fixtures. +- Support future hardening tracks like rootless or DinD variants. + +### Non-goals + +- Replacing Gitea itself. +- Building a full control plane or autoscaling runner manager in v1. +- Solving every orchestration model on day one. + +--- + +## Architecture + +### Design principles + +- Deterministic image builds. +- No hidden runtime package installs in normal operation. +- Explicit entrypoint and healthcheck behavior. +- Pinned versions where practical. +- Clear separation of image build, registration, runtime config, and operations. +- Logs that are useful during failure, not just success. + +### Planned v1 stack + +- Debian slim or Ubuntu slim base image. +- Pinned `act_runner` binary or pinned upstream release artifact. +- Bundled tooling: + - `bash` + - `curl` + - `git` + - `jq` + - `node` + - `npm` + - `docker` + - `ca-certificates` + - `tini` +- Entrypoint script for validation, registration, and daemon startup. +- Healthcheck script for runtime verification. +- Example config and compose files. + +### Runtime model + +The runner container is intended to be long-lived and operator-managed. + +Preferred v1 modes: + +1. Pre-generated config mounted into the container. +2. Environment-driven one-time bootstrap registration when config is absent. + +For Docker build/push workflows, v1 assumes a trusted host and supports a mounted Docker socket. Future variants can harden or isolate this behavior. + +--- + +## Repository layout + +```text +custom-gitea-runner/ +├── AGENT.md +├── README.md +├── ROADMAP.md +├── CHANGELOG.md +├── LICENSE +├── .gitignore +├── .env.example +├── docker/ +│ ├── runner/ +│ │ ├── Dockerfile +│ │ ├── docker-entrypoint.sh +│ │ ├── healthcheck.sh +│ │ └── smoke-test.sh +│ └── compose/ +│ ├── docker-compose.example.yml +│ └── unraid-template-notes.md +├── config/ +│ ├── runner.example.yaml +│ ├── labels.example.env +│ └── trusted-ca/ +├── scripts/ +│ ├── register-runner.sh +│ ├── deregister-runner.sh +│ ├── verify-runtime.sh +│ ├── build-image.sh +│ ├── publish-image.sh +│ └── test-local-runner.sh +├── docs/ +│ ├── architecture.md +│ ├── operations.md +│ ├── troubleshooting.md +│ ├── unraid.md +│ └── decisions/ +│ └── 0001-base-image.md +├── test/ +│ ├── fixtures/ +│ ├── sample-workflows/ +│ └── smoke/ +└── src/ + └── optional/ +``` + +--- + +## Quick start + +### 1. Create the repository + +Create a new Gitea repository named `custom-gitea-runner` and commit the initial documentation set: + +- `AGENT.md` +- `README.md` +- `ROADMAP.md` +- `CHANGELOG.md` +- `.gitignore` +- `.env.example` + +### 2. Build the first image + +Once the Dockerfile exists: + +```bash +docker build -t custom-gitea-runner:v0.1.0 -f docker/runner/Dockerfile . +``` + +### 3. Provide runtime configuration + +Create a `.env` file from `.env.example` and decide whether to: + +- mount a pre-generated runner config, or +- let the container self-register on first boot. + +### 4. Start the runner + +Use Docker Compose or the equivalent Unraid template settings to start the container with: + +- persistent config mount, +- persistent work directory, +- Docker socket mount if build/push is required, +- required env vars. + +### 5. Run smoke workflows + +Before production use, validate at minimum: + +- checkout-only workflow, +- Node-based action workflow, +- Docker login workflow, +- Docker build/push workflow. + +--- + +## Environment + +Planned environment variables for bootstrap mode: + +| Variable | Required | Purpose | +|---|---:|---| +| `GITEA_INSTANCE_URL` | Yes | Base URL of the Gitea instance. | +| `GITEA_RUNNER_TOKEN` | Yes | Registration token for the runner. | +| `GITEA_RUNNER_NAME` | Yes | Human-readable runner name. | +| `GITEA_RUNNER_LABELS` | No | Comma-separated label list. | +| `GITEA_RUNNER_WORKDIR` | No | Working directory inside the container. | +| `GITEA_RUNNER_CONFIG_PATH` | No | Path to the runner config file. | +| `TZ` | No | Time zone for logs and runtime behavior. | + +Future environment variables may include: + +- custom CA paths, +- logging mode, +- healthcheck tuning, +- Docker socket override, +- feature flags for experimental runner behavior. + +--- + +## Example deployment model + +### Docker Compose direction + +The project will include a compose example that follows this pattern: + +- pinned image tag, +- mounted runner config, +- mounted work directory, +- mounted Docker socket, +- explicit restart policy, +- explicit environment variables. + +Example shape: + +```yaml +services: + gitea-runner: + image: custom-gitea-runner:v0.1.0 + container_name: custom-gitea-runner + restart: unless-stopped + environment: + GITEA_INSTANCE_URL: https://git.example.com + GITEA_RUNNER_NAME: unraid-runner-01 + GITEA_RUNNER_TOKEN: ${GITEA_RUNNER_TOKEN} + GITEA_RUNNER_LABELS: ubuntu-latest,docker + TZ: America/Chicago + volumes: + - ./config:/config + - ./work:/work + - /var/run/docker.sock:/var/run/docker.sock +``` + +### Unraid direction + +The Unraid notes should document: + +- repository/image field, +- appdata path recommendations, +- variable definitions, +- volume mounts, +- Docker socket usage, +- update workflow, +- rollback workflow. + +--- + +## Operations + +### Expected startup behavior + +At startup, the container should log: + +- image version, +- embedded git revision if available, +- `act_runner` version, +- `node` version, +- `docker` version, +- config path, +- work path, +- registration mode, +- target Gitea URL, +- active labels. + +### Health behavior + +The healthcheck should confirm: + +- runner process is alive, +- config exists, +- required tools exist, +- Docker socket is available when configured. + +### Upgrade workflow + +Recommended upgrade process: + +1. Pull or build a new pinned image tag. +2. Review `CHANGELOG.md`. +3. Stop the existing container. +4. Update image tag in compose or Unraid template. +5. Start the container. +6. Verify logs and healthcheck. +7. Run smoke workflow. + +### Rollback workflow + +1. Stop the container. +2. Revert to prior known-good image tag. +3. Start the container. +4. Verify registration/config still valid. +5. Confirm smoke workflow success. + +--- + +## Documentation set + +This repository should maintain the following docs as first-class assets: + +- `AGENT.md` — build rules, architecture constraints, agent instructions. +- `README.md` — project overview, install/use guidance, operational entry point. +- `ROADMAP.md` — phased plan with active status tracking. +- `CHANGELOG.md` — release history. +- `docs/architecture.md` — deeper design details. +- `docs/operations.md` — runtime/admin guidance. +- `docs/troubleshooting.md` — symptom-driven fixes. +- `docs/unraid.md` — Unraid-specific deployment instructions. +- `docs/decisions/*.md` — ADR-style architecture decisions. + +--- + +## Testing strategy + +Required validation layers: + +- image build verification, +- runtime tool verification, +- registration smoke tests, +- workflow smoke tests, +- regression tests for previously encountered failure classes. + +The first workflows to validate should be: + +1. `actions/checkout` +2. Node-based action execution +3. `docker/login-action` +4. `docker build` +5. `docker push` + +--- + +## Roadmap + +Project planning lives in [`ROADMAP.md`](./ROADMAP.md). + +High-level phases: + +- Phase 0: Research and design +- Phase 1: Base image and bootstrap +- Phase 2: Registration/config flows +- Phase 3: Docker workflow support +- Phase 4: Test harness and smoke validation +- Phase 5: Unraid packaging and docs +- Phase 6: Hardening and enhancements + +--- + +## Release model + +Recommended versioning: + +- `v0.1.0` +- `v0.1.1` +- `v0.2.0` + +`latest` may exist as a convenience tag, but documentation should always recommend pinned versions for real deployments. + +Every release should map to: + +- a Git tag, +- a CHANGELOG entry, +- image metadata labels, +- and documented upgrade notes where relevant. + +--- + +## Contributing workflow + +Recommended development loop: + +1. Update docs first when requirements or behavior change. +2. Make small, reviewable changes. +3. Keep scripts simple and auditable. +4. Add regression coverage for painful bugs. +5. Prefer explicit configuration over implicit behavior. + +--- + +## Current status + +This repository is in planning/bootstrap stage. + +The immediate next steps are: + +- finalize the architecture direction, +- scaffold the repository, +- build the first pinned image, +- implement registration/bootstrap scripts, +- validate smoke workflows, +- document Unraid deployment. diff --git a/forgerunner.src/ROADMAP.md b/forgerunner.src/ROADMAP.md new file mode 100644 index 0000000..a10ccb2 --- /dev/null +++ b/forgerunner.src/ROADMAP.md @@ -0,0 +1,308 @@ +# ROADMAP.md + +## Project + +**Name:** custom-gitea-runner + +**Status:** Planning / bootstrap + +**Objective:** +Deliver a self-owned, versioned, Docker-first Gitea runner platform that is reliable on Unraid and Linux, easy to debug, and explicitly documented from image build through runtime operations. + +--- + +## Guiding outcomes + +The project is considered successful when it can: + +- run as a pinned Docker image, +- execute checkout + Node-based + Docker build/push workflows reliably, +- register and restart predictably, +- surface actionable logs during failure, +- and be upgraded or rolled back cleanly. + +--- + +## Project phases + +## Phase 0 — Research and design + +**Status:** Active + +### Goals + +- Define architecture, scope, and first-release constraints. +- Capture prior failure modes as design inputs. +- Establish documentation and decision-tracking structure. + +### Tasks + +- [x] Write `AGENT.md` +- [x] Write `README.md` +- [x] Write `ROADMAP.md` +- [ ] Create `CHANGELOG.md` +- [ ] Create `.env.example` +- [ ] Create ADR template under `docs/decisions/` +- [ ] Write `docs/architecture.md` +- [ ] Decide base image strategy +- [ ] Decide socket-mount vs DinD position for v1 +- [ ] Decide registration mode defaults + +### Exit criteria + +- Scope is documented. +- Core repo structure is defined. +- Major open decisions are listed. +- First implementation sequence is agreed. + +--- + +## Phase 1 — Base image and bootstrap + +**Status:** Planned + +### Goals + +- Produce the first buildable runner image. +- Eliminate runtime package mutation. +- Establish deterministic startup behavior. + +### Tasks + +- [ ] Create `docker/runner/Dockerfile` +- [ ] Pin base image tag +- [ ] Pin `act_runner` source/version +- [ ] Install required dependencies at build time: + - [ ] bash + - [ ] curl + - [ ] git + - [ ] jq + - [ ] nodejs + - [ ] npm + - [ ] docker CLI + - [ ] ca-certificates + - [ ] tini + - [ ] tzdata +- [ ] Create `docker/runner/docker-entrypoint.sh` +- [ ] Create `docker/runner/healthcheck.sh` +- [ ] Add image metadata labels +- [ ] Verify startup prints tool versions + +### Exit criteria + +- Image builds locally. +- Container starts cleanly. +- `node`, `git`, `docker`, and `act_runner` are all present. +- Healthcheck script returns useful status. + +--- + +## Phase 2 — Registration and config flows + +**Status:** Planned + +### Goals + +- Support both mounted-config and env-driven registration. +- Make bootstrap idempotent. +- Ensure config persistence survives restarts. + +### Tasks + +- [ ] Create `config/runner.example.yaml` +- [ ] Create `config/labels.example.env` +- [ ] Create `scripts/register-runner.sh` +- [ ] Create `scripts/deregister-runner.sh` +- [ ] Add config path validation +- [ ] Add first-boot registration flow +- [ ] Add re-run safe bootstrap logic +- [ ] Document required environment variables +- [ ] Validate restart behavior with existing config + +### Exit criteria + +- Runner can register successfully. +- Existing config is reused without duplicate registration. +- Missing configuration fails fast with clear logs. + +--- + +## Phase 3 — Docker workflow support + +**Status:** Planned + +### Goals + +- Prove the runner can handle real Docker-centric CI workloads. +- Ensure JavaScript-based actions work out of the box. + +### Tasks + +- [ ] Validate `actions/checkout` +- [ ] Validate Node-based action runtime +- [ ] Validate `docker/login-action` +- [ ] Validate `docker build` +- [ ] Validate `docker push` +- [ ] Add support notes for self-hosted Gitea Container Registry +- [ ] Validate mounted Docker socket usage +- [ ] Document permission expectations for `/var/run/docker.sock` +- [ ] Evaluate `buildx` as optional enhancement + +### Exit criteria + +- Standard Docker build/push workflows pass. +- No runtime install hacks are needed. +- Node-based actions work on first boot. + +--- + +## Phase 4 — Test harness and smoke validation + +**Status:** Planned + +### Goals + +- Convert operational pain into repeatable tests. +- Establish confidence before release. + +### Tasks + +- [ ] Create `docker/runner/smoke-test.sh` +- [ ] Create `scripts/verify-runtime.sh` +- [ ] Create `scripts/test-local-runner.sh` +- [ ] Add `test/sample-workflows/checkout.yml` +- [ ] Add `test/sample-workflows/node-action.yml` +- [ ] Add `test/sample-workflows/docker-login.yml` +- [ ] Add `test/sample-workflows/docker-build-push.yml` +- [ ] Add regression test cases for: + - [ ] missing `node` + - [ ] broken Docker socket access + - [ ] invalid registration config + - [ ] startup tool validation failures +- [ ] Document how to run smoke tests locally + +### Exit criteria + +- Smoke tests are runnable by an operator. +- Known painful regressions are covered. +- Runtime validation is part of the normal release flow. + +--- + +## Phase 5 — Unraid packaging and docs + +**Status:** Planned + +### Goals + +- Make deployment smooth in the real target environment. +- Provide operational documentation that matches actual host usage. + +### Tasks + +- [ ] Create `docker/compose/docker-compose.example.yml` +- [ ] Create `docker/compose/unraid-template-notes.md` +- [ ] Write `docs/unraid.md` +- [ ] Write `docs/operations.md` +- [ ] Write `docs/troubleshooting.md` +- [ ] Document update procedure +- [ ] Document rollback procedure +- [ ] Document appdata path recommendations +- [ ] Document Docker socket trust model +- [ ] Optionally create Unraid XML/template artifact + +### Exit criteria + +- Operator can deploy from docs alone. +- Unraid-specific steps are explicit. +- Upgrade and rollback are documented and tested. + +--- + +## Phase 6 — Hardening and enhancements + +**Status:** Backlog + +### Goals + +- Expand safety and flexibility after the baseline runner is stable. + +### Candidate enhancements + +- [ ] Rootless variant +- [ ] DinD variant +- [ ] Dedicated BuildKit support +- [ ] Ephemeral single-job runner mode +- [ ] Structured JSON logging +- [ ] Metrics/exporter support +- [ ] Label policy controls +- [ ] Custom CA bootstrap helpers +- [ ] Small helper CLI in TypeScript +- [ ] Multi-runner orchestration concepts + +### Exit criteria + +- Enhancements are prioritized based on real operational need. +- Stability is not regressed by added flexibility. + +--- + +## Immediate next actions + +### Next 10 actions + +1. Create `CHANGELOG.md` +2. Create `.env.example` +3. Scaffold repo directories +4. Write `docs/architecture.md` +5. Write first ADR: base image choice +6. Create initial `Dockerfile` +7. Create `docker-entrypoint.sh` +8. Create `healthcheck.sh` +9. Build first local image +10. Verify runtime toolchain inside container + +--- + +## Risks and watch items + +### Technical risks + +- Upstream `act_runner` behavior may still impose constraints even with a custom wrapper image. +- Docker socket usage is convenient but increases host trust exposure. +- Self-registration flows can become brittle if not made idempotent. +- Docker build/push success does not guarantee all third-party actions behave as expected. + +### Process risks + +- Letting docs lag implementation will erode the value of the project quickly. +- Overengineering v1 will delay a usable baseline. +- Supporting too many runtime modes too early may reduce stability. + +--- + +## Decision log to create + +Create ADRs for: + +- [ ] Base image selection +- [ ] Runner binary acquisition strategy +- [ ] Runtime user model +- [ ] Docker socket vs DinD +- [ ] Registration strategy +- [ ] Release and tagging policy + +--- + +## Definition of done for v0.1.0 + +`v0.1.0` should mean: + +- image builds reproducibly, +- runner registers successfully, +- startup validation is clear, +- `actions/checkout` works, +- Node-based actions work, +- Docker login/build/push works, +- docs cover install, operation, upgrade, rollback, and troubleshooting, +- and the release is tagged and documented in `CHANGELOG.md`. diff --git a/forgerunner.src/current build yml.png b/forgerunner.src/current build yml.png new file mode 100644 index 0000000..fb27348 Binary files /dev/null and b/forgerunner.src/current build yml.png differ diff --git a/placeholder.md b/placeholder.md deleted file mode 100644 index e69de29..0000000