Files
computer-playbook/docs/contributing/actions/testing/suppression.md
T
kevinveenbirkenbachandClaude Opus 4.7 cb4cc393d0 test(lint): forbid hard-coded NETWORK_PUBLIC_DNS_RESOLVERS IPs
Roles, playbooks, templates and scripts MUST consume the central
`NETWORK_PUBLIC_DNS_RESOLVERS` list from `group_vars/all/08_networks.yml`
instead of pasting `1.1.1.1` / `8.8.8.8` / `1.0.0.1` literally, so a
single edit propagates everywhere those resolvers are used.

- tests/lint/repository/test_no_hardcoded_dns_resolvers.py: scans the
  repo for the literal IPs declared in NETWORK_PUBLIC_DNS_RESOLVERS,
  fails on any occurrence not covered by `# noqa: hardcoded-dns-resolver`.
- roles/sys-svc-container/vars/main.yml: `SYS_SVC_DOCKER_AUTOMTU_TARGETS`
  no longer hard-codes `1.1.1.1`; the list is now built from
  `['registry-1.docker.io', 'github.com'] + NETWORK_PUBLIC_DNS_RESOLVERS`.
- roles/user/templates/bashrc.j2: `ip route get 8.8.8.8` ->
  `ip route get {{ NETWORK_PUBLIC_DNS_RESOLVERS[0] }}`.
- group_vars/all/08_networks.yml: drop literal IP examples from the
  resolver-block doc comment.
- compose/coredns/Corefile.tmpl, scripts/system/network/dns/setup/wsl.sh,
  roles/sys-ctl-mtn-cert-deploy/SETUP.md: tag the legitimate literal
  occurrences with `# noqa: hardcoded-dns-resolver`. These are
  substitution points that cannot consume the variable (CoreDNS
  forward directive, host-bootstrap shell fallback, Markdown example).
- docs/contributing/actions/testing/suppression.md: catalog the new
  `hardcoded-dns-resolver` rule with position semantics and example.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 20:27:38 +02:00

8.5 KiB

Suppression Markers 🚫

The unified # noqa / # nocheck syntax that suppresses individual checks across the infinito-nexus test suite.

You MUST use these markers only when the check genuinely does not apply. You MUST NOT use them to silence legitimate issues.

Grammar 📐

A suppression marker is a comment carrying one or more rule keys:

<comment-prefix> (noqa|nocheck): <rule>(, <rule>)*

Rules:

  • noqa and nocheck are synonyms. By convention, use noqa for code-level lints (analogous to flake8 / ruff) and nocheck for repository-content checks (URLs, image versions, file size, run-once schema). Either keyword works for any rule; the test does not enforce which one is used.
  • The keyword is matched case-insensitively.
  • <rule> is a kebab-case identifier from the catalog below.
  • Multiple rules MAY be combined on one comment, comma-separated: # noqa: shared, email.

Accepted comment prefixes (so the marker fits any file format that the test scans):

