Skip to content

Gate the generated Ansible collection on ansible-lint in CI - #15184

Merged
jan-cerny merged 5 commits into
ComplianceAsCode:masterfrom
ggbecker:cert-ansible-lint-ci-gate
Oct 23, 2026
Merged

jan-cerny merged 5 commits into
ComplianceAsCode:masterfrom
ggbecker:cert-ansible-lint-ci-gate

Conversation

@ggbecker

@ggbecker ggbecker commented Oct 13, 2026 •

Copy link
Copy Markdown
Member

Description:

  • Extend the gate-lint-ansible-roles CI workflow to lint the generated Ansible collection against the command-instead-of-module rule.
  • Tighten the role lint gate so it covers the certification rules, and drop the waivers from tests/ansible-lint_config.yml that are now enforced.

Rationale:

  • Automation Hub partner certification runs ansible-lint under the production profile. These gates catch command-instead-of-module and related violations in CI so regressions never reach the published collection.

Review Hints:

run: ansible-lint -x 204 -x experimental -x command-instead-of-module ./build/ansible_roles/*
run: ansible-lint -x 204 -x experimental ./build/ansible_roles/*
- name: Build Ansible Collection (as published downstream)
run: python3 utils/ansible_roles_to_collection.py --roles-dir ./build/ansible_roles --output-dir ./build/ansible_collection --namespace redhat --collection rhel_hardening_roles

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Does this work if there isn't the PYTHONPATH=. unlike the other commands? We don't know if it works because the CI job terminates in the "Lint Ansible Roles" step and doesn't even run this step.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I think it's worth to update it with the same variable definition

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Done. Added workflow-level env vars COLLECTION_NAMESPACE: redhat and COLLECTION_NAME: rhel_hardening_roles and used them both in the build command and in the gate step's working-directory. Also added the missing PYTHONPATH=. to the collection build step (the script does from ssg.constants import min_ansible_version, which needs the repo root on the path, like the other build steps).

@ggbecker
ggbecker force-pushed the cert-ansible-lint-ci-gate branch 2 times, most recently from 56b7f0b to 6c556e3 Compare October 16, 2026 10:36
run: ansible-lint -x 204 -x experimental -x command-instead-of-module ./build/ansible_roles/*
run: ansible-lint -x 204 -x experimental ./build/ansible_roles/*
- name: Build Ansible Collection (as published downstream)
run: PYTHONPATH=. python3 utils/ansible_roles_to_collection.py --roles-dir ./build/ansible_roles --output-dir ./build/ansible_collection --namespace ${{ env.COLLECTION_NAMESPACE }} --collection ${{ env.COLLECTION_NAME }}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

the --namespace option doesn't exist

ansible_roles_to_collection.py: error: unrecognized arguments: --namespace redhat

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Fixed in a01f737. --namespace was replaced upstream by --target {galaxy,hub} (which derives the namespace/author/metadata as a set), so I rebased onto current master and switched the workflow to --target hub --collection ${{ env.COLLECTION_NAME }}, which resolves to namespace redhat (same as before). Verified end-to-end locally: built real rhel9 roles, ran this exact command, and confirmed the collection lands at ansible_collections/redhat/rhel_hardening_roles as the subsequent gate step expects.

@ggbecker
ggbecker force-pushed the cert-ansible-lint-ci-gate branch 5 times, most recently from e92c343 to 5351f9e Compare October 19, 2026 13:52
@github-actions

github-actions Bot commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

This datastream diff is auto generated by the check Compare DS/Generate Diff

Click here to see the full diff
ansible remediation for rule 'xccdf_org.ssgproject.content_rule_enable_gpgcheck_for_all_repositories' differs.
--- xccdf_org.ssgproject.content_rule_enable_gpgcheck_for_all_repositories
+++ xccdf_org.ssgproject.content_rule_enable_gpgcheck_for_all_repositories
@@ -24,6 +24,8 @@
     option: gpgcheck
     value: '1'
     no_extra_spaces: true
+    mode: '0644'
+    owner: root
   loop: '{{ repo_grep_results.stdout | regex_findall( ''(.+\.repo):\[(.+)\]\n?'' )
     if repo_grep_results is not skipped else [] }}'
   when: repo_grep_results is not skipped

ansible remediation for rule 'xccdf_org.ssgproject.content_rule_ensure_gpgcheck_never_disabled' differs.
--- xccdf_org.ssgproject.content_rule_ensure_gpgcheck_never_disabled
+++ xccdf_org.ssgproject.content_rule_ensure_gpgcheck_never_disabled
@@ -36,6 +36,7 @@
     value: '1'
     no_extra_spaces: true
     mode: '0644'
+    owner: root
   loop: '{{ repo_grep_results.stdout |regex_findall( ''(.+\.repo):\[(.+)\]\n?'' )
     if repo_grep_results is not skipped else [] }}'
   when: repo_grep_results is not skipped

@jan-cerny

Copy link
Copy Markdown
Member

/packit build

@jan-cerny

Copy link
Copy Markdown
Member

@ggbecker Have you noticed this suspicious message in the GitHub action jobs output? Is this expected? What does it mean?

https://github.com/ComplianceAsCode/content/actions/runs/39263858402/job/118098652705?pr=15184

Run ANSIBLE_COLLECTIONS_PATH="$GITHUB_WORKSPACE/build/ansible_collection" ansible-lint --nocolor --tags command-instead-of-module roles/
WARNING  Another version of 'redhat.rhel_hardening_roles' 0.1.83 was found installed in /__w/content/content/build/ansible_collection/ansible_collections/redhat/rhel_hardening_roles/.ansible/collections/ansible_collections, only the first one will be used, 0.1.83 (/__w/content/content/build/ansible_collection/ansible_collections).

echo "--- FQCN rewrite check ---"
if grep -rq "community\.general\.\|ansible\.posix\." "${COLLECTION_DIR}/roles/" 2>/dev/null; then
echo "FAIL: unrewritten FQCNs found:"
grep -rn "community\.general\.\|ansible\.posix\." "${COLLECTION_DIR}/roles/"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Should it exit with 1 and/or save the exit code to exit with 1? It seems that it will print FAIL but finish successfully.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Should be fixed by:

Make utils/test_ansible_collection.sh return a non-zero exit status when the
FQCN rewrite check finds unrewritten references, instead of printing FAIL and
finishing successfully.

@ggbecker

Copy link
Copy Markdown
Member Author

@ggbecker Have you noticed this suspicious message in the GitHub action jobs output? Is this expected? What does it mean?

https://github.com/ComplianceAsCode/content/actions/runs/39263858402/job/118098652705?pr=15184

Run ANSIBLE_COLLECTIONS_PATH="$GITHUB_WORKSPACE/build/ansible_collection" ansible-lint --nocolor --tags command-instead-of-module roles/
WARNING  Another version of 'redhat.rhel_hardening_roles' 0.1.83 was found installed in /__w/content/content/build/ansible_collection/ansible_collections/redhat/rhel_hardening_roles/.ansible/collections/ansible_collections, only the first one will be used, 0.1.83 (/__w/content/content/build/ansible_collection/ansible_collections).

Should be fixed by the following change:

Run the collection gate with --offline so ansible-lint does not install a
cache copy of the collection it is linting. The collection is already
available through ANSIBLE_COLLECTIONS_PATH, and the cache copy triggered a
confusing "Another version of 'redhat.rhel_hardening_roles' ... was found
installed" warning.

Remove command-instead-of-module, risky-file-permissions and the legacy
301/303/403/503 ids from the content CI ansible-lint skip list, and update
the role lint gate workflow so the non-skippable certification rules are
enforced on generated roles.
The downstream redhat.rhel_hardening_roles collection enforces
ansible-lint's command-instead-of-module rule for Automation Hub
certification. Command/shell remediations that have a module equivalent
are rewritten to the vendored ssg_hardening module when the collection is
assembled; a new upstream remediation whose command is not mapped would
stay raw and regress certification, which is only discovered at publishing
time today.

Extend the RHEL Ansible-role gate to assemble the collection the same way
downstream does and lint it with just the command-instead-of-module rule
(with ANSIBLE_COLLECTIONS_PATH set so the vendored modules resolve). This
fails the pull request that introduces an unmapped command instead of the
publishing pipeline. Commands without a module equivalent (find, grep,
custom shell, ...) are not flagged by this rule, so they do not cause
false failures.
Run the collection gate with --offline so ansible-lint does not install a
cache copy of the collection it is linting. The collection is already
available through ANSIBLE_COLLECTIONS_PATH, and the cache copy triggered a
confusing "Another version of 'redhat.rhel_hardening_roles' ... was found
installed" warning.

Make utils/test_ansible_collection.sh return a non-zero exit status when the
FQCN rewrite check finds unrewritten references, instead of printing FAIL and
finishing successfully.
branches: [ 'master' ] has one space too many inside the brackets
(yamllint's brackets rule), pre-existing since the workflow was added in
2021. Not related to this PR's changes, but caught while touching this
file; fix it while we're here.
Per review, add owner: root alongside the existing mode: '0644' on the
ini_file task in ensure_gpgcheck_never_disabled, matching the same change
made to enable_gpgcheck_for_all_repositories in this PR. Not required by
ansible-lint's risky-file-permissions rule (which only checks mode), but
makes repo file ownership explicit rather than implicit.
@ggbecker
ggbecker force-pushed the cert-ansible-lint-ci-gate branch from 263df0a to 4f875c1 Compare October 23, 2026 12:37

@jan-cerny jan-cerny left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The Build, Lint Ansible Roles on Fedora Latest (Container) builds the collection and passes the lint and also passes the command-on-module gating test.

@jan-cerny
jan-cerny merged commit 4b1a9a8 into ComplianceAsCode:master Oct 23, 2026
74 of 75 checks passed
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.

3 participants