ci: add CI workflows and pre-commit hooks - #2
Conversation
Introduce a two-layer quality gate for the DevOps monorepo, which had no CI and no pre-commit config. Local (.pre-commit-config.yaml): hygiene, shellcheck, yamllint (reusing ansible/.yamllint), and markdownlint. ansible-lint is an opt-in manual hook. CI (.github/workflows/): - ci.yml: path-filtered pre-commit, ansible-lint + playbook syntax-check, KICS Ansible security scan, and actionlint. - molecule.yml: blocking containerised converge/verify on ansible/** changes. Supply-chain hardening: - Third-party actions pinned to full commit SHAs (version-commented); Dependabot bumps them weekly (.github/dependabot.yml). - KICS uses the official Checkmarx/kics-github-action pinned to its post-remediation hardened HEAD (the March 2026 TeamPCP hijack was remediated; the v2.1.20 tag predates the April base-image hardening, so Dependabot is told not to bump it). Supporting files: root Makefile (hooks/lint/security/molecule), CONTRIBUTING.md, .shellcheckrc, .markdownlint-cli2.yaml, and a kics-results/ gitignore entry. Make the existing anvil-devnet bash scripts shellcheck-clean (proper source and library directives) so the new shellcheck gate passes. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Code Review
This pull request introduces local development hygiene and CI configurations, including pre-commit hooks, a markdownlint configuration, a repository-wide ShellCheck configuration, a central Makefile, and a CONTRIBUTING guide detailing supply-chain pinning rules. Feedback on these changes suggests running the KICS Docker container in the Makefile with the host user's UID/GID to avoid permission issues with generated files on Linux, and explicitly exporting the required variable in lib.sh instead of globally toggling set -a.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
There was a problem hiding this comment.
Pull request overview
Introduces baseline contributor hygiene and automated quality gates for this DevOps monorepo by adding pre-commit configuration, GitHub Actions CI workflows, and supporting documentation/Make targets to run linting, Ansible validation, Molecule testing, and KICS security scanning.
Changes:
- Add local pre-commit hooks for formatting/linting (shellcheck, yamllint for
ansible/, markdownlint, and general hygiene). - Add GitHub Actions workflows for a path-filtered CI pipeline (
pre-commit, Ansible lint + syntax-check, KICS scan, actionlint) plus a separate Molecule workflow gated onansible/**changes. - Add supporting repo docs/config (Makefile targets, contributing guide, lint configs, dependabot, and KICS results ignore).
Reviewed changes
Copilot reviewed 8 out of 11 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| services/anvil-devnet/bin/lib.sh | Adjusts shellcheck-related directives and env sourcing to be lint-clean under the new gates. |
| services/anvil-devnet/bin/install.sh | Adds a targeted shellcheck suppression to keep the script clean under CI/pre-commit. |
| Makefile | Adds convenience targets to run hooks/lint/ansible lint/KICS/molecule from repo root. |
| CONTRIBUTING.md | Documents the new local + CI quality gates and supply-chain pinning approach. |
| .shellcheckrc | Establishes repo-wide shellcheck configuration suitable for the ops script layout. |
| .pre-commit-config.yaml | Defines local pre-commit hooks and scopes YAML linting to ansible/. |
| .markdownlint-cli2.yaml | Configures a relaxed markdownlint ruleset to fit existing docs while catching structural issues. |
| .gitignore | Ignores generated KICS output directory. |
| .github/workflows/molecule.yml | Adds an ansible/**-scoped Molecule workflow to run converge/verify in CI. |
| .github/workflows/ci.yml | Adds path-filtered CI jobs for pre-commit, Ansible lint/syntax-check, KICS, and actionlint with SHA-pinned actions. |
| .github/dependabot.yml | Adds Dependabot config to keep SHA-pinned GitHub Actions dependencies updated (with an explicit ignore for KICS action pin). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- ci.yml: drop stale "secrets" from the pre-commit job comment (no secret-scanning hook is configured). - lib.sh: export ANVIL_MNEMONIC explicitly instead of toggling `set -a` globally around the source (avoids exporting unintended vars). - Makefile: run the local KICS container as the host UID/GID so kics-results/ files aren't root-owned on rootful Docker. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* feat(anvil): expose devnet RPC over public HTTPS via Caddy The anvil devnet was unreachable off-host: rpc-dev.decdn.org A-records straight to the droplet, but nftables default-deny opened no HTTP hole (Caddy bound 127.0.0.1:8080) and the documented Cloudflare tunnel was never stood up. A firewall change alone is a no-op since Caddy is loopback-bound, so this moves Caddy's listener public too. - Add caddy_public toggle (default true): Caddy serves rpc_hostname on 443 with auto-TLS (Let's Encrypt) + per-dev basic auth, reverse-proxying to the loopback anvil. Set false for the old loopback plain-HTTP mode (dev/CI or behind a tunnel). - Open tcp/80+443 for the anvil_devnet group via baseline_extra_inbound (new inventory/group_vars/anvil_devnet.yml), the same idiom decdn_nodes uses for udp/4433. 80 carries ACME HTTP-01 + the http->https redirect. - Pin molecule to caddy_public: false so CI keeps asserting the loopback bind and avoids a doomed public-ACME attempt in-container. - anvil itself stays loopback; only the auth-terminating Caddy proxy faces the internet. Update hard-rule #2, README, and CLAUDE.md accordingly. Verified: ansible-lint (production), molecule (converge/idempotence/verify), KICS (0 high/critical), galaxy build/check, and `make check-anvil` dry-run (shows the exact nftables + Caddyfile diffs). Live deploy intentionally deferred to an operator. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(caddy): guard caddy_acme_email with default('') in Caddyfile `caddy_acme_email | length > 0` errors under StrictUndefined or when the var is set to null/None in group_vars. `| default('')` absorbs both and relies on empty-string falsiness — verified across empty/None/set/undefined. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
What
Adds a two-layer quality gate to the DevOps monorepo, which previously had no CI and no pre-commit config.
Local —
.pre-commit-config.yamlHygiene,
shellcheck,yamllint(reusesansible/.yamllint), andmarkdownlint.ansible-lintis an opt-inmanualhook (it needs Galaxy collections installed). Install withmake hooks.CI —
.github/workflows/ci.yml— a path-filtered pipeline:pre-commit,ansible-lint+ playbook--syntax-check, KICS Ansible security scan, andactionlint. Bash-only PRs skip the Ansible jobs.molecule.yml— blocking containerised converge/verify, scoped toansible/**changes.Supporting files
Root
Makefile(hooks/lint/lint-ansible/security/molecule),CONTRIBUTING.md,.shellcheckrc,.markdownlint-cli2.yaml,.github/dependabot.yml, and akics-results/gitignore entry.Supply-chain hardening
Checkmarx/kics-github-action, pinned to its post-remediation hardened HEAD by SHA. The March 2026 TeamPCP tag-hijack (CISA KEV) has been remediated; thev2.1.20tag predates the April base-image digest-pinning, so Dependabot is told not to bump it..gitignore+ templates only); enable GitHub push protection if desired.Note on the bash changes
services/anvil-devnet/bin/{lib.sh,install.sh}were made genuinelyshellcheck-clean (propersource/library directives) so the new shellcheck gate passes on day one — they were not clean before.Verified locally
pre-commit run --all-files(13 hooks),actionlint,ansible-lint+ syntax-check, and KICS (0 HIGH → exit 0) all pass.Follow-up (manual GitHub settings, not in this PR)
Mark the
ci.ymljobs andmoleculeas required status checks in branch protection once proven.🤖 Generated with Claude Code