Skip to content

feat(examples): starter CI, lint and AGENTS.md for collection-fleet - #174

Merged
thiras merged 2 commits into
mainfrom
feat/collection-fleet-ci-agents
Oct 21, 2026
Merged

thiras merged 2 commits into
mainfrom
feat/collection-fleet-ci-agents

Conversation

@thiras

@thiras thiras commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

Summary

examples/collection-fleet/ gets the things our own fleet repo added after it was copied from this template:

  • Starter CI and lint. .github/workflows/ci.yml has three jobs:

    • pre-commit.
    • ansible:
      • installs the collections fresh from Galaxy, retrying only on transient errors;
      • runs scripts/check-vars-shadowing.sh;
      • loads the inventory and every vars file with ansible-inventory --list;
      • syntax-checks decdn.publisher.site, .backup and .decommission.
    • actionlint.

    The example also gets .pre-commit-config.yaml, .yamllint, .markdownlint-cli2.yaml and .github/dependabot.yml. The workflow and README say plainly what CI can't check: what a role does with your variables. Only a --check --diff run shows that.

  • The vars-shadowing trap. Ansible reads only one of <name>/, <name>.yml, <name>.yaml and <name>.json in group_vars/ and host_vars/, and gives no warning. So a group_vars/decdn_nodes/ directory, made to hold a git-ignored secret.yml, drops every setting in decdn_nodes.yml.

    • Verified on ansible-core 2.21.
    • The README documents it, including that host secrets override group secrets and when to use group_vars/all/.
    • The check script runs as a pre-commit hook on the working tree, where the git-ignored folders actually exist and CI can't see them. CI runs it too.
  • AGENTS.md (and CLAUDE.md → @AGENTS.md) for a fleet copy, with a This fleet section for the operator to fill in.

  • Current floors. requirements.yml still said >=0.2.0; it now says decdn.node >=0.4.0 and decdn.publisher >=0.3.1. scripts/release.sh now moves a collection's floor in its release commit, and refuses with a clear reason when it can't: the floor is already at the new version, or there are 0 or 2 or more entries for the collection. RELEASING.md notes the short window before Galaxy publishes the new version.

Guards

  • make test-scripts checks:

    • each floor equals its collection's galaxy.yml version;
    • every action in the example's ci.yml is pinned to a commit SHA that this repo's ci.yml also uses;
    • the example's pre-commit revs and yamllint pin match this repo's, and it uses no hook repo this repo doesn't.

    It also runs check-vars-shadowing.sh on the example's inventory, plus four kinds of shadowing pair. New release.sh fixture cases cover:

    • the floor moves for each collection, and the other's is left alone;
    • each release commit's exact file list;
    • restore after a failed make check;
    • the refusals.
  • ansible/galaxy/check-playbooks.sh, run by make galaxy-check and the galaxy-build job, runs the example the way a copy would, once with each collection's hosts example:

    • the inventory loads under the example's ansible.cfg, and has the expected groups (a cfg that isn't read can't pass silently);
    • every decdn.<collection>.<playbook> named in its README, AGENTS.md or CI ships and passes a syntax check.

    CI's ansible path filter now includes examples/collection-fleet/**.

  • CI's actionlint lints the example workflow too, and a root yamllint hook covers the example under its own .yamllint.

Test plan

  • make test-scripts: all pass
  • pre-commit run --all-files, in the repo and in a scratch copy of the example
  • galaxy/check-playbooks.sh node|publisher, plus negative cases: an unknown playbook name, an ansible.cfg with no inventory, and an exported ANSIBLE_INVENTORY
  • In a scratch copy of the example, the CI ansible steps by hand against Galaxy (decdn.node 0.4.0, decdn.publisher 0.3.1). With a floor Galaxy doesn't have, the install fails at once with ::error::
  • The pre-commit shadowing hook fails on a git-ignored group_vars/decdn_nodes/secret.yml next to decdn_nodes.yml
  • actionlint on the example workflow

🤖 Generated with Claude Code

Bring what decdn/fleet learned back into the template it was copied from:

