Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
31db9df
docs: add prebuilt Caddy/CrowdSec toolchain image spec
Wikid82 Sep 7, 2026
17cec80
ci: add toolchain image workflow, key tooling, and split builder stages
Wikid82 Sep 7, 2026
c0ee119
refactor(docker): build the app image from the prebuilt toolchain image
Wikid82 Sep 7, 2026
5313427
feat(security): harden build-pipeline integrity verification
Wikid82 Sep 7, 2026
ba0d9df
perf(ci): stop forcing from-source rebuilds of the bundled toolchain
Wikid82 Sep 8, 2026
c1ee107
ci: route the weekly security rebuild through the toolchain image
Wikid82 Sep 8, 2026
01f5ba4
ci: document the toolchain image, right-size build timeouts, sweep st…
Wikid82 Sep 8, 2026
75ca9c8
chore(docker): exclude build-only scripts and bats tests from the ima…
Wikid82 Sep 8, 2026
e3b76d0
docs(ci): reconcile toolchain-image bootstrap notes with the image-co…
Wikid82 Sep 8, 2026
ea5680e
docs(qa): replace QA report with prebuilt toolchain image audit
Wikid82 Sep 8, 2026
999ca5e
feat(ci): prebuilt Caddy/CrowdSec toolchain image to fix Docker-build…
Wikid82 Sep 8, 2026
e06ff2a
chore(main): release 0.40.0
github-actions[bot] Sep 8, 2026
5bfe27c
ci: add consolidated integration-tests workflow (build once, fan out)
Wikid82 Sep 8, 2026
9009566
ci: update in-tree references to the consolidated integration workflow
Wikid82 Sep 8, 2026
03e30b8
chore(main): release 0.40.0 (#1305)
Wikid82 Sep 8, 2026
6f38be5
chore(docker): sync toolchain image pin to caddy-crowdsec-9eb9862f44b…
github-actions[bot] Sep 8, 2026
255a23d
ci: consolidate integration test suites into one build + fan-out work…
Wikid82 Sep 8, 2026
30f954c
fix(ci): restore the toolchain pin to match main's recipe
Wikid82 Sep 8, 2026
2e750b4
fix(ci): stop sync-pin-on-pr from committing to long-lived branches
Wikid82 Sep 8, 2026
2316e0f
fix(ci): restore toolchain pin on main + guard sync-pin-on-pr against…
Wikid82 Sep 8, 2026
6cc3a1c
chore(main): release 0.40.1
github-actions[bot] Sep 8, 2026
f169740
ci: bump integration image artifact retention to 3 days
Wikid82 Sep 8, 2026
0423373
ci: use chore prefix for the toolchain bump-bot commits and PRs
Wikid82 Sep 8, 2026
1dd3cec
chore(main): release 0.40.1 (#1311)
Wikid82 Sep 8, 2026
8a93887
ci: integration artifact retention + toolchain bump-bot commit prefix…
Wikid82 Sep 8, 2026
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: 11 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,17 @@ docs/implementation/
# -----------------------------------------------------------------------------
dist/

# -----------------------------------------------------------------------------
# Build-only helper scripts — used by .github/workflows/toolchain-image.yml and
# the quality-checks.yml verify-toolchain-pin / bats jobs from a plain checkout,
# never from inside a built container. The Dockerfile's `COPY scripts/` would
# otherwise ship them into /app/scripts/ in the runtime image.
# -----------------------------------------------------------------------------
scripts/tests/
scripts/toolchain-key.sh
scripts/verify-toolchain-pin.sh
scripts/lib/dockerfile-stage.sh

# -----------------------------------------------------------------------------
# Tools (not needed in image)
# -----------------------------------------------------------------------------
Expand Down
70 changes: 49 additions & 21 deletions .github/actions/build-charon-image/action.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
name: Build Charon image
description: >-
Build the Charon Docker image locally for integration / security-scan jobs,
with GitHub Actions layer caching (type=gha) so the multi-stage build is not
rebuilt cold on every run. Loads the image into the local Docker daemon.
Build the Charon Docker image locally for integration / security-scan jobs.
The custom Caddy + CrowdSec binaries come from the digest-pinned, daily-
rebuilt-and-Trivy-scanned prebuilt toolchain image
(ghcr.io/wikid82/charon-toolchain) via COPY --from — no xcaddy / CrowdSec
compile on this path. Every remaining stage is GitHub Actions layer-cached
(type=gha). Pin freshness is enforced per-PR by
scripts/verify-toolchain-pin.sh. Loads the image into the local Docker daemon.
inputs:
tag:
description: Image tag to load locally.
Expand All @@ -12,31 +16,54 @@ inputs:
description: Value passed as the CI build-arg.
required: false
default: 'false'
no-cache-filters:
builder-src:
description: >-
Comma-separated Dockerfile stages to force-rebuild (never restore from the
layer cache). Empty by default: every stage, including the expensive
caddy-builder xcaddy step, is GHA layer-cached — that is where the build
time is recovered. Suitable for the integration-test callers
(waf/crowdsec/rate-limit/cerberus), which exercise runtime behaviour and
do not care about dependency freshness.

CVE-scan-gate callers (security-pr.yml, supply-chain-pr.yml) MUST override
this with `caddy-builder,crowdsec-builder`. The caddy-builder and
crowdsec-builder stages patch pinned transitive dependencies in-place
(`go get pkg@fixed` in their Stage 2 blocks). A global build-arg bump does
not reliably invalidate the GHA layer-cache key for a stage that only
*consumes* that arg (the same edge case that produced CVE-2026-45135 and
the 2026-09-04 grpc-go v1.83.0 recurrence), so a restored stale layer keeps
shipping the superseded, still-vulnerable version. The release image
(docker-build.yml) already force-rebuilds caddy-builder for this reason.
Which source the Caddy / CrowdSec binaries come from:
prebuilt (default) — COPY --from the digest-pinned toolchain image
(ghcr.io/wikid82/charon-toolchain), no compile.
inline — compile caddy-inline / crowdsec-inline from source
(fork PR / bootstrap / offline; ~14 min).
required: false
default: prebuilt
ghcr-token:
description: >-
Token with packages:read, used to log in to ghcr.io so BuildKit can pull
the (private) prebuilt toolchain image. Callers pass secrets.GITHUB_TOKEN.
Composite actions cannot read the secrets context themselves, so this must
be threaded in from the calling workflow. Ignored when builder-src=inline;
a fork PR that cannot supply a working token should pass builder-src=inline.
required: false
default: ''
runs:
using: composite
steps:
- name: Resolve builder source stages
id: srcsel
shell: bash
env:
BUILDER_SRC: ${{ inputs.builder-src }}
run: |
set -euo pipefail
case "${BUILDER_SRC:-prebuilt}" in
inline)
echo "caddy=caddy-inline" >> "$GITHUB_OUTPUT"
echo "crowdsec=crowdsec-inline" >> "$GITHUB_OUTPUT" ;;
prebuilt)
echo "caddy=toolchain-prebuilt" >> "$GITHUB_OUTPUT"
echo "crowdsec=toolchain-prebuilt" >> "$GITHUB_OUTPUT" ;;
*)
echo "::error::build-charon-image: invalid builder-src '${BUILDER_SRC}' (want prebuilt|inline)"
exit 1 ;;
esac
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@37fe631027851001ddb9b187196cc803df7f5f0e # v4.3.0
- name: Log in to GHCR (pull prebuilt toolchain image)
if: inputs.builder-src != 'inline' && inputs.ghcr-token != ''
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ inputs.ghcr-token }}
- name: Build image
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7
with:
Expand All @@ -47,6 +74,7 @@ runs:
tags: ${{ inputs.tag }}
build-args: |
CI=${{ inputs.ci }}
CADDY_BUILDER_SRC=${{ steps.srcsel.outputs.caddy }}
CROWDSEC_BUILDER_SRC=${{ steps.srcsel.outputs.crowdsec }}
cache-from: type=gha,scope=charon-integration-image
cache-to: type=gha,mode=max,scope=charon-integration-image
no-cache-filters: ${{ inputs.no-cache-filters }}
2 changes: 1 addition & 1 deletion .github/instructions/testing.instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ This step:
- Test requests routing through Caddy proxy with full middleware
- **Port: 80 (User Traffic via Caddy)**
- **Location: `backend/integration/` with `//go:build integration` tag**
- **CI: Runs in separate workflows (cerberus-integration.yml, waf-integration.yml, etc.)**
- **CI: Runs in `integration-tests.yml` (one shared image build, then parallel `cerberus` / `waf` / `rate-limit` / `crowdsec` suite jobs)**

### Two Modes: Docker vs Vite

Expand Down
7 changes: 7 additions & 0 deletions .github/renovate.json
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,13 @@
],
"semanticCommitType": "chore"
},
{
"description": "The ghcr.io/wikid82/charon-toolchain digest pin (Dockerfile ARG CHARON_TOOLCHAIN_TAG / CHARON_TOOLCHAIN_DIGEST) is owned by .github/workflows/toolchain-image.yml's bot PR, NOT Renovate: its content-hash tag (caddy-crowdsec-<hex>) has no version series to follow (spec N7). Disabled here so a stray digest bump cannot land without the matching key change the freshness guard requires.",
"matchPackageNames": [
"ghcr.io/wikid82/charon-toolchain"
],
"enabled": false
},
{
"description": "Group GitHub Actions non-major updates into one PR",
"matchManagers": [
Expand Down
119 changes: 0 additions & 119 deletions .github/workflows/cerberus-integration.yml

This file was deleted.

137 changes: 0 additions & 137 deletions .github/workflows/crowdsec-integration.yml

This file was deleted.

Loading
Loading