Configure yamllint and ansible-lint, plus a workflow running yamllint, ansible-lint and ansible-playbook --syntax-check over every playbook. ansible-lint uses the moderate profile: on the current code it reports exactly the same violations as basic, so it costs nothing today while holding a higher bar for new code. skip_list is empty; noisy legacy rules go to warn_list with a comment on why and when to restore them. Correctness and safety rules stay fatal. Two constraints are encoded in the workflow: syntax-check must run from ansible/ because roles_path is relative, and ansible-lint needs absolute ANSIBLE_ROLES_PATH/ANSIBLE_COLLECTIONS_PATH when run from the root. The runner is not registered yet; registration notes are in the workflow. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GTocXkGUUazHdKKd3r9k71
135 lines
6.3 KiB
YAML
135 lines
6.3 KiB
YAML
---
|
||
# Статические проверки Ansible-кода HomeLab infras.
|
||
#
|
||
# ГДЕ ЭТО ДОЛЖНО ВЫПОЛНЯТЬСЯ
|
||
# --------------------------
|
||
# Gitea живёт на LXC `gitea` (192.168.1.25). Gitea Actions по умолчанию
|
||
# ВЫКЛЮЧЕНЫ и не имеют ни одного раннера — этот workflow не запустится,
|
||
# пока раннер не зарегистрирован ОТДЕЛЬНО, вручную:
|
||
#
|
||
# 1. Включить Actions в Gitea:
|
||
# app.ini -> [actions] ENABLED = true
|
||
# и в настройках репозитория: Settings -> Actions -> Enable.
|
||
#
|
||
# 2. Поднять act_runner. Подходящий хост — LXC `docker-test`
|
||
# (192.168.1.29): там уже есть Docker, а сборка контейнеров раннера
|
||
# не мешает проду. Ставить раннер на сам LXC `gitea` не стоит —
|
||
# CI-нагрузка не должна валить git-сервис.
|
||
#
|
||
# 3. Зарегистрировать раннер (на docker-test):
|
||
# act_runner register --no-interactive \
|
||
# --instance http://192.168.1.25:3000 \
|
||
# --token <RUNNER_TOKEN из Gitea Settings -> Actions -> Runners> \
|
||
# --name docker-test-runner \
|
||
# --labels ubuntu-latest:docker://catthehacker/ubuntu:act-latest
|
||
#
|
||
# Метка `ubuntu-latest` обязательна — именно её просит `runs-on` ниже.
|
||
#
|
||
# 4. Раннеру нужен исходящий интернет (PyPI + Ansible Galaxy).
|
||
# На docker-test трафик может идти через mihomo/OpenVPN — проверить,
|
||
# что pip и galaxy резолвятся, иначе шаг установки упадёт.
|
||
#
|
||
# Регистрация раннера НЕ автоматизирована этим репозиторием: она требует
|
||
# одноразового токена из веб-интерфейса Gitea.
|
||
#
|
||
# Локально те же проверки воспроизводятся через nix:
|
||
# nix develop -c yamllint .
|
||
# nix develop -c ansible-lint
|
||
# nix develop -c sh -c 'cd ansible && for f in playbooks/*.yml; do ansible-playbook --syntax-check "$f"; done'
|
||
|
||
name: lint
|
||
|
||
on:
|
||
push:
|
||
pull_request:
|
||
|
||
jobs:
|
||
lint:
|
||
name: yamllint + ansible-lint + syntax-check
|
||
runs-on: ubuntu-latest
|
||
|
||
env:
|
||
# ansible.cfg лежит в ansible/ и использует ОТНОСИТЕЛЬНЫЕ пути
|
||
# (roles_path = roles). Из корня репозитория он не работает, поэтому
|
||
# пути задаются абсолютно через окружение. Без этого ansible-lint
|
||
# выдаёт 12 ложных syntax-check[specific] «role not found».
|
||
ANSIBLE_ROLES_PATH: ${{ github.workspace }}/ansible/roles
|
||
ANSIBLE_COLLECTIONS_PATH: ${{ github.workspace }}/ansible/collections
|
||
ANSIBLE_INVENTORY: ${{ github.workspace }}/ansible/inventory/hosts.yml
|
||
# Ansible шумит депрекейшенами ядра — в CI они не наши.
|
||
ANSIBLE_DEPRECATION_WARNINGS: "false"
|
||
PIP_DISABLE_PIP_VERSION_CHECK: "1"
|
||
|
||
steps:
|
||
- name: Checkout
|
||
uses: actions/checkout@v4
|
||
|
||
# Образ catthehacker/ubuntu:act-latest уже несёт python3, но не всегда
|
||
# python3-venv. Ставим явно, чтобы шаг не был хрупким.
|
||
- name: Ensure python3 + venv
|
||
run: |
|
||
set -eux
|
||
if ! command -v python3 >/dev/null 2>&1 || ! python3 -m venv --help >/dev/null 2>&1; then
|
||
apt-get update
|
||
apt-get install -y --no-install-recommends python3 python3-venv python3-pip
|
||
fi
|
||
python3 --version
|
||
|
||
- name: Install ansible-core, ansible-lint, yamllint
|
||
run: |
|
||
set -eux
|
||
python3 -m venv /tmp/lintenv
|
||
. /tmp/lintenv/bin/activate
|
||
python3 -m pip install --upgrade pip
|
||
# ansible-core/proxmoxer/requests берём из репозитория, чтобы CI и
|
||
# локальное окружение не разъезжались.
|
||
python3 -m pip install -r ansible/requirements.txt
|
||
# Линтеры пинуем: обновление ansible-lint регулярно добавляет новые
|
||
# правила и красит CI без единого коммита в инфраструктуру.
|
||
python3 -m pip install 'ansible-lint==25.8.2' 'yamllint==1.37.1'
|
||
echo "/tmp/lintenv/bin" >> "$GITHUB_PATH"
|
||
|
||
- name: Install Galaxy collections
|
||
run: |
|
||
set -eux
|
||
ansible-galaxy collection install \
|
||
-r ansible/requirements.yml \
|
||
-p ansible/collections
|
||
|
||
- name: Versions
|
||
run: |
|
||
set -eux
|
||
ansible --version | head -n1
|
||
ansible-lint --version
|
||
yamllint --version
|
||
|
||
# Конфиг в /.yamllint. Падает только на ошибках (табы, дубли ключей,
|
||
# битый YAML); стилевые замечания идут как warning и CI не роняют.
|
||
- name: yamllint
|
||
run: yamllint -f standard .
|
||
|
||
# Конфиг в /.ansible-lint, profile: moderate.
|
||
- name: ansible-lint
|
||
run: ansible-lint
|
||
|
||
# syntax-check запускается ИЗ ansible/, иначе ansible.cfg с
|
||
# относительными roles_path не подхватывается и 13 плейбуков падают
|
||
# с «role not found». Переменные Proxmox (PROXMOX_*) для syntax-check
|
||
# НЕ нужны: `lookup('env', ...)` на этапе парсинга не вычисляется,
|
||
# проверено — все 37 плейбуков проходят с пустым окружением.
|
||
- name: ansible-playbook --syntax-check (все плейбуки)
|
||
working-directory: ansible
|
||
run: |
|
||
set -u
|
||
rc=0
|
||
for f in playbooks/*.yml; do
|
||
if ansible-playbook --syntax-check "$f" >/tmp/sc.log 2>&1; then
|
||
echo "ok $f"
|
||
else
|
||
rc=1
|
||
echo "FAIL $f"
|
||
sed 's/^/ /' /tmp/sc.log
|
||
fi
|
||
done
|
||
exit "$rc"
|