agent and source files
This commit is contained in:
@@ -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.
|
||||
@@ -0,0 +1,421 @@
|
||||
<div align="center">
|
||||
|
||||
# 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)
|
||||
|
||||
</div>
|
||||
|
||||
---
|
||||
|
||||
## 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.
|
||||
@@ -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`.
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 249 KiB |
Reference in New Issue
Block a user