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]>
84 lines
3.4 KiB
Bash
Executable File
84 lines
3.4 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
#
|
|
# The full static gate: yamllint, ansible-lint, and a syntax check of every
|
|
# playbook. This is the definition of "done" for a change to this repository.
|
|
#
|
|
# scripts/check.sh # or: make check
|
|
#
|
|
# CI runs this same script, so a green run here means a green pipeline. Keep it
|
|
# that way: a check that only exists in a workflow file cannot be run before
|
|
# pushing, and one that only exists here does not gate anything.
|
|
set -euo pipefail
|
|
|
|
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
cd "$repo_root"
|
|
|
|
# Version specifications, single-sourced here and read by both CI configurations.
|
|
#
|
|
# Pinned to a minor series so that a deploy does not change because PyPI did, and
|
|
# a lint result does not depend on the morning it ran, while patch releases still
|
|
# arrive. Verified against ansible-core 2.21.2, ansible-lint 26.6.0 and yamllint
|
|
# 1.38.0. Raise a ceiling deliberately, after running this script -- not to chase
|
|
# a release. The Galaxy collections are floored separately in
|
|
# ansible/requirements.yml.
|
|
ANSIBLE_CORE_SPEC="${ANSIBLE_CORE_SPEC:-ansible-core>=2.21,<2.22}"
|
|
ANSIBLE_LINT_SPEC="${ANSIBLE_LINT_SPEC:-ansible-lint>=26.6,<27}"
|
|
YAMLLINT_SPEC="${YAMLLINT_SPEC:-yamllint>=1.38,<2}"
|
|
export ANSIBLE_CORE_SPEC ANSIBLE_LINT_SPEC YAMLLINT_SPEC
|
|
|
|
# CI installs the toolchain itself and then re-enters this script with
|
|
# RUNNER=installed. It asks for the pins here so that they are defined in exactly
|
|
# one place and a workflow can never drift from what runs locally.
|
|
if [ "${1:-}" = "--print-specs" ]; then
|
|
printf '%s\n%s\n%s\n' \
|
|
"$ANSIBLE_CORE_SPEC" "$ANSIBLE_LINT_SPEC" "$YAMLLINT_SPEC"
|
|
exit 0
|
|
fi
|
|
|
|
# In CI the tools are already installed and on PATH. Locally, run them through
|
|
# uvx so this repository needs no virtualenv of its own. Set RUNNER=pip if you
|
|
# would rather install them yourself.
|
|
if [ "${RUNNER:-}" = "installed" ] || command -v ansible-lint >/dev/null 2>&1; then
|
|
yamllint_cmd=(yamllint)
|
|
ansible_lint_cmd=(ansible-lint)
|
|
galaxy_cmd=(ansible-galaxy)
|
|
syntax_cmd=(ansible-playbook)
|
|
elif command -v uvx >/dev/null 2>&1; then
|
|
yamllint_cmd=(uvx --from "$YAMLLINT_SPEC" yamllint)
|
|
ansible_lint_cmd=(uvx --from "$ANSIBLE_LINT_SPEC" --with "$ANSIBLE_CORE_SPEC" ansible-lint)
|
|
galaxy_cmd=(uvx --from "$ANSIBLE_CORE_SPEC" ansible-galaxy)
|
|
syntax_cmd=(uvx --from "$ANSIBLE_CORE_SPEC" ansible-playbook)
|
|
else
|
|
echo "check: need either the tools on PATH or uv installed (https://docs.astral.sh/uv/)" >&2
|
|
exit 1
|
|
fi
|
|
|
|
step() { printf '\n== %s ==\n' "$*"; }
|
|
|
|
# From the repository root, where .yamllint and its ignore list live. ansible-lint
|
|
# runs yamllint too, but only over files it recognises as Ansible content; this
|
|
# covers the workflows, the CI configuration and everything else.
|
|
step "yamllint"
|
|
"${yamllint_cmd[@]}" .
|
|
|
|
# Every ansible command runs from ansible/: ansible.cfg is only discovered in the
|
|
# current directory, and it is what puts roles/ on the roles path. From the
|
|
# repository root you get "the role 'compose_stack' was not found".
|
|
cd ansible
|
|
|
|
# Install the collections before linting, or community.docker and ansible.posix
|
|
# resolve to nothing and the fully-qualified-name checks pass vacuously.
|
|
step "ansible-galaxy install"
|
|
"${galaxy_cmd[@]}" install -r requirements.yml
|
|
|
|
step "ansible-lint"
|
|
"${ansible_lint_cmd[@]}" .
|
|
|
|
step "syntax check"
|
|
for playbook in playbooks/*.yml; do
|
|
printf ' %s\n' "$playbook"
|
|
"${syntax_cmd[@]}" --syntax-check "$playbook" >/dev/null
|
|
done
|
|
|
|
printf '\nAll checks passed.\n'
|