- CI (pre-commit; a fresh Galaxy install, a vars-shadowing guard, inventory
  parse and playbook syntax-check; actionlint), pre-commit, yamllint,
  markdownlint and dependabot configs, and an AGENTS.md/CLAUDE.md skeleton.
- Document group-wide secrets in group_vars/<group>/secret.yml, and that a
  group_vars/<group>/ directory silently replaces a <group>.yml beside it.
- requirements.yml floors were still >=0.2.0: raise them to the current
  releases, and have scripts/release.sh move a collection's floor in its
  release commit.

Guards: make test-scripts checks the floors equal the galaxy.yml versions and
that the example pins this repo's action SHAs and hook revs;
galaxy/check-playbooks.sh runs the example against the built collections
(inventory parses, every playbook it names ships and syntax-checks); CI's
actionlint and yamllint cover its workflow and inventory.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings October 21, 2026 15:58

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

No unresolved defects were identified in the starter configuration, release-floor handling, or regression guards.

No open issues 🎉

What changed in this PR

Makes the collection-fleet example a more complete starter repository, with CI, linting, operator guidance, and release-synchronized collection requirements.

Changes:

  • Adds starter CI, lint configuration, dependency updates, and agent guidance.
  • Documents and checks Ansible vars-file shadowing.
  • Synchronizes collection floors during releases and adds regression checks.
File Description
tests/​scripts-test.sh Tests pin alignment and release-floor updates.
scripts/​release.sh Updates and restores example floors during releases.
RELEASING.md Documents release-floor synchronization.
examples/​collection-fleet/​requirements.yml Raises collection minimum versions.
examples/​collection-fleet/​README.md Explains CI, secrets, and upgrades.
examples/​collection-fleet/​CLAUDE.md References fleet agent guidance.
examples/​collection-fleet/​AGENTS.md Adds fleet-specific operating guidance.
examples/​collection-fleet/​.yamllint Configures inventory YAML linting.
examples/​collection-fleet/​.pre-commit-config.yaml Adds hygiene and lint hooks.
examples/​collection-fleet/​.markdownlint-cli2.yaml Configures Markdown linting.
examples/​collection-fleet/​.github/​workflows/​ci.yml Adds lint, inventory, and playbook checks.
examples/​collection-fleet/​.github/​dependabot.yml Schedules action and hook updates.
CONTRIBUTING.md Documents expanded validation coverage.
ansible/​README.md Explains group-secret shadowing.
ansible/​galaxy/​check-playbooks.sh Validates the example against built collections.
AGENTS.md Documents example maintenance couplings.
.pre-commit-config.yaml Lints the example’s Ansible inputs.
.github/​workflows/​ci.yml Includes example changes and workflow linting.

Review effort: Balanced

- CI loads the inventory with ansible-inventory --list, which reads every vars file
  (--graph read none), and says what it cannot check: what a role makes of the
  variables.
- The vars-shadowing check is now scripts/check-vars-shadowing.sh, run by a
  pre-commit hook on the working tree (where git-ignored secret.yml directories
  exist) and by CI; it also catches .yml beside .yaml and extensionless names.
- The Galaxy install retries only transient errors, and fails at once with an
  ::error:: otherwise; the workflow runs bash with pipefail.
- check-playbooks.sh: unset the caller's inventory overrides, assert the hosts
  example's groups (a cfg that is not read gives an implicit localhost, exit 0),
  and say which doc file is missing instead of exiting silently.
- fleet_pins_check refuses a tag-pinned action, an unknown hook repo and a
  yamllint pin in another spelling; release.sh says why a floor cannot move
  (already there, N entries); more release.sh and shadowing tests.
- Docs: sudo-rs advice only where a become password is sent, first-run wording
  that matches the hosts examples, host-over-group secret precedence and
  group_vars/all, the floor's window before Galaxy publishes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@thiras
thiras merged commit 005f85a into main Oct 21, 2026
56 checks passed
@thiras
thiras deleted the feat/collection-fleet-ci-agents branch October 21, 2026 16:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants