Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 2 additions & 9 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -137,15 +137,8 @@ jobs:
pnpm render-linux-docker-project-manifest -- --config config/linux-docker-runners.yaml --env /tmp/linux-docker.env

windows_contract_trusted:
name: windows docker contract
if: >-
vars.WINDOWS_DOCKER_CONTRACT_ENABLED == 'true' &&
(github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository)
runs-on:
- self-hosted
- windows
- docker-capable
- private
name: windows template contract
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@v7
Expand Down
7 changes: 5 additions & 2 deletions .github/workflows/release-image.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ jobs:

- run: pnpm validate-config -- --config config/pools.yaml --env /tmp/release.env

- name: Enforce runner release freshness
run: pnpm check-runner-version -- --fail-after-days 21

- run: SMOKE_PLATFORM=linux/amd64 pnpm smoke-test

- uses: docker/setup-qemu-action@v4
Expand Down Expand Up @@ -273,11 +276,11 @@ jobs:

- run: |
docker run --rm --platform linux/amd64 --entrypoint /bin/sh "${{ steps.release_meta.outputs.image_ref }}" -lc \
'test "$(cd /actions-runner && ./bin/Runner.Listener --version)" = "2.334.0" && command -v pgrep && pgrep --version | head -n 1 && docker --version && node --version && python3 --version && terraform version | head -n 1'
'test "$(cd /actions-runner && ./bin/Runner.Listener --version)" = "$(cat /.runner-version)" && command -v pgrep && pgrep --version | head -n 1 && docker --version && node --version && python3 --version && terraform version | head -n 1'

- run: |
docker run --rm --platform linux/arm64 --entrypoint /bin/sh "${{ steps.release_meta.outputs.image_ref }}" -lc \
'test "$(cd /actions-runner && ./bin/Runner.Listener --version)" = "2.334.0" && command -v pgrep && pgrep --version | head -n 1 && docker --version && node --version && python3 --version && terraform version | head -n 1'
'test "$(cd /actions-runner && ./bin/Runner.Listener --version)" = "$(cat /.runner-version)" && command -v pgrep && pgrep --version | head -n 1 && docker --version && node --version && python3 --version && terraform version | head -n 1'

- if: ${{ inputs.publish_project_release }}
env:
Expand Down
32 changes: 32 additions & 0 deletions .github/workflows/runner-version-freshness.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: Runner Version Freshness

on:
schedule:
- cron: "17 7 * * *"
workflow_dispatch:

permissions:
contents: read

jobs:
freshness:
name: runner-version-freshness
runs-on: ubuntu-latest
timeout-minutes: 10
env:
GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
steps:
- uses: actions/checkout@v7

- uses: actions/setup-node@v6
with:
node-version: "24"

- uses: pnpm/action-setup@v6
with:
version: 10.32.1

- run: pnpm install --frozen-lockfile

- name: Fail before the disabled-update cutoff
run: pnpm check-runner-version -- --fail-after-days 21
1 change: 1 addition & 0 deletions .runner-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
2.335.1
21 changes: 9 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ The roadmap doc keeps the operator view short; the GitHub issues are the executi
## Why This Exists

- Keep Synology runner capacity locked to shell-safe workloads instead of gradually drifting into privileged Docker-host territory.
- Give private repos dedicated Linux and Windows Docker execution planes for `container:` jobs, service containers, and platform-native container workflows.
- Give private repos a release-backed Linux Docker plane, plus an explicitly experimental Windows template for lab validation.
- Give the org a second execution plane for macOS-native jobs through pooled Lume VMs without baking long-lived GitHub credentials into the base image.
- Make runner policy explicit in config and docs so downstream repos can tell, up front, which jobs belong on this fleet and which jobs should stay on GitHub-hosted runners.

Expand All @@ -45,7 +45,7 @@ The roadmap doc keeps the operator view short; the GitHub issues are the executi
| --- | --- | --- | --- |
| Synology Linux pools | Ephemeral containers built from a multi-arch runner image | shell jobs, JS actions, Python `3.12`, Terraform, docs and validation work | Docker socket jobs, `container:` jobs, service containers, privileged workloads |
| Linux Docker pool | Ephemeral runner containers on a dedicated Linux Docker host | `container:` jobs, service containers, Docker daemon workflows, Buildx, Kind, heavier Linux integration | untrusted public fork PRs, macOS-native jobs, turning Synology into a Docker host |
| Windows Docker pool | Ephemeral Windows runner containers on a dedicated Windows Docker host | Windows container workflows, PowerShell automation, Windows x64 jobs that need self-hosted capacity | untrusted public fork PRs, Linux container jobs, macOS-native jobs |
| Windows Docker template (experimental) | Unreleased example configuration for a separately managed Windows Docker host | configuration rendering and controlled lab evaluation | production workloads, release-backed installs, or any assumption that the example image is published by this project |
| Lume macOS pool | Ephemeral VM clones from a sealed macOS base image | macOS-native build and test lanes that need a real macOS host | long-lived snowflake VMs, secrets baked into the base image, ad hoc manual drift |

