Commit Graph
10 Commits
Author SHA1 Message Date
Lucas WintherandClaude Opus 5 d2c303e346 Fix the TOML syntax in the gitleaks config
lint / yamllint + ansible-lint + syntax (push) Successful in 2m26s
lint / shellcheck (push) Successful in 8s
lint / secret scan (push) Successful in 3s
The title was written with YAML syntax, so gitleaks failed to load the
config before it reached [extend] or [allowlist]:

    FTL unable to load gitleaks config, err: While parsing config: toml:
    expected character =

Verified with the pinned binary the Gitea lint workflow uses (v8.30.1):
`gitleaks detect --source=. --config=.gitleaks.toml --redact --verbose
--no-banner` now scans the working tree and all history and reports no
leaks.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
2026-09-16 04:09:42 +02:00
Lucas WintherandClaude Opus 5 e1f152ec3e Add the documentation and the agent instructions
lint / yamllint + ansible-lint + syntax (push) Successful in 2m52s
lint / shellcheck (push) Successful in 7s
lint / secret scan (push) Failing after 3s
README for humans, AGENTS.md for agents and contributors, and the docs that
outlive any one platform: architecture, secrets, connectivity, triggering a
deploy from another repository. CLAUDE.md, GEMINI.md and .claude/skills/ are
pointers rather than copies, so every agent and every human reads the same
text.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
2026-09-16 03:58:24 +02:00
Lucas WintherandClaude Opus 5 971034e630 Add the Gitea Actions configuration
The third port of the same two things. Gitea walks WORKFLOW_DIRS and stops
at the first directory that exists, so .gitea/workflows/ replaces
.github/workflows/ outright on a Gitea instance — which is the point, since
deploy.yml there is built on repository_dispatch and an environment: and
Gitea has neither.

Four differences shape the files:

- No environment:, so no scoped secret and no required reviewers. The file
  does not write the key at all rather than claim a protection that Gitea
  parses and ignores; what gates a deploy is write access to the repository.
- No repository_dispatch. External callers post to the workflow dispatch
  API, which fills in the same form — and can return a run id, so unlike
  repository_dispatch the caller may follow the deploy it asked for.
- runs-on takes a literal label only, so GitHub's vars.DEPLOY_RUNNER
  expression becomes one documented line to edit.
- A job is itself a container with no Docker socket, so the secret scan runs
  the pinned gitleaks binary instead of the upstream image.

Input validation carries over unchanged and matters more here: type: choice
constrains the dispatch form, not the API.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
2026-09-16 03:58:18 +02:00
Lucas WintherandClaude Opus 5 1130f2f07e Add the GitLab CI configuration
The same two things as the GitHub workflows, in GitLab's shape: one lint
job, and a per-stack check/deploy button pair. Branch pipelines only, since
a bare `when: manual` would otherwise make GitLab build a merge request
pipeline that drops every job without rules — which looks exactly like the
deploy buttons having vanished.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
2026-09-16 03:58:09 +02:00
Lucas WintherandClaude Opus 5 a0e56c96b7 Add the GitHub Actions workflows
A lint gate on every push, a manual deploy form, and a connectivity
workflow for when a deploy hangs instead of failing. Nothing deploys on a
push: merging changes what would be deployed, a person still decides when.
The stack name and pull policy reach a shell command, so they are validated
through env: rather than interpolated into a run: block.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
2026-09-16 03:58:09 +02:00
Lucas WintherandClaude Opus 5 9b9e39e67f Add the lint configuration and the Makefile
ansible-lint at the production profile from the first commit, which is much
cheaper than adopting it later. yamllint forbids implicit octal so a file
mode cannot silently become an integer, and the Makefile is a thin wrapper
so `make check` and CI run byte-identical commands.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
2026-09-16 03:58:01 +02:00
Lucas WintherandClaude Opus 5 ff0a518001 Add the check and deploy-key scripts
check.sh is the full static gate and the single source of the tool version
pins, which CI reads with --print-specs so a workflow cannot drift from what
runs locally. load-ssh-key.sh is the only thing that knows where the deploy
key comes from — file, CI secret, or Vault — and prints a path, never key
material.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
2026-09-16 03:58:01 +02:00
Lucas WintherandClaude Opus 5 b76c76e3b0 Add the example stack payloads
The files copied to /srv/stacks/<stack>/ verbatim: compose files, vhosts,
Prometheus configuration, the webapp image source. Payloads are data, never
templated and never linted as Ansible content.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
2026-09-16 03:58:01 +02:00
Lucas WintherandClaude Opus 5 7b52e9af9e Add the compose_stack role, inventory and playbooks
One role that syncs a payload and brings the stack up, configured entirely
through stack_* variables, plus six playbooks that each demonstrate one part
of that contract. Every playbook runs standalone and is tagged with its
stack name, so site.yml --tags <stack> works.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
2026-09-16 03:58:01 +02:00
Lucas WintherandClaude Opus 5 7cdf9b854b Add repository scaffolding
MIT license, the ignore list that keeps secrets and Ansible scratch files
out, and a .gitattributes that normalises everything to LF — payloads are
deployed to Linux hosts, where a CRLF breaks a shell script outright.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
2026-09-16 03:57:50 +02:00