Prefix Use in
# Python, YAML, shell, conf, INI, …
// JS, JSONC, …
{# … #} Jinja2 templates
<!-- … --> HTML, Markdown

Implementation: utils/annotations/suppress.py.

Position semantics 📍

The placement rule is per check. The catalog column "Position" uses these labels:

  • same line: the marker MUST be on the same line as the construct it suppresses.
  • line above: the marker MUST be on the immediately preceding non-empty line. Blank lines between the marker and the construct break the association.
  • same or above: either of the above is accepted.
  • comment block above: the marker may sit on any line in a contiguous comment block above the construct (no blank line between marker and construct).
  • head (first 30 lines): the marker MAY appear anywhere in the first 30 lines of the file. Used for file-level opt-outs that should stay visible at the top of the file.
  • anywhere: the marker may appear on any line of the file. Used for whole-file opt-outs whose semantics legitimately apply to the entire file.

Catalog 📚

Rule Position Affected test Effect
url same or above test_urls_reachable.py Skips probing the literal HTTP(S) URL. Use for CDN roots and API base URLs that return 4xx without a path.
docker-version line above test_image_versions.py Skips the live version-update warning for that image's version: key.
direct-yaml same line / span test_no_direct_yaml_calls.py Allows the marked yaml.safe_load / safe_dump call to bypass utils.cache.yaml.
shared comment block above test_service_shared_consistency.py Marks a service whose enabled: true legitimately does not require shared: true.
email line above test_web_app_email_integration.py Suppresses the missing-email-integration warning when paired with enabled: false and shared: false.
file-size head (first 30 lines) test_python_file_size.py Opts the entire .py file out of the 500-line cap.
run-once anywhere test_run_once_tags.py, test_schema.py Marks a role's tasks/main.yml as intentionally re-runnable; skips both the run-once tag check and the suffix check.
run-once-suffix same line test_schema.py Allows a single when: item to reference a run_once_<other> flag whose suffix differs from the current role.
raw-docker same or above; head (first 30 lines) test_no_raw_docker.py Marks a single line or a whole file under roles/ as legitimately calling docker / docker compose / docker-compose directly. The check is scoped to roles/; bootstrap scripts and CI workflows outside roles/ are not scanned and need no marker.
hardcoded-dns-resolver same or above test_no_hardcoded_dns_resolvers.py Marks a line that legitimately needs a literal IP from NETWORK_PUBLIC_DNS_RESOLVERS at the substitution point (CoreDNS forward directives that don't run through Jinja, host-bootstrap shell scripts, documentation examples). The variable in group_vars/all/08_networks.yml is the SPOT for these IPs everywhere else.

Examples 💡

url, on the line carrying the literal URL or on the line above it:

ensure_proxy_repo raw raw-packagist "$(... https://repo.packagist.org/ ...)"  # nocheck: url
# nocheck: url
api_base_url: "https://example.org/v1"

docker-version, directly above a version: key:

service_x:
  # nocheck: docker-version
  version: "4.5"

direct-yaml, anywhere on the call's physical line or on any line spanned by the multi-line call:

data = yaml.safe_load(text)  # noqa: direct-yaml

shared, somewhere in the comment block immediately above a service key:

# This service is inherently role-local.
# noqa: shared
my_local_service:
  enabled: true

email, directly above the email: block, paired with both flags false:

# noqa: email
email:
  enabled: false
  shared: false

file-size, at the top of a long Python file:

"""Module docstring."""
# nocheck: file-size  (single-host orchestration script ships as one file)

run-once, at the top of a role's tasks/main.yml:

# nocheck: run-once

- name: ...

run-once-suffix, on the exact when: list-item line:

when:
  - run_once_svc_db_openldap is not defined   # noqa: run-once-suffix

raw-docker, per-line on a single role-task line that legitimately calls docker directly (e.g. a bootstrap step that runs before the container wrapper is on the path):

- name: "Bootstrap engine before the wrapper exists"
  ansible.builtin.command: docker info  # noqa: raw-docker

raw-docker, file-level at the top of a role's bundled shell script that legitimately drives the engine directly:

#!/usr/bin/env bash
# nocheck: raw-docker. Runs from sys-svc-container's installer before the wrapper symlink lands.
docker buildx build ...

hardcoded-dns-resolver, on the line that emits the literal IP, when the substitution point cannot consume NETWORK_PUBLIC_DNS_RESOLVERS (e.g. a CoreDNS forward directive in a non-Jinja template):

forward . 1.1.1.1 8.8.8.8  # noqa: hardcoded-dns-resolver

Adding a new rule 🆕

  1. Pick a kebab-case <rule> identifier.
  2. Decide which position semantic from the list above fits the check.
  3. Use the is_suppressed_at / is_suppressed_in_head / is_suppressed_anywhere helpers from utils/annotations/suppress.py in your test. Do NOT roll a new regex.
  4. Add the rule to the catalog table on this page.