Align CI tags, PR checks, and docs #4

Merged
eleith merged 1 commits from align-ci-tags-and-docs into main 2026-10-24 15:57:20 +00:00
22 changed files with 213 additions and 97 deletions

No files matched your search

+24 -5
View File
@@ -2,6 +2,12 @@ name: Build and Push dane-verify
on:
workflow_dispatch:
pull_request:
branches:
- main
paths:
- "dane-verify/**"
- ".github/workflows/build-dane-verify.yml"
push:
branches:
- main
@@ -12,11 +18,11 @@ on:
- "dane-verify/v*"
jobs:
build:
checks:
name: DANE checks
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout code
@@ -28,6 +34,18 @@ jobs:
- name: Run tests
run: bats dane-verify/tests/
build:
if: github.event_name != 'pull_request'
needs: checks
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Extract tag name
id: tag_name
run: |
@@ -42,14 +60,15 @@ jobs:
uses: docker/metadata-action@v5
with:
images: ghcr.io/${{ github.repository_owner }}/containers-dane-verify
flavor: latest=false
tags: |
type=raw,value=latest,enable={{is_default_branch}}
type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' }}
type=semver,pattern={{version}},value=${{ steps.tag_name.outputs.version }},enable=${{ github.ref_type == 'tag' }}
type=semver,pattern={{major}}.{{minor}},value=${{ steps.tag_name.outputs.version }},enable=${{ github.ref_type == 'tag' }}
type=semver,pattern={{major}},value=${{ steps.tag_name.outputs.version }},enable=${{ github.ref_type == 'tag' }}
- name: Login to GitHub Container Registry
if: github.event_name != 'pull_request'
if: github.ref == 'refs/heads/main' || github.ref_type == 'tag'
uses: docker/login-action@v3
with:
registry: ghcr.io
@@ -61,6 +80,6 @@ jobs:
with:
context: ./dane-verify
file: ./dane-verify/Dockerfile
push: true
push: ${{ github.ref == 'refs/heads/main' || github.ref_type == 'tag' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
+3 -2
View File
@@ -37,12 +37,13 @@ jobs:
images: ghcr.io/${{ github.repository_owner }}/containers-hledger
flavor: latest=false
tags: |
type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' }}
type=semver,pattern={{version}},value=${{ steps.tag_name.outputs.version }},enable=${{ github.ref_type == 'tag' }}
type=semver,pattern={{major}}.{{minor}},value=${{ steps.tag_name.outputs.version }},enable=${{ github.ref_type == 'tag' }}
type=semver,pattern={{major}},value=${{ steps.tag_name.outputs.version }},enable=${{ github.ref_type == 'tag' }}
- name: Login to GitHub Container Registry
if: github.ref_type == 'tag'
if: github.ref == 'refs/heads/main' || github.ref_type == 'tag'
uses: docker/login-action@v3
with:
registry: ghcr.io
@@ -55,6 +56,6 @@ jobs:
context: ./hledger
file: ./hledger/Dockerfile
platforms: linux/amd64
push: ${{ github.ref_type == 'tag' }}
push: ${{ github.ref == 'refs/heads/main' || github.ref_type == 'tag' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
+4 -2
View File
@@ -40,14 +40,16 @@ jobs:
uses: docker/metadata-action@v5
with:
images: ghcr.io/${{ github.repository_owner }}/containers-nvim
flavor: latest=false
tags: |
type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' }}
type=raw,value=${{ steps.tag_name.outputs.variant }},enable=${{ github.ref_type == 'tag' }}
type=semver,pattern={{version}},value=${{ steps.tag_name.outputs.version }},enable=${{ github.ref_type == 'tag' }}
type=semver,pattern={{major}}.{{minor}},value=${{ steps.tag_name.outputs.version }},enable=${{ github.ref_type == 'tag' }}
type=semver,pattern={{major}},value=${{ steps.tag_name.outputs.version }},enable=${{ github.ref_type == 'tag' }}
- name: Login to GitHub Container Registry
if: github.event_name != 'pull_request'
if: github.ref == 'refs/heads/main' || github.ref_type == 'tag'
uses: docker/login-action@v3
with:
registry: ghcr.io
@@ -59,6 +61,6 @@ jobs:
with:
context: ./nvim
file: ./nvim/Dockerfile
push: ${{ github.ref_type == 'tag' }}
push: ${{ github.ref == 'refs/heads/main' || github.ref_type == 'tag' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
+4 -2
View File
@@ -39,14 +39,16 @@ jobs:
uses: docker/metadata-action@v5
with:
images: ghcr.io/${{ github.repository_owner }}/containers-playwright
flavor: latest=false
tags: |
type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' }}
type=raw,value=${{ steps.tag_name.outputs.variant }},enable=${{ github.ref_type == 'tag' }}
type=semver,pattern={{version}},value=${{ steps.tag_name.outputs.version }},enable=${{ github.ref_type == 'tag' }}
type=semver,pattern={{major}}.{{minor}},value=${{ steps.tag_name.outputs.version }},enable=${{ github.ref_type == 'tag' }}
type=semver,pattern={{major}},value=${{ steps.tag_name.outputs.version }},enable=${{ github.ref_type == 'tag' }}
- name: Login to GitHub Container Registry
if: github.event_name != 'pull_request'
if: github.ref == 'refs/heads/main' || github.ref_type == 'tag'
uses: docker/login-action@v3
with:
registry: ghcr.io
@@ -58,6 +60,6 @@ jobs:
with:
context: ./playwright
file: ./playwright/Dockerfile
push: ${{ github.ref_type == 'tag' }}
push: ${{ github.ref == 'refs/heads/main' || github.ref_type == 'tag' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
+3 -2
View File
@@ -59,12 +59,13 @@ jobs:
images: ghcr.io/${{ github.repository_owner }}/containers-porkbun-ddns
flavor: latest=false
tags: |
type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' }}
type=semver,pattern={{version}},value=${{ steps.tag_name.outputs.version }},enable=${{ github.ref_type == 'tag' }}
type=semver,pattern={{major}}.{{minor}},value=${{ steps.tag_name.outputs.version }},enable=${{ github.ref_type == 'tag' }}
type=semver,pattern={{major}},value=${{ steps.tag_name.outputs.version }},enable=${{ github.ref_type == 'tag' }}
- name: Login to GitHub Container Registry
if: github.ref_type == 'tag'
if: github.ref == 'refs/heads/main' || github.ref_type == 'tag'
uses: docker/login-action@v3
with:
registry: ghcr.io
@@ -76,6 +77,6 @@ jobs:
with:
context: ./porkbun-ddns
file: ./porkbun-ddns/Dockerfile
push: ${{ github.ref_type == 'tag' }}
push: ${{ github.ref == 'refs/heads/main' || github.ref_type == 'tag' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
+4 -3
View File
@@ -36,14 +36,15 @@ jobs:
uses: docker/metadata-action@v5
with:
images: ghcr.io/${{ github.repository_owner }}/containers-ssh
flavor: latest=false
tags: |
type=raw,value=latest,enable={{is_default_branch}}
type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' }}
type=semver,pattern={{version}},value=${{ steps.tag_name.outputs.version }},enable=${{ github.ref_type == 'tag' }}
type=semver,pattern={{major}}.{{minor}},value=${{ steps.tag_name.outputs.version }},enable=${{ github.ref_type == 'tag' }}
type=semver,pattern={{major}},value=${{ steps.tag_name.outputs.version }},enable=${{ github.ref_type == 'tag' }}
- name: Login to GitHub Container Registry
if: github.event_name != 'pull_request'
if: github.ref == 'refs/heads/main' || github.ref_type == 'tag'
uses: docker/login-action@v3
with:
registry: ghcr.io
@@ -55,6 +56,6 @@ jobs:
with:
context: ./ssh
file: ./ssh/Dockerfile
push: true
push: ${{ github.ref == 'refs/heads/main' || github.ref_type == 'tag' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
+4 -3
View File
@@ -36,14 +36,15 @@ jobs:
uses: docker/metadata-action@v5
with:
images: ghcr.io/${{ github.repository_owner }}/containers-wg-verify
flavor: latest=false
tags: |
type=raw,value=latest,enable={{is_default_branch}}
type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' }}
type=semver,pattern={{version}},value=${{ steps.tag_name.outputs.version }},enable=${{ github.ref_type == 'tag' }}
type=semver,pattern={{major}}.{{minor}},value=${{ steps.tag_name.outputs.version }},enable=${{ github.ref_type == 'tag' }}
type=semver,pattern={{major}},value=${{ steps.tag_name.outputs.version }},enable=${{ github.ref_type == 'tag' }}
- name: Login to GitHub Container Registry
if: github.event_name != 'pull_request'
if: github.ref == 'refs/heads/main' || github.ref_type == 'tag'
uses: docker/login-action@v3
with:
registry: ghcr.io
@@ -55,6 +56,6 @@ jobs:
with:
context: ./wg-verify
file: ./wg-verify/Dockerfile
push: true
push: ${{ github.ref == 'refs/heads/main' || github.ref_type == 'tag' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
+4 -3
View File
@@ -36,14 +36,15 @@ jobs:
uses: docker/metadata-action@v5
with:
images: ghcr.io/${{ github.repository_owner }}/containers-yq
flavor: latest=false
tags: |
type=raw,value=latest,enable={{is_default_branch}}
type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' }}
type=semver,pattern={{version}},value=${{ steps.tag_name.outputs.version }},enable=${{ github.ref_type == 'tag' }}
type=semver,pattern={{major}}.{{minor}},value=${{ steps.tag_name.outputs.version }},enable=${{ github.ref_type == 'tag' }}
type=semver,pattern={{major}},value=${{ steps.tag_name.outputs.version }},enable=${{ github.ref_type == 'tag' }}
- name: Login to GitHub Container Registry
if: github.event_name != 'pull_request'
if: github.ref == 'refs/heads/main' || github.ref_type == 'tag'
uses: docker/login-action@v3
with:
registry: ghcr.io
@@ -55,6 +56,6 @@ jobs:
with:
context: ./yq
file: ./yq/Dockerfile
push: true
push: ${{ github.ref == 'refs/heads/main' || github.ref_type == 'tag' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
+4
View File
@@ -3,6 +3,10 @@ workspace:
path: app
when:
- event: pull_request
branch: main
path:
include: [".woodpecker/build-dane-verify.yml", "dane-verify/**"]
- event: push
branch: main
path:
+5 -1
View File
@@ -28,10 +28,14 @@ steps:
image: woodpeckerci/plugin-docker-buildx:6.0.3
settings:
repo: git.eleith.com/eleith.private/hledger
username: eleith
dockerfile: hledger/Dockerfile
context: hledger
platforms: linux/amd64
dry_run: true
registry: https://git.eleith.com
password:
from_secret: gitea_docker_registry
tags: latest
when:
- event: push
branch: main
+5 -1
View File
@@ -37,9 +37,13 @@ steps:
image: woodpeckerci/plugin-docker-buildx:6.0.3
settings:
repo: git.eleith.com/eleith.private/nvim
username: eleith
dockerfile: nvim/Dockerfile
context: nvim
dry_run: true
registry: https://git.eleith.com
password:
from_secret: gitea_docker_registry
tags: latest
when:
- event: push
branch: main
+5 -1
View File
@@ -36,9 +36,13 @@ steps:
image: woodpeckerci/plugin-docker-buildx:6.0.3
settings:
repo: git.eleith.com/eleith.private/playwright
username: eleith
dockerfile: playwright/Dockerfile
context: playwright
dry_run: true
registry: https://git.eleith.com
password:
from_secret: gitea_docker_registry
tags: latest
when:
- event: push
branch: main
+5 -1
View File
@@ -39,9 +39,13 @@ steps:
image: woodpeckerci/plugin-docker-buildx:6.0.3
settings:
repo: git.eleith.com/eleith.private/porkbun-ddns
username: eleith
dockerfile: porkbun-ddns/Dockerfile
context: porkbun-ddns
dry_run: true
registry: https://git.eleith.com
password:
from_secret: gitea_docker_registry
tags: latest
when:
- event: push
branch: main
+8 -46
View File
@@ -1,49 +1,11 @@
# 🤖 Hello, Fellow Agent!
# 🤖 Agents
Welcome to the utility belt. To help you help us, here's some context and rules for making updates here.
Read the relevant docs before making changes:
## 📜 Principles
- [Building](docs/building.md)
- [Testing](docs/testing.md)
- [Releases](docs/releases.md)
- [Secrets](docs/secrets.md)
- **Alpine First:** Prefer Alpine where suitable. Keep images small and focused; document why another base is needed.
- **Security:** Do not hardcode credentials. Prefer read-only mounted secrets; keep credentials out of logs and command arguments.
- **Accuracy:** Scripts like `check.sh` are precise. When updating them, ensure you maintain the core DANE/TLSA logic correctly.
## 🛠 Working with the Codebase
### Dockerfiles
- Use supported stable base-image versions and install only the dependencies the tool needs.
- Minimize layers by combining `RUN` commands where it makes sense.
- Use `ENTRYPOINT` for main commands in specialized containers like `dane-verify`.
### Scripts
- Bash is fine, but keep it readable. Use `set -e` for safety.
- Use `jq` for JSON; `awk`, `sed`, and `grep` are useful for text output from tools like `dig` and `openssl`.
- Bound network requests with timeouts and return nonzero on failures.
### CI/CD
- We use both GitHub Actions and [Woodpecker CI](https://woodpecker-ci.org/). Keep their build, test, and publishing behavior aligned.
- Prefer the newer `hledger` and `porkbun-ddns` workflows as examples; older workflows may use different publishing conventions.
## ✅ New Container Checklist
- **Purpose:** One clear command contract. Keep scheduling outside one-shot tools.
- **Image:** Minimal supported base, documented exceptions, and only necessary dependencies.
- **Privileges:** Run as non-root where practical. Document required users, mounts, and capabilities.
- **Tests:** Run lint and offline tests before building in both CI systems. Make failures easy to locate.
- **Releases:** For new images, build `main` without publishing and publish versioned release tags, not `latest`. Document tag names, show pinned usage examples, and register the package in `.github/workflows/cleanup.yml`.
- **Docs:** Brief purpose, working usage example, arguments, and important runtime requirements. No shared framework is required.
## ✅ How to Test
Run each container's documented local checks. For example:
```bash
shellcheck porkbun-ddns/update.sh porkbun-ddns/tests/update_test.sh
bash porkbun-ddns/tests/update_test.sh
```
The user handles Docker builds and runs. Provide commands when needed, but do not execute Docker commands. Live API checks require explicit user approval.
## 🤝 Need Help?
If something is unclear, just ask the user! We're all in this together.
- Leave Docker commands to the user.
- Keep documentation short and match the surrounding style.
+6 -13
View File
@@ -3,7 +3,7 @@
This repo is a collection of small, focused Docker containers for use in crons,
ci and cd.
## 🛠 What's inside?
## 🧰 What's inside?
- [**dane-verify**](./dane-verify): A specialized tool to monitor a domain's
DNSSEC and TLSA records
@@ -19,16 +19,9 @@ ci and cd.
- [**yq**](./yq): A lightweight image with Mike Farah's `yq` and `bash`
- [**playwright**](./playwright): playwright + node 26 + Temporal
## 🚀 Quick Start
## 📚 Docs
Each container lives in its own directory with its own `Dockerfile`. To build them:
```bash
docker build -t dane-verify ./dane-verify
docker build -t porkbun-ddns ./porkbun-ddns
docker build --platform linux/amd64 -t hledger ./hledger
docker build -t nvim ./nvim
docker build -t ssh ./ssh
docker build -t wg-verify ./wg-verify
docker build -t yq ./yq
```
- [Building](docs/building.md)
- [Testing](docs/testing.md)
- [Releases](docs/releases.md)
- [Secrets](docs/secrets.md)
+31
View File
@@ -0,0 +1,31 @@
# 🛠 Building
Build from the repo root:
```bash
docker build -t porkbun-ddns ./porkbun-ddns
docker build -t hledger ./hledger
```
Check the container README and Dockerfile for build options
## Dockerfiles
- Prefer supported Alpine releases
- Combine related `RUN` commands for smaller image sizes
- Use `ENTRYPOINT` for dedicated commands. Keep toolchain images usable by CI shells.
- Run as non-root where practical. Document required mounts and capabilities.
## Shell scripts
- Keep functions focused and `main` easy to follow.
- Use `set -euo pipefail` in Bash scripts.
- Use `jq` for JSON and `awk`, `sed`, or `grep` for text.
- Give network requests timeouts and return nonzero on failures.
## Adding a container
1. Add its directory, `Dockerfile`, scripts, and README with usage and arguments.
2. Add [tests and PR checks](testing.md) in GitHub Actions and Woodpecker.
3. Add [release workflows and cleanup registration](releases.md).
4. Add it to [What's inside?](../README.md).
+41
View File
@@ -0,0 +1,41 @@
# 🏷 Releases
| Event | Result |
|-------|--------|
| Pull request | Existing checks |
| Push to `main` | Build and publish `latest` for updated containers |
| Release tag | Build and publish version tags |
`latest` follows `main`. Release builds leave it unchanged.
## Tags
Release tags use `<container>/vX.Y.Z`. Choose an unused version and tag `main`:
```bash
tag=porkbun-ddns/v0.0.3
git switch main
git pull --ff-only
git tag "$tag"
git push origin "$tag"
```
Release pipelines publish `X`, `X.Y`, and `X.Y.Z` image tags.
Neovim and Playwright also publish their version-specific toolchain tags.
## Registries
- Public: `ghcr.io/eleith/containers-<name>`
- Private: `git.eleith.com/eleith.private/<name>`
GitHub Actions and Woodpecker publish matching release tags.
## Adding release workflows
- Add `.github/workflows/build-<name>.yml` and `.woodpecker/build-<name>.yml`.
- Keep version extraction and publishing behavior aligned in both workflows.
- In GitHub Actions, disable automatic `latest` with `flavor: latest=false` and
enable the explicit `latest` tag only for `refs/heads/main`.
- In Woodpecker, use `tags: latest` for main builds and a version-only `.tags`
file for releases.
+30
View File
@@ -0,0 +1,30 @@
# 🔐 Secrets
## Files
- Store credentials outside the repo and mount them read-only.
- Keep credentials out of images, logs, and command arguments.
- Follow the container README for the required file format and mount destination.
Bind mount source paths refer to the Docker host, including jobs launched by a
scheduler container.
## Users and permissions
Mounted files retain their host ownership and permissions. Check them with:
```bash
stat -c '%u:%g %a' /path/to/credentials.json
```
Set the container's `--user` to a UID:GID that can read the file. For a file owned
by your current host user, use `--user "$(id -u):$(id -g)"`. In Compose, set `user:`
on the service reading the file.
The scheduler and each container it launches have their own runtime user.
Keep credential files restricted to the users that need them.
## CI
Use GitHub Actions secrets and Woodpecker `from_secret` for registry and
notification credentials. Scope them to the steps that need them.
+18
View File
@@ -0,0 +1,18 @@
# ✅ Testing
## Local checks
Install Bash, jq, ShellCheck, and Bats to run the current suites:
```bash
shellcheck porkbun-ddns/update.sh porkbun-ddns/tests/update_test.sh
bash porkbun-ddns/tests/update_test.sh
bats dane-verify/tests/
```
These suites mock network calls. Cover validation, failure, and unchanged paths
when changing scripts. Test failures should identify the test and source line.
## CI
Existing checks run on matching pull requests, pushes to `main`, and release tags.
+1 -5
View File
@@ -52,11 +52,7 @@ The private registry image is `git.eleith.com/eleith.private/hledger:1.99.5`.
Release tags use `hledger/vX.Y.Z`, matching the packaged hledger version.
For example, `hledger/v1.99.5` publishes `1`, `1.99`, and `1.99.5`.
There is no extra tool-prefixed tag and no `latest`; pin the full version tag
or image digest for CI.
Pushes to `main` build without publishing. Release tags publish via
GitHub Actions and Woodpecker, like `nvim`.
See [Releases](../docs/releases.md) for `latest` and publishing.
## ⚙️ Build
+2 -4
View File
@@ -87,10 +87,8 @@ descriptive one naming what is inside:
1 1.0 1.0.0 0.12.1-luals3.19.1-stylua2.5.2
```
The descriptive tag is derived from this `Dockerfile`'s build args at build
time, so it cannot drift. There is **no `latest`**: pin the descriptive tag (or
a semver tag) so a tool bump can never arrive unannounced. Pushes to `main`
build the image without publishing it.
The descriptive tag comes from the Dockerfile's build args.
See [Releases](../docs/releases.md) for `latest` and publishing.
## ⚙️ Build Args
+2 -3
View File
@@ -55,9 +55,8 @@ descriptive one naming what is inside:
1 1.0 1.0.0 1.61.1-node26
```
The descriptive tag is derived from this `Dockerfile` at build time, so it cannot drift.
There is **no `latest`** — pin `1.61.1-node26` (or a semver tag) so a Playwright or Node
bump can never arrive unannounced. Pushes to `main` build the image without publishing it.
The descriptive tag comes from the Dockerfile.
See [Releases](../docs/releases.md) for `latest` and publishing.
## ⚠️ Version pairing