|
1 | | -# Deerhide / Template for Container Image |
| 1 | +# Deerhide / Python GitHub Runner |
2 | 2 |
|
3 | | -## Pre-requisites |
| 3 | +Container image based on the [GitHub Actions Runner](https://github.com/actions/runner) with Python tooling, DevOps CLIs, and a full container build pipeline baked in. Designed to be used as a self-hosted runner that can build itself. |
4 | 4 |
|
5 | | -### Install `docker` |
6 | | -[See Docker documentation](https://docs.docker.com/get-docker/) |
| 5 | +## What's included |
7 | 6 |
|
8 | | -### Install tools |
| 7 | +### Base image |
| 8 | + |
| 9 | +`ghcr.io/actions/runner` (GitHub Actions Runner) |
| 10 | + |
| 11 | +### Python |
| 12 | + |
| 13 | +| Tool | Version | |
| 14 | +|------|---------| |
| 15 | +| Python | 3.12, 3.13, 3.14 (via deadsnakes PPA) | |
| 16 | +| Poetry | latest | |
| 17 | +| UV | latest | |
| 18 | + |
| 19 | +### DevOps CLIs |
| 20 | + |
| 21 | +| Tool | Description | |
| 22 | +|------|-------------| |
| 23 | +| [Argo Workflows CLI](https://github.com/argoproj/argo-workflows) | Workflow orchestration on Kubernetes | |
| 24 | +| [Kargo CLI](https://github.com/akuity/kargo) | Application lifecycle orchestration | |
| 25 | +| [pack](https://github.com/buildpacks/pack) | Cloud Native Buildpacks CLI | |
| 26 | +| [skopeo](https://github.com/containers/skopeo) | Container image registry operations | |
| 27 | + |
| 28 | +### Build pipeline tools |
| 29 | + |
| 30 | +These tools allow the image to run its own build pipeline as a self-hosted runner. |
| 31 | + |
| 32 | +| Tool | Description | |
| 33 | +|------|-------------| |
| 34 | +| [buildah](https://github.com/containers/buildah) | OCI container image builder | |
| 35 | +| [dive](https://github.com/wagoodman/dive) | Container filesystem analysis | |
| 36 | +| [trivy](https://github.com/aquasecurity/trivy) | Vulnerability scanner | |
| 37 | +| [hadolint](https://github.com/hadolint/hadolint) | Dockerfile/Containerfile linter | |
| 38 | +| [yq](https://github.com/mikefarah/yq) | YAML processor | |
| 39 | + |
| 40 | +## CI/CD |
| 41 | + |
| 42 | +### Workflows |
| 43 | + |
| 44 | +| Workflow | Trigger | Description | |
| 45 | +|----------|---------|-------------| |
| 46 | +| **CI** | Pull request to `master` | Commitlint, hadolint lint, test build | |
| 47 | +| **Release** | Push to `master` | Semantic release, build, scan, push to GHCR | |
| 48 | +| **Update tools** | Weekly (Monday 08:00 UTC) / manual | Checks for new tool versions, opens a PR | |
| 49 | + |
| 50 | +### Release process |
| 51 | + |
| 52 | +Releases are fully automated via [semantic-release](https://github.com/semantic-release/semantic-release). Pushing to `master` triggers version analysis based on [Conventional Commits](https://www.conventionalcommits.org/): |
| 53 | + |
| 54 | +| Commit prefix | Version bump | |
| 55 | +|---------------|-------------| |
| 56 | +| `fix:` | Patch (1.0.0 -> 1.0.1) | |
| 57 | +| `feat:` | Minor (1.0.0 -> 1.1.0) | |
| 58 | +| `feat!:` / `BREAKING CHANGE:` | Major (1.0.0 -> 2.0.0) | |
| 59 | + |
| 60 | +When a new version is determined, the release workflow: |
| 61 | + |
| 62 | +1. Creates a GitHub release with auto-generated notes |
| 63 | +2. Updates `CHANGELOG.md` |
| 64 | +3. Builds the image with `buildah` (OCI format, squashed layers) |
| 65 | +4. Runs `hadolint` lint validation |
| 66 | +5. Runs `dive` filesystem efficiency scan |
| 67 | +6. Runs `trivy` vulnerability scan (HIGH/CRITICAL) |
| 68 | +7. Pushes to GHCR with semver tags: `1.2.3`, `1.2`, `1`, `latest` |
| 69 | + |
| 70 | +### Image tags |
| 71 | + |
| 72 | +``` |
| 73 | +ghcr.io/deerhide/python-github-runner:latest |
| 74 | +ghcr.io/deerhide/python-github-runner:1 |
| 75 | +ghcr.io/deerhide/python-github-runner:1.2 |
| 76 | +ghcr.io/deerhide/python-github-runner:1.2.3 |
| 77 | +``` |
| 78 | + |
| 79 | +## Local development |
| 80 | + |
| 81 | +### Pre-requisites |
| 82 | + |
| 83 | +Install [Docker](https://docs.docker.com/get-docker/), then install the build tools: |
9 | 84 |
|
10 | 85 | ```bash |
11 | 86 | ./scripts/install_tools.sh |
12 | 87 | ``` |
13 | 88 |
|
14 | | -## How to build the container image |
| 89 | +### Configuration |
15 | 90 |
|
16 | | -### Update `manifest.yaml` |
| 91 | +Build configuration is defined in `manifest.yaml`: |
17 | 92 |
|
18 | 93 | ```yaml |
19 | | -name: deerhide_container_example |
20 | | -tags: |
| 94 | +name: python-github-runner |
| 95 | +tags: |
21 | 96 | - latest |
22 | | -registry: ghcr.io/deerhide/template_container_image |
| 97 | +registry: ghcr.io/deerhide/python-github-runner |
23 | 98 | build: |
24 | 99 | format: oci |
25 | 100 | args: |
26 | | - - APP_UID=1000 |
27 | | - - UBUNTU_VERSION=24.04 |
| 101 | + - RUNNER_VERSION=latest |
| 102 | + - ARGO_VERSION=3.6.4 |
| 103 | + - KARGO_VERSION=1.9.2 |
| 104 | + - PACK_VERSION=0.36.4 |
| 105 | + - DIVE_VERSION=0.12.0 |
| 106 | + - HADOLINT_VERSION=2.12.0 |
| 107 | + - YQ_VERSION=4.45.4 |
| 108 | + labels: |
| 109 | + - org.opencontainers.image.source=https://github.com/deerhide/python-github-runner |
| 110 | + - org.opencontainers.image.description="Python GitHub Runner" |
| 111 | + - org.opencontainers.image.licenses="MIT" |
| 112 | + - org.opencontainers.image.authors="Deerhide" |
| 113 | + - org.opencontainers.image.vendor="Deerhide" |
28 | 114 | ``` |
29 | 115 |
|
30 | | -### Authenticate to the container registry |
| 116 | +### Build |
| 117 | +
|
| 118 | +Authenticate to the container registry: |
31 | 119 |
|
32 | 120 | ```bash |
33 | 121 | skopeo login ghcr.io |
34 | 122 | ``` |
35 | 123 |
|
36 | | -### Launch Builder |
| 124 | +Run the full build pipeline (lint, build, scan, push): |
37 | 125 |
|
38 | 126 | ```bash |
39 | 127 | ./scripts/builder.sh |
40 | 128 | ``` |
| 129 | + |
| 130 | +### Contributing |
| 131 | + |
| 132 | +This project uses [Conventional Commits](https://www.conventionalcommits.org/). Commit messages are validated by commitlint on pull requests. |
| 133 | + |
| 134 | +```bash |
| 135 | +# Good |
| 136 | +git commit -m "feat: add kubectl to image" |
| 137 | +git commit -m "fix: correct trivy scan exit code" |
| 138 | +git commit -m "chore: update argo to v3.7.0" |
| 139 | + |
| 140 | +# Bad |
| 141 | +git commit -m "added stuff" |
| 142 | +git commit -m "WIP" |
| 143 | +``` |
| 144 | + |
| 145 | +## Project structure |
| 146 | + |
| 147 | +``` |
| 148 | +. |
| 149 | +├── Containerfile # Multi-stage container definition |
| 150 | +├── manifest.yaml # Build configuration and metadata |
| 151 | +├── .releaserc.yaml # Semantic release configuration |
| 152 | +├── .hadolint.yaml # Hadolint configuration |
| 153 | +├── .commitlintrc.yaml # Commitlint configuration |
| 154 | +├── .containerignore # Build context exclusions |
| 155 | +├── .dive-ci # Dive efficiency thresholds |
| 156 | +├── .github/ |
| 157 | +│ └── workflows/ |
| 158 | +│ ├── ci.yaml # PR validation |
| 159 | +│ ├── release.yaml # Semantic release + build + push |
| 160 | +│ └── update-tools.yaml # Automated tool version updates |
| 161 | +└── scripts/ |
| 162 | + ├── builder.sh # Local build orchestration |
| 163 | + ├── install_tools.sh # Build tool installer |
| 164 | + ├── lib_utils.sh # Logging utilities |
| 165 | + └── login_skopeo.sh # Registry authentication helper |
| 166 | +``` |
| 167 | + |
| 168 | +## License |
| 169 | + |
| 170 | +[MIT](LICENSE) |
0 commit comments