046 - Custom Roles from Inventory-Declared Sources¶
User Story¶
As an operator, I want to declare application roles that live in their own repositories, such as the landing page and the store GUI, as ordinary inventory groups that Infinito.Nexus pulls into roles/web-app-cst-* and verifies like every in-tree role, so that these projects ship their role from their own repository without a fork of core and without a second, weaker set of checks.
Acceptance Criteria¶
Declaration¶
[x] A custom role is an ordinary inventory group named
web-app-cst-<name>; a host joins it the same way it joins anyweb-app-*group.[x]
applications.web-app-cst-<name>.custom: true, set inhost_varsor anywhere else the inventory sets application values, marks the group as a custom role.[x]
applications.web-app-cst-<name>.sourceholdsurl(a Git URL over HTTPS or SSH),version(a tag or a full commit SHA) andpath(the role directory inside that repository).[x] A custom role whose
source.versionnames a branch, or whosesourcemissesurl,versionorpath, stops the run before anything is pulled, and the message names the group and the missing or rejected field.[x] A group named
web-app-cst-*withoutcustom: true, orcustom: trueon a group outside theweb-app-cst-prefix, stops the run with a message naming the group.[x] The pull reads
customandsourcefrom the raw inventory and never renders them as templates: a value that holds a Jinja expression stops the run with a message naming the group and the field, so no templated value can trigger a fetch.[x] A
source.urlthat embeds credentials stops the run without echoing the URL.
Authentication¶
[x] A private repository is fetched through the SSH agent or SSH configuration of the controller.
[x] A fetch that needs interactive credentials fails instead of prompting.
[x] No credential reaches the inventory, the
ansible-playbookcommand line, Ansible variables or the deploy log.
Pull and placement¶
[x] Before the playbook starts, and so before the applications SPOT reads
roles/*/meta/, the deploy pulls every custom role declared for the target hosts at itssource.versionand placessource.pathasroles/web-app-cst-<name>in the core checkout that runs the deploy.[x] A
maketarget pulls the custom roles an inventory declares into the local core checkout without deploying, so every othermaketarget can run against them.[x] A local directory may stand in for
source.urlduring development, so a role checkout is verified and deployed without a tag.[x] A local source that resolves to its own placement directory
roles/web-app-cst-<name>stops the run with a message naming the path, so a pull never deletes its own source.[x] A placed role whose directory name or
vars/main.ymlapplication_iddiffers from its group name stops the run with a message naming both values; core never renames a role.[x] Pulling again replaces each
roles/web-app-cst-*directory with the pinned content, and removes the directory of a custom role the inventory no longer declares.[x] A pull that stops leaves
roles/unchanged, and no staging or leftover directory of a pull appears underroles/.[x] A declared name that meets a symbolic link under
roles/, or a directory the pull did not place, stops the run with a message naming it, and the pull never replaces or removes such a directory.[x] A command lists the placed custom roles with their source and resolved commit, and a
maketarget removes everyroles/web-app-cst-*directory the pull placed and nothing else.[ ]
INFINITO_EXTRA_MOUNTS=<dir>[,<dir>]mounts each directory read-only at the same path into theinfinitocontainer when the stack is created, so a localsource.urlresolves inside the container; an entry that is not an existing absolute directory stops the stack start with an error naming it.[x]
roles/web-app-cst-*is ignored by Git in core, so a pulled role never enters a core commit.[x] The
web-app-cst-prefix is reserved: a lint fails on an in-tree role whose name starts with it.[x]
meta/categories.ymldeclaresweb-app-cstas a category, so the entity name ofweb-app-cst-<name>is<name>and the container, database and volume names a custom role derives stay what they were before its rename.[x] A custom role whose entity name equals the entity name of an in-tree role stops the run with a message naming both roles.
[ ] A swarm or Act run (
make swarm-*,make act-*) carries the pulled custom roles into the copy of the core checkout its nodes use.
Verification¶
[ ] A pulled custom role is scanned by
make test,make lintandmake quality-highexactly like an in-tree role: no lint, unit or integration check skipsroles/web-app-cst-*, and no check exists only for custom roles. The one exception is the licence: a custom role is exempt from the Infinito.Nexus licence wording the role README lint demands in Credits, and states its own licence instead.[ ]
make compose-deploydeploys a pulled custom role through the same path as an in-tree role, including its Playwright specs.[ ] The README of
php-landingpageand ofinfinito-nexus-guidocuments the inventory format above for their role.[ ]
php-landingpagenames its roleweb-app-cst-<name>in directory andapplication_id, and its CI pulls the role into a core checkout and runs core’smake testandmake lintagainst it.[ ]
infinito-nexus-guinames its store roleweb-app-cst-<name>in directory andapplication_id, and its CI pulls the role into a core checkout and runs core’smake testandmake lintagainst it.
Quality¶
[x] The pull, placement, validation and cleanup logic has unit tests, including a branch name refused as
source.version, a role whoseapplication_iddiffers from its group, and the removal of a role the inventory no longer declares.[ ]
make testpasses.