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: 11 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,17 @@ jobs:
- name: ExternalSecret keys are named once and patched per cluster
run: ./scripts/check-externalsecret-keys.py

# The catalog declares one ClusterSecretStore and eleven other places
# restate its name — eight secretStoreRefs, an ApplicationSet patch target,
# and five chart defaults in repositories this one does not own. An
# ExternalSecret naming a store that is not there installs and syncs
# cleanly and records SecretSyncedError on an object nothing in the install
# path reads; an unmatched kustomize patch target is not an error at all,
# so the region rewrite silently does not happen. This holds them to the
# declaration and publishes it for the consumers outside this repository.
- name: Every secret-store reference resolves to the declared store
run: ./scripts/check-secret-store-refs.py

# A CUR export runs an explicit column projection, so its delivered set is
# far narrower than the CUR specification and every documented column name
# looks plausible in a panel query. The dashboard gate below reads
Expand Down
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@
*secret*.json
!*secret*-store*.yaml
!*secret*-store*.yml
# The store's published contract — its name and apiVersion, for consumers in
# other repositories to assert against instead of restating. Same category as
# the two lines above: a description of where secrets are fetched from, holding
# none. JSON because that is the shape the org's other cross-repo pins take.
!*secret*-store*.json
# ExternalSecret manifests are references into the secret store, not secret
# material — they must ship with the charts that need them.
!*externalsecret*.yaml
Expand Down
3 changes: 2 additions & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ task validate:sync-waves # Assert the documented sync-wave category or
task validate:label-values # Every k8s label value satisfies the API server's grammar
task validate:policy-admission # Prove no addon is denied by the Enforce-tier Kyverno policies (+ exclusion-list parity)
task validate:externalsecret-keys # Each ExternalSecret names its remote secret once, and the delivering appset patches it
task validate:secret-store-refs # Every secret-store reference names the one store this catalog declares, and the published contract states it
task validate:dashboards # grafana.com dashboard ids exist and are AMG-saveable
task validate:athena-panel-columns # Every column a CUR panel names is one the export delivers
task validate:fork-safety # No hardcoded catalog repoURL in applied ApplicationSets (report-only locally)
Expand All @@ -112,7 +113,7 @@ task validate:image-vulnerabilities # Every fixed CRITICAL in a rendered image i

`task validate` runs the structural gates (lint, kustomize build, helm-render,
ApplicationSet schema, sync-wave ordering, appset render, policy-admission,
dashboards, fork-safety). CI runs those plus several gates that have **no local
secret-store references, dashboards, fork-safety). CI runs those plus several gates that have **no local
`task` target**, and one that has a target but is deliberately outside the
aggregate, so a clean `task validate` is necessary but not sufficient:

Expand Down
8 changes: 7 additions & 1 deletion Taskfile.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -195,13 +195,18 @@ tasks:
cmds:
- ./scripts/check-externalsecret-keys.py

validate:secret-store-refs:
desc: "Secret-store gate — every reference names the one store this catalog declares, and the published contract states it"
cmds:
- ./scripts/check-secret-store-refs.py

validate:athena-panel-columns:
desc: "Athena panel gate — every column a CUR panel names is one the export delivers"
cmds:
- ./scripts/check-athena-panel-columns.py

validate:
desc: Run all validations (lint, build, helm-render, appset schema, sync waves, label values, appset render, policy admission, externalsecret keys, athena panel columns, dashboard/fork-safety)
desc: Run all validations (lint, build, helm-render, appset schema, sync waves, label values, appset render, policy admission, secret refs, athena panels, dashboard/fork-safety)
deps:
- lint:yaml
- lint:python
Expand All @@ -213,6 +218,7 @@ tasks:
- validate:appset-render
- validate:policy-admission
- validate:externalsecret-keys
- validate:secret-store-refs
- validate:athena-panel-columns
- validate:dashboards
- validate:fork-safety
Expand Down
12 changes: 12 additions & 0 deletions contracts/secret-store.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"_generated": "scripts/check-secret-store-refs.py --write; the source of truth is the manifest under addons/bootstrap/secret-stores/. Edit that, then regenerate.",
"_purpose": "Consumers outside this repository assert their chart defaults against these values instead of restating them.",
"clusterSecretStore": {
"apiVersion": "external-secrets.io/v1",
"kind": "ClusterSecretStore",
"name": "aws-secrets-manager"
},
"externalSecret": {
"apiVersion": "external-secrets.io/v1"
}
}
Loading