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]>
This commit is contained in:
Lucas Winther
2026-09-16 03:58:01 +02:00
co-authored by Claude Opus 5
parent ff0a518001
commit 9b9e39e67f
4 changed files with 103 additions and 0 deletions
+25
View File
@@ -0,0 +1,25 @@
---
# The strictest profile, held from the first commit. It is much cheaper than
# adopting it later.
profile: production
exclude_paths:
- .git/
- .idea/
# Stack payloads are data — third-party compose and config files copied to the
# host verbatim. They are not Ansible content and must not be linted as if
# they were. See server/README.md.
- server/
skip_list:
# The production profile wants role variables prefixed with the role name
# (compose_stack_name, compose_stack_networks, ...). compose_stack is internal
# to this repository and is never published to Galaxy, and the shorter stack_*
# names are what playbooks read as. Documented as a contract in AGENTS.md.
- var-naming[no-role-prefix]
kinds:
- playbook: ansible/playbooks/*.yml
- vars: ansible/inventory/group_vars/*.yml
- vars: ansible/inventory/host_vars/*.yml
- requirements: ansible/requirements.yml
+20
View File
@@ -0,0 +1,20 @@
# gitleaks configuration. Run in CI by the lint workflow of whichever platform is
# in use (.github/workflows/lint.yml, .gitea/workflows/lint.yml, or the lint job
# in .gitlab-ci.yml) over the working tree *and* the history — a secret that was
# committed and then deleted is still a leaked secret, and the only fix is
# rotating it.
title: "config repository secret scan"
[extend]
# Start from the upstream rule set rather than reinventing it.
useDefault = true
[allowlist]
description = "Documentation and examples"
paths = [
# Every value here is a placeholder or an empty assignment. The real thing
# lives in a .env on the host, which this repository never contains.
'''.*\.env\.example$''',
# Documentation quotes variable names and shows the shape of a key.
'''^docs/secrets\.md$''',
]
+36
View File
@@ -0,0 +1,36 @@
---
extends: default
ignore: |
.git/
.idea/
server/
rules:
# Ansible convention: every file opens with ---
document-start:
present: true
line-length:
max: 120
allow-non-breakable-words: true
indentation:
spaces: 2
indent-sequences: true
comments:
min-spaces-from-content: 1
# Both required by ansible-lint's embedded yamllint; it refuses to use a
# custom config that disagrees, and disables fix mode.
comments-indentation: false
braces:
max-spaces-inside: 1
# File modes must be quoted strings ("0755"), never bare octal. An unquoted
# 0644 is the integer 420 in YAML, and Ansible applies it as such.
octal-values:
forbid-implicit-octal: true
forbid-explicit-octal: true
truthy:
allowed-values: ["true", "false"]
# GitHub Actions workflows are keyed on `on:`, which YAML 1.1 reads as the
# boolean true. Without this every workflow file fails the truthy rule on a
# key it is not allowed to spell any other way.
check-keys: false
+22
View File
@@ -0,0 +1,22 @@
# Thin wrapper over scripts/, so that `make check` and CI run byte-identical
# commands. See CONTRIBUTING.md.
.PHONY: help check install lint syntax
help:
@echo "make check - the full static gate (what CI runs)"
@echo "make install - install the Galaxy collections"
@echo "make lint - yamllint + ansible-lint only"
@echo "make syntax - syntax-check every playbook only"
check:
scripts/check.sh
install:
cd ansible && ansible-galaxy install -r requirements.yml
lint:
yamllint .
cd ansible && ansible-lint .
syntax:
cd ansible && for p in playbooks/*.yml; do ansible-playbook --syntax-check "$$p"; done