Repository navigation
chore(ci): make local gates fail honestly and pin pre-commit hook repos (#349, slice 1) - #1307
Conversation
First slice of the 2026-07-28 review findings for this repo: - Makefile: lint, security-scan-docker and security-scan-snyk fail when the tool is missing and stop on the tool's own exit status instead of a trailing echo; drop the retired tfsec target; terraform-validate validates the flat terraform/environments/<cloud> roots instead of a nonexistent */dev glob. scripts/test-make-gates.sh covers all of this with stub tools and runs in the lint job. - Makefile.terraform: clean-locks needs CONFIRM_CLEAN_LOCKS=yes. - database-migration.yml: stop writing migrate's stderr into GITHUB_ENV. - .pre-commit-config.yaml: pin the three third-party hook repos to commit SHAs and let check-yaml see workflow files. - .golangci.yml: gocyclo min-complexity 10, matching the CI gate. - ci.yml: tfvars fmt checks no longer swallow a non-zero exit. - .env.example: no working admin password or API key. - .dockerignore: exclude the test compose/Dockerfile pair. - .trivyignore/.snyk: correct the AVD-AWS-0013 and GCP-0015 reasons and drop .snyk keys the Snyk CLI never reads. Refs LeanerCloud#349 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Deleting it breaks LeanerCloud#1222's gitignore test, which expects the Makefile to still write tfsec-report.json. The target now fails honestly like the others; removing it can follow once LeanerCloud#1222 merges. Refs LeanerCloud#349 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: true
Comment |
Brings in main's CI fixes (LeanerCloud#1236, LeanerCloud#1252) and CI changes since, so this PR gets a fresh CI run. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Independent review (IAmJSD's agent, fresh context, given only the diff, the issue and the PR text): VERDICT: APPROVE Blocking:
Non-blocking:
Attacked:
Body-stale:
Reviewer: rB6. Bar while the maintainers are away (set by IAmJSD as acting owner): one approving independent review on the head, two for money, auth and security paths. |
|
Local verification at |
|
Merged by IAmJSD's agent at IAmJSD's request (IAmJSD is acting owner while the maintainers are away), under the bar IAmJSD set: 1 approving independent review(s) on |
Brings the branch up to date with main (f316add). Conflicted files: - .github/workflows/ci.yml: main added the gcp-import-dev-state (LeanerCloud#1119) and gitignore-make-artifacts (LeanerCloud#1222) shell-only jobs in the same spot where this branch adds tf-deploy-wrapper. Kept all three jobs, with tf-deploy-wrapper after main's two, and listed all three in ci-success's needs alongside main's new vpc-peering-delete-scope, tfstate-concurrency-group and rollback-ecr-registry entries. Makefile.terraform merged cleanly: main's clean-locks confirmation (LeanerCloud#1307) and this branch's frontend-only change touch different targets. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
First slice of #349, the medium/low findings from the 2026-07-28 review (platform part). I re-checked every finding against current main (
a14dc8f2). This PR fixes the ones that can be verified locally and don't collide with other open branches. The table below covers all of them.Refs #349
Root cause and fix
Several local gates reported success no matter what happened. Each Makefile scanner target ended its
thenbranch with a successechoand printed a hint instead of failing when the tool was missing.terraform-validatelooped over aterraform/environments/*/devglob that matches nothing. A few config files also kept settings that nothing reads or that undercut the gate next to them.lint,security-scan-dockerandsecurity-scan-snyknow fail when their tool is missing, and the tool runs as its own recipe line so make stops on its exit status.security-scanno longer runs the deprecated tfsec target (CI replaced tfsec with Trivy). Thesecurity-scan-terraformtarget is kept, with the same honest shape, because chore(gitignore): ignore root artifacts written by Make targets #1222's gitignore test expects the Makefile to still writetfsec-report.json. It can be deleted once chore(gitignore): ignore root artifacts written by Make targets #1222 merges.terraform-validatenow runsinit -backend=false+validatein each flatterraform/environments/<cloud>root (the same roots CI validates) and fails if it finds none.security-scan-dockernow uses--scanners vuln,misconfiginstead of the deprecated--security-checks vuln,config. It still reports Trivy findings without failing on them, the same as CI's Trivy fs step (see the deferred items).clean-locksrefuses to run withoutCONFIRM_CLEAN_LOCKS=yesand warns that the regenerated lock files must be reviewed as a supply-chain change.scripts/test-make-gates.sh(new, 28 cases) runs all of the above against stub tools on a PATH that contains nothing else. It runs as a step in ci.yml's existinglintjob, soci-success'sneeds:list is unchanged.MIGRATION_VERSIONto$GITHUB_ENV. Nothing read the value. migrate prints its version on stderr, so the2>&1capture stays for the log line, but on failure that same capture holds a multi-line error. Written to$GITHUB_ENV, an error line shaped likeNAME=valuewould have set that variable for every later step.# frozen: <tag>), each confirmed through the GitHub API as the commit its tag points at.check-yamlno longer excludes.github/workflows/.min-complexity: 10, the same threshold as the standalonegocyclo -over 10gates.terraform fmt -checkcalls no longer end in|| echo "Note: ...".ADMIN_PASSWORD_DEVandADMIN_API_KEY_DEVare now empty.EnvResolver.GetSecretrejects an empty value, so a copy that skips them fails at startup instead of booting with published credentials.docker-compose.test.ymlandDockerfile.test.docker build -fstill uses an excluded Dockerfile, the same wayDockerfile.devalready works.TLSv1is set explicitly, and the finding is unexploitable only becauseenable_cdndefaults to false and every shipped tfvars sets it false. The GCP-0015 reason is corrected: there is norequire_sslvariable, and both blocks hardcodessl_mode = "ENCRYPTED_ONLY"..snykdropsfailOnSeverityandlicense, which the Snyk CLI never reads, with a comment saying where the threshold actually lives.Per-finding status (re-verified on main
a14dc8f2)--skip-dirs terraform/environments/aws, CI Trivy IaC exit-code 0)exit-code: 1leaves main green. The pre-commit job also installs Trivy v0.69.3, which panics on that directory (fixed in v0.72.0, which ci.yml already pins), so the fix also needs a pre-commit.yml Trivy bump. #1227 edits pre-commit.yml (different lines). Next slice.security-scan-gowas already fixed by #340 (scripts/run-gosec.sh).make ci/make terraform-validatebroken (*/devglob)continue-on-errorand outsideci-successsnyk-scanis skipped on fork PRs (if: ... head.repo.full_name == github.repository), andci-successnow accepts onlysuccess, so adding it toneeds:as is would turn every fork PR red. The fix also editsci-success'sneeds:block, which #1222, #1119 and fork branchfix/issue-59all append to.exit-code: 1on Trivy fs would turn main red whenever a new upstream CVE is published, and I couldn't measure what it reports today. Whether the coverage line is a gate is the owner's call.docker-buildsmoke test rebuilds and uses|| true039698da): the image is built once withload: true, and the architecture/execution check uses no|| true.Get migration versionwrites command output to$GITHUB_ENVf1aceec9moved rollback.yml to 1.10.5, and database-migration.yml is 1.10.5 too. Still reproduces: deploy-aws-lambda, deploy-aws-fargate, deploy-azure, deploy-gcp, cleanup-staging and destroy-fargate-dev pinTF_VERSION: '1.10.0', while ci.yml and pre-commit.yml pin 1.10.5. None of the open branches touch those lines. Next slice (bump to 1.10.5 plus a pin-consistency check)..env.exampleships a working admin password/API keydocker-compose.ymlstill carries the same two values inline for the local dev stack. That file isn't in the finding, so I left it alone.deploy-all.ymlignores cancelled childrenbb2d2312): it now allowlists on success, andcancelledfails the run..dockerignoreomits the test pairclean-lockswithout confirmationcheck-yamlexcludes workflows; no actionlinta43a575b, local hook plus theworkflow-lintjob). This PR removes the exclusion..golangci.ymlgocyclo 15 vs 10.golangci.ymlonly). The Makefilecomplexityhalf is A14-037, below.TLSv1branch) is tracked separately, as the issue says.scripts/tf-deploy.shbuilds a nonexistent per-profile rootfix/issue-59rewiresMakefile.terraformthroughtf-deploy.shand addsscripts/test-tf-deploy.shfor it. Changing the script's directory logic now would collide with that work..snykinert keys.snyk). The GCP-0015 entry itself is kept until a Trivy run without it is shown to be clean.nginx:alpine/dpage/pgadmin4:9.2not digest-pinnedcomplexitylacks-ignore "_test\.go";2>&1 || truefix/issue-177rewrites that same Makefile line (and the ci.yml gocyclo line).fmt -check ... || echocan't failterraform fmt -check -recursive terraform/) already fails on a broken tfvars file (exit 2) or an unformatted one (exit 3), both checked locally. The soft-fail was misleading, though, and is gone.Branch overlap check
Every
.github/workflows/ci.yml, pre-commit and Makefile hunk in #1222, #1227, #1119 and #1142, in fork branchesfix/issue-1233,-353,-177and-59, and in every other open PR touching CI files (#1086, #1090, #1106, #1112, #1114, #1144, #1147, #1149, #1193, #1203, #1207, #1213, #1221, #1228, #1236) was read.git merge-tree --write-treeagainst each of those heads is clean. On the combined trees, the sibling self-tests that read the files touched here pass: #1222'stest-gitignore-make-artifacts.sh(15/15, after keeping the tfsec target, see above), #1227'scheck-gosec-pin.shandtest-check-gosec-pin.sh(43/43), andfix/issue-59'stest-tf-deploy.sh(14/14).test-make-gates.shpasses on each combined tree too.Verification
All of this is local, stub- or fixture-based evidence. Nothing calls a cloud API, and no workflow was triggered.
bash scripts/test-make-gates.sh: 28 passed, 0 failed on this branch. The same script run against origin/main'sMakefile/Makefile.terraform(viagit archive origin/main; the run predates the tfsec-target case, so it had 24 cases) gave 11 passed, 13 failed: lint/trivy/snyk passed with the tool missing, trivy/snyk passed when the tool failed, security-scan ran tfsec, terraform-validate failed with exit 2 on the*/devglob and never called terraform, and clean-locks deleted the lock file without confirmation.make terraform-validate(actualterraform init -backend=false+validate, providers from the public registry, no backend, no credentials;TF_DATA_DIRin a temp dir):Success! The configuration is valid.for aws, azure and gcp, exit 0. Side effect:initadds platformh1:hashes to the committed.terraform.lock.hclfiles (I reverted them). The committed locks also record staleconstraints(for examplehttp~> 3.0while the code says~> 3.4). That's out of scope, noted below.$GITHUB_ENVinjection: I extracted the "Get migration version"run:block from both revisions and ran it with a stubmigratethat writes a two-line error to stderr and exits 1. On main,$GITHUB_ENVended up containingMIGRATION_VERSION=error: ..., thenINJECTED_VAR=attacker-value, thenunknown. On this branch it stays empty. migrate printing its version on stderr was confirmed in golang-migrate'sinternal/cli(versionCmd→log.Println→os.Stderr)..github/workflows/(temporary, deleted after).pre-commit run check-yaml --files <fixture>printed(no files to check)Skippedwith main's config and failed with a YAML parse error with this branch's.pre-commit run check-yaml --all-filespasses on the branch, so every existing workflow parses.gocyclo -over 10reports it) gave0 issueswith main's.golangci.ymland1 issues: gocyclowith this branch's.golangci-lint run --enable-only gocyclo --build-tags integration ./...gives0 issueson the whole repo (tests/e2ewith--build-tags e2etoo), andgocyclo -over 10 -ignore "_test\.go|node_modules" .reports nothing.golangci-lint config verifyagainst the vendored v2.10 schema passes.docker build -f Dockerfile.test .with the new.dockerignore: exit 0.git ls-remoteplusgh api repos/<repo>/commits/<sha>for each (chore(release): version 1.105.0,v6.0.0,Bump version 0.47.0).actionlint .github/workflows/ci.yml .github/workflows/database-migration.yml(v1.7.12): clean.shellcheck scripts/test-make-gates.sh(0.11.0): clean. zizmor isn't installed here, so it didn't run.git diff --check: clean.go build ./...,go vet ./...,go vet -tags integration ./...: pass. No Go files changed.Combined-tree verification. This branch was tested together with the other queued branches on a local, never-pushed tree:
queue/platform@b56afb2b= origin/maina14dc8f2plus these heads, merged in this order:fix/issue-324andfix/issue-204both edit.github/workflows/ci.ymlnext to theazure-kv-access-policyjob. The tree kept #324's new "Run Function URL reader self-tests" step and #204's updated job comment; whichever PR merges second takes that same resolution.Linux, Go 1.26.9,
AWS_CONFIG_FILE=/dev/null AWS_SHARED_CREDENTIALS_FILE=/dev/null AWS_EC2_METADATA_DISABLED=true; Docker Postgres via testcontainers. The full suite ran oned0c7174, which differs fromb56afb2bonly by one.gitallowedline on fix/issue-324:go build ./...,go vet ./...,go vet -tags integration ./...and the fullgo test -race -short -count=1 ./....--build-tags integration.gocyclo -over 10is silent on the changed non-test files.-tags integration -count=1, 60-minute local timeout):internal/api,internal/purchase,internal/schedulerandinternal/serverall pass..gitallowedline. Re-run atb56afb2b: git-secrets, using the repo'sscripts/setup-git-secrets.shpatterns in a fresh repo with an isolated HOME, found nothing in the changed files, and a planted fake key was flagged.scripts/test-git-secrets-allowlist.sh: 137 PASS, 0 FAIL.Out of scope / follow-ups
fix/issue-59), A14-037 (afterfix/issue-177), and deleting the deprecated tfsec target (after chore(gitignore): ignore root artifacts written by Make targets #1222).terraform/environments/*/.terraform.lock.hclfiles record providerconstraintsthat no longer match the code (for examplehttp~> 3.0vs~> 3.4), so anyterraform initrewrites them.docker-compose.ymlstill carries the dev admin password and API key inline.For the maintainer (repo-admin actions, not done here)
test-make-gates.shruns inside the existingLint Codejob, which is already inci-success. If Snyk becomes a gate (M4), either the job has to run on fork PRs (it needsSNYK_TOKEN, which forks don't get), orci-successhas to acceptskippedfor it specifically. That's a policy choice, plus a ruleset update if you want "Snyk Security Scan" to be required directly..github/workflows/**andterraform/**..github/dependabot.ymlforgithub-actions,dockerandgomod(andnpmforfrontend/if the UI owner wants it) opens PRs against this repo once merged. Your call on whether you want that PR volume and how to group updates.Could a maintainer please mirror #349's triage labels onto this PR:
impact/internal,effort/l,type/chore,triaged,priority/p3,severity/low,urgency/eventually.🤖 Generated with Claude Code