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
22 changes: 20 additions & 2 deletions caddy.Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -69,18 +69,36 @@
# Verify the LB is `externalTrafficPolicy: Local` + the parent
# Caddy's `trustedProxies` covers the LB CIDR range.

FROM caddy:2.11.4-builder@sha256:198d47eaee306d4d0c38a9960c89ff2c959aa29ad51d3e2dafa3e93ac961782a AS builder
FROM caddy:2.11.4-builder@sha256:4bdeabce8e79d36b23d1cba7d20598cec2c1117ace960d8ca06071f945e8fc9b AS builder

# `$CADDY_VERSION` is set by the base image itself (v2.11.4 here), so xcaddy
# builds exactly the version the builder ships and a skew is impossible by
# construction — there is no second version literal to forget. The tag on the
# FROM line is informational only; the digest is what resolves.
#
# The three `--replace` lines lift Caddy 2.11.4's own vendored deps past
# CVE-2026-46600 (x/net), CVE-2026-56852 (x/text) and GHSA-hrxh-6v49-42gf
# (grpc), which upstream has not yet re-released. `--replace` and not `--with`:
# `--with` also writes a blank import, and none of these modules has a package
# at its root, so it fails with "cannot find module providing package".
# Refresh or drop each line when Caddy ships a release that already carries the
# fixed version — a replace pinning an OLDER version than upstream would
# silently downgrade.
#
# cel-go is deliberately NOT in this list. v0.29.0 renames
# interpreter.Interpretable to InterpretableV2, which does not compile against
# 2.11.4's modules/caddyhttp/celmatcher.go — an upstream code change, not a
# version bump. GHSA-gcjh-h69q-9w9g (MEDIUM) therefore stays open until Caddy
# adopts it; see the SCA PR for the reachability note.
RUN --mount=type=cache,target=/go/pkg/mod,sharing=locked \
--mount=type=cache,target=/root/.cache,sharing=locked \
test -n "${CADDY_VERSION}" \
&& xcaddy build "${CADDY_VERSION}" \
--with github.com/grafana/certmagic-gcs@v0.1.7 \
--with github.com/mholt/caddy-ratelimit@16aecbbcb8ca07dc1c671e263379606ff9493c55 \
--replace golang.org/x/net=golang.org/x/net@v0.58.0 \
--replace golang.org/x/text=golang.org/x/text@v0.41.0 \
--replace google.golang.org/grpc=google.golang.org/grpc@v1.82.1 \
&& caddy version | grep -qF "${CADDY_VERSION} " \
&& caddy list-modules | grep -qE '^http\.handlers\.rate_limit$' \
&& caddy list-modules | grep -qE '^caddy\.storage\.gcs$'
Expand All @@ -93,7 +111,7 @@ RUN --mount=type=cache,target=/go/pkg/mod,sharing=locked \
# falls back to local-filesystem cert storage, so a multi-replica parent
# stack gets per-pod ACME state and risks Let's Encrypt rate-limit lockout.

FROM caddy:2.11.4@sha256:844f60b64e4724a5aa8245e019dace0d3f199f7433ce6c57676cb30a920dbad9
FROM caddy:2.11.4@sha256:df7f1c2fb114453b951de51a98efc010db1655a92c2e86be6706714e2417a78d