## Topology
Expand Down Expand Up @@ -172,7 +172,7 @@ If you set `resources.cpus` or `resources.pidsLimit`, `validate-config` and `ren
7. Build the runner image:

```bash
./scripts/build-image.sh ghcr.io/your-org/github-runner-fleet:0.1.9 --push
./scripts/build-image.sh ghcr.io/your-org/github-runner-fleet:0.2.2 --push
```

When `--push` is used without an explicit `--platform`, the helper now defaults to `linux/amd64,linux/arm64` so the same tag works across Intel and ARM Synology models. A single-arch tag combined with the wrong `platform` or `architecture` setting will fail at startup with `Exec format error`.
Expand Down Expand Up @@ -241,25 +241,22 @@ Recommended workflow labels:
- Docker-capable private repos: `runs-on: [self-hosted, linux, docker-capable, private]`
- Legacy private Synology-labeled shell jobs can also land on Linux Docker runners because those runners advertise `synology` plus `shell-only`.

## Windows Docker Pool
## Windows Docker Template (Experimental)

This repo also carries a Windows control plane for Docker-capable private workloads under [config/windows-runners.yaml](config/windows-runners.yaml). It stages ephemeral Windows runner containers on a dedicated Windows Server or Windows Docker host reachable over OpenSSH.
This repo carries an experimental Windows control-plane template under [config/windows-runners.yaml](config/windows-runners.yaml). The project does not currently build, publish, sign, or smoke-test a Windows image, and the example `ghcr.io/example/...-windows` reference is intentionally not part of the production release contract. Operators evaluating this template must supply and validate their own Windows image, Docker host, OpenSSH access, signing policy, and runtime proof.

Useful Windows Docker commands:
Template validation commands:

```bash
pnpm validate-windows-config -- --config config/windows-runners.yaml --env .env
pnpm validate-windows-github -- --config config/windows-runners.yaml --env .env
pnpm render-windows-compose -- --config config/windows-runners.yaml --env .env --output docker-compose.windows.yml
pnpm render-windows-project-manifest -- --config config/windows-runners.yaml --env .env
pnpm install-windows-project -- --config config/windows-runners.yaml --env .env
pnpm drain-pool -- --pool windows-private --plane windows-docker --timeout 15m --windows-config config/windows-runners.yaml --env .env
pnpm teardown-windows-project -- --config config/windows-runners.yaml --env .env
```

The installer path uses `ssh` and `scp` to stage `compose.yaml`, a project-local `.env`, and a generated PowerShell deployment script onto `WINDOWS_DOCKER_HOST`, then runs `docker compose up -d` or `docker compose down` there. Runner containers mount the Windows Docker named pipe and register as ephemeral organization runners.
Install, drain, and teardown commands remain available for controlled development, but they do not establish production support. A future production contract must add a project-owned Windows image, immutable signing and attestation, native runtime smoke proof, and release-version parity before this plane can be advertised for workloads.

Recommended workflow labels:
Experimental workflow labels:

- Docker-capable Windows private repos: `runs-on: [self-hosted, windows, docker-capable, private]`

Expand Down Expand Up @@ -378,7 +375,7 @@ bash scripts/lume/install-launch-agent.sh
sudo bash scripts/lume/install-system-launch-daemons.sh --disable-user-lume-agent
```

Keep the Lume runner env file outside git and locked down with `chmod 600`. The host controller reads that file and copies it into each guest VM just before starting the guest bootstrap. Do not bake GitHub credentials into the base VM image. If you want the macOS/base-image pipeline to stay pinned to a specific GitHub Actions runner build, set `pool.runnerVersion` in `config/lume-runners.yaml`; otherwise it falls back to `RUNNER_VERSION` from the env file.
Keep the Lume runner env file outside git and locked down with `chmod 600`. The host controller reads that file and copies it into each guest VM just before starting the guest bootstrap. Do not bake GitHub credentials into the base VM image. The default runner build comes from `.runner-version`; an explicit `RUNNER_VERSION` is intended only for controlled compatibility testing.

The launchd installers publish a source-independent controller runtime under `~/Library/Application Support/github-runner-fleet/controller/current` and point the Lume pool job at that path. Runtime `.env` remains beside that controller at `~/Library/Application Support/github-runner-fleet/controller/.env`, is mode `0600`, and is preserved when the source checkout moves or the installer is rerun. Override the runtime root with `GITHUB_RUNNER_FLEET_RUNTIME_ROOT` if this Mac needs a different stable location.

Expand Down
2 changes: 1 addition & 1 deletion config/linux-docker-runners.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
version: 1
image:
repository: ghcr.io/OMT-Global/github-runner-fleet
tag: 0.1.9
tag: 0.2.2

pools:
- key: linux-docker-private
Expand Down
1 change: 0 additions & 1 deletion config/lume-runners.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ pool:
guestPassword: ${LUME_GUEST_PASSWORD}
guestRunnerRoot: /Users/lume/actions-runner
guestWorkRoot: /Users/lume/actions-runner/_work
runnerVersion: 2.334.0
# telemetry:
# enabled: true
# endpoint: ${OTEL_EXPORTER_OTLP_ENDPOINT}
Expand Down
2 changes: 1 addition & 1 deletion config/pools.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
version: 1
image:
repository: ghcr.io/omt-global/github-runner-fleet
tag: 0.2.1
tag: 0.2.2
pools:
- key: synology-private
visibility: private
Expand Down
2 changes: 2 additions & 0 deletions config/windows-runners.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
version: 1
plane: windows-docker
# Experimental template only: this image is not published or supported by the
# github-runner-fleet release workflow. Supply a separately verified image.
pools:
- name: windows-private
group: windows-private
Expand Down
Loading
Loading