RUN apk update && apk upgrade --no-cache && rm -rf /var/cache/apk/*

Expand Down
16 changes: 16 additions & 0 deletions cloud-helpers.aws.Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,22 @@ RUN dnf upgrade -y --setopt=tsflags=nodocs \
&& dnf clean all \
&& rm -rf /var/cache/dnf

# Drop the Runtime Interface Emulator. It is the base image's LOCAL-testing
# shim: /lambda-entrypoint.sh execs it only when AWS_LAMBDA_RUNTIME_API is
# unset, and the ENTRYPOINT below replaces that script with /cloud-helpers
# outright — so the RIE binary is never executed in this image, in Lambda or
# anywhere else. It is also 9 MB of Go built by AWS with an older toolchain,
# which is where every stdlib finding in this image came from (8 HIGH at the
# al2023 digest pinned above, all fixed in Go >= 1.26.6; the currently-tagged
# al2023 digest carries 30). Deleting it is the fix, not a suppression: nothing
# links it and no workflow invokes it.
#
# Local debugging is unaffected — `welder run debug-aws-cloud-helpers` runs on
# the HOST and uses the host's own `aws-lambda-rie` (welder.yaml), not this
# image's copy. What this does remove is `docker run --entrypoint
# /lambda-entrypoint.sh <image> /cloud-helpers`; use the welder task instead.
RUN rm -f /usr/local/bin/aws-lambda-rie && test ! -e /usr/local/bin/aws-lambda-rie

WORKDIR /
COPY dist/cloud-helpers /cloud-helpers
# actions/upload-artifact does not preserve the executable bit, and the release
Expand Down
41 changes: 25 additions & 16 deletions docs/TESTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,21 @@ new tests for every code change.

## Current state — to be updated each pass

| Metric | Value as of 2026-05-19 |
| Metric | Value as of 2026-08-21 |
|---|---|
| Total test files | 87 (`*_test.go`) |
| Test files using **gomega** | 67 (77 %) |
| Test files using **testify** | 3 (3 %; mock-only) |
| Test files using **plain `testing`** | 19 (22 %; mostly fuzz + small utilities) |
| Table-driven tests | 43 files |
| Sub-tests via `t.Run` | 66 files |
| Integration tests (`*_integration_test.go`) | 5 packages |
| Mocks generated by `mockery v2.53.4` | `pkg/api/git/mocks/`, `pkg/clouds/pulumi/mocks/` |
| **Overall statement coverage** | **~16 %** |
| Coverage on `pkg/security/...` | 42 – 66 % per sub-pkg |

These numbers are the baseline. Every PR should hold or improve them.
| Total test files | 197 (`*_test.go`) |
| Test files using **gomega** | 166 (84 %) |
| Test files using **testify** | 12 (6 %; mock-only) |
| Sub-tests via `t.Run` | 145 files |
| Mocks generated by `mockery v2.53.6` | `pkg/api/git/mocks/`, `pkg/clouds/pulumi/mocks/` |
| **Included-set statement coverage** (Gold-tier denominator) | **90.5 %** |
| Full-set statement coverage (whole repo, unfiltered) | 29.0 % |
| Coverage on `pkg/security/...` | 79.6 – 97.8 % per sub-pkg |

These numbers are the baseline. Every PR should hold or improve them. The two
coverage figures and the scope that separates them are defined under
[Coverage scope](#coverage-scope) below; the included-set figure is the one the
OpenSSF criterion is judged on.

## Test framework — choose gomega

Expand Down Expand Up @@ -339,9 +340,17 @@ this table:
Everything not excluded above — the unit-testable core: `pkg/api/*`,
`pkg/util`, `pkg/security/*`,
`pkg/clouds/{github,aws,k8s,gcloud,compose,fs,telegram,slack,discord,…}`,
`pkg/template`, and the rest. This is roughly **5,760 statements** and is
`pkg/template`, and the rest. This is roughly **5,975 statements** and is
the denominator the Gold-tier criterion is judged on.

`pkg/security/tools/cosigntest` is deliberately NOT excluded even though it is
a test harness. Go attributes coverage per test binary, so a helper package
consumed only by *other* packages' tests reads as 0 % — which is a real gap,
not a measurement artifact: the harness generates a `/bin/sh` script whose
quoting, invocation counter and stream selection three retry suites silently
depend on. It has its own tests (`cosigntest_test.go`) instead of an
exclusion.

The `coverage` task emits two numbers on every run:

- **included-set** aggregate → `dist/cover.out` (the Gold-tier figure)
Expand All @@ -353,8 +362,8 @@ The `coverage` task emits two numbers on every run:
| Target | Threshold | Status |
|---|---|---|
| **Per-PR no-regression** | Included-set aggregate must not decrease vs `main` | Observed by `.github/workflows/coverage.yml` (sticky PR comment); hard gate deferred until the baseline stabilises |
| **Silver badge** (`test_statement_coverage80`) | ≥ 80 % included-set aggregate | Met |
| **Gold badge** (`test_statement_coverage90`) | ≥ 90 % included-set aggregate | Met |
| **Silver badge** (`test_statement_coverage80`) | ≥ 80 % included-set aggregate | Met (90.5 %) |
| **Gold badge** (`test_statement_coverage90`) | ≥ 90 % included-set aggregate | Met (90.5 %, from 89.6 % on 2026-08-21) |

Both numbers are reported by `welder run coverage` and by the coverage
workflow; the included-set aggregate is the one the OpenSSF criterion is
Expand Down
37 changes: 27 additions & 10 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,11 @@ require (
go.mongodb.org/mongo-driver v1.17.9
go.uber.org/atomic v1.11.0
gocloud.dev v0.46.0
golang.org/x/crypto v0.54.0
golang.org/x/crypto v0.55.0
golang.org/x/oauth2 v0.36.0
golang.org/x/sync v0.22.0
golang.org/x/term v0.45.0
golang.org/x/text v0.40.0
golang.org/x/text v0.41.0
google.golang.org/api v0.284.0
gopkg.in/yaml.v2 v2.4.0
gopkg.in/yaml.v3 v3.0.1
Expand Down Expand Up @@ -165,7 +165,7 @@ require (
github.com/chavacava/garif v0.1.0 // indirect
github.com/cheggaaa/pb v1.0.29 // indirect
github.com/chigopher/pathlib v0.19.1 // indirect
github.com/cilium/ebpf v0.11.0 // indirect
github.com/cilium/ebpf v0.22.0 // indirect
github.com/ckaznocha/intrange v0.3.0 // indirect
github.com/clipperhouse/displaywidth v0.11.0 // indirect
github.com/clipperhouse/uax29/v2 v2.7.0 // indirect
Expand Down Expand Up @@ -393,7 +393,7 @@ require (
github.com/segmentio/asm v1.1.3 // indirect
github.com/segmentio/encoding v0.3.5 // indirect
github.com/sergi/go-diff v1.4.0 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/sirupsen/logrus v1.9.4 // indirect
github.com/sivchari/containedctx v1.0.3 // indirect
github.com/sivchari/tenv v1.12.1 // indirect
github.com/skeema/knownhosts v1.3.1 // indirect
Expand Down Expand Up @@ -463,13 +463,13 @@ require (
gocloud.dev/secrets/hashivault v0.46.0 // indirect
golang.org/x/arch v0.11.0 // indirect
golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f // indirect
golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac // indirect
golang.org/x/mod v0.38.0 // indirect
golang.org/x/net v0.57.0 // indirect
golang.org/x/exp/typeparams v0.0.0-20260209203927-2842357ff358 // indirect
golang.org/x/mod v0.40.0 // indirect
golang.org/x/net v0.58.0 // indirect
golang.org/x/sys v0.47.0 // indirect
golang.org/x/telemetry v0.0.0-20260708182218-49f421fb7959 // indirect
golang.org/x/telemetry v0.0.0-20260811182544-a038080d80e5 // indirect
golang.org/x/time v0.15.0 // indirect
golang.org/x/tools v0.48.0 // indirect
golang.org/x/tools v0.49.0 // indirect
golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect
google.golang.org/genproto v0.0.0-20260319201613-d00831a3d3e7 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa // indirect
Expand All @@ -480,7 +480,7 @@ require (
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
honnef.co/go/tools v0.6.1 // indirect
honnef.co/go/tools v0.7.0 // indirect
k8s.io/api v0.36.1 // indirect
k8s.io/klog/v2 v2.140.0 // indirect
k8s.io/kube-openapi v0.0.0-20260317180543-43fb72c5454a // indirect
Expand All @@ -492,3 +492,20 @@ require (
sigs.k8s.io/structured-merge-diff/v6 v6.3.2 // indirect
sigs.k8s.io/yaml v1.6.0 // indirect
)

// honnef.co/go/tools is staticcheck, imported ONLY by
// github.com/golangci/golangci-lint (the `unused` linter). golangci-lint
// v1.64.8 requires v0.6.1 and does not compile against v0.7.0's analysis API:
// it panics mid-run with "typedness: panic during analysis: interface
// conversion: interface {} is nil, not *buildir.IR" and exits 7, which fails
// the `golangci-lint run` step in branch.yaml / push.yaml.
//
// MVS raises it to v0.7.0 because github.com/cilium/ebpf v0.22.0 names that
// version in its own go.mod — ebpf needs staticcheck for ITS CI, not for any
// code we compile, and v0.22.0 is the fix for GO-2026-6238 so it cannot be
// held back. A `require` line loses to ebpf's; only `replace` pins it.
//
// Remove this when golangci-lint moves to v2 (v2.x builds against honnef
// v0.7.x) — that is a separate migration: v2 renames the module path and
// changes the .golangci.yml schema.
replace honnef.co/go/tools => honnef.co/go/tools v0.6.1
Loading
Loading