yq — Antora

Attribute Inventory

The single most frequent yq operation in this repository: inspecting antora.yml attributes.

Count total attributes
yq '.asciidoc.attributes | keys | length' docs/antora.yml
# Output: ~134 (grows as infrastructure expands)
List all attribute keys sorted
yq -r '.asciidoc.attributes | keys | .[]' docs/antora.yml | head -20
# Output:
# ad-dc-hostname
# ad-dc-ip
# attribute-missing
# author
# bind-ip
# bt-buds-mac
# bt-buds-name
# bt-kinesis-mac
# bt-kinesis-name
# category
# ...
Find attributes by prefix — infrastructure audit
yq -r '.asciidoc.attributes | to_entries[] | select(.key | test("^ise-")) | "\(.key): \(.value)"' docs/antora.yml
# Output:
# ise-hostname: ise-01.inside.domusdigitalis.dev
# ise-ip: 10.50.1.20
# ise-ers-port: 9060
# ise-openapi-port: 443
# ise-mnt-port: 443
# ise-dc-port: 2484
# ise-pxgrid-port: 8910

Attribute Auditing Patterns

Find all IP address attributes
yq -r '.asciidoc.attributes | to_entries[] | select(.value | type == "!!str" and test("^10\\.50\\.")) | "\(.key): \(.value)"' docs/antora.yml
# Output: every attribute containing a 10.50.x.x IP

This is the audit command for IP sprawl. Run it before any network migration to find every reference.

Find all hostname attributes
yq -r '.asciidoc.attributes | to_entries[] | select(.key | test("-hostname$")) | "\(.key): \(.value)"' docs/antora.yml
# Output:
# ise-hostname: ise-01.inside.domusdigitalis.dev
# vault-hostname: vault-01.inside.domusdigitalis.dev
# vault-01-hostname: vault-01.inside.domusdigitalis.dev
# pfsense-hostname: pfsense-01.inside.domusdigitalis.dev
# wlc-hostname: wlc-01.inside.domusdigitalis.dev
# nas-hostname: nas-01.inside.domusdigitalis.dev
# ...
Find deprecated attributes (grep comments won’t catch these — yq does)
yq -r '.asciidoc.attributes | to_entries[] | select(.key | test("pfsense")) | "\(.key): \(.value)"' docs/antora.yml
# Output:
# pfsense-hostname: pfsense-01.inside.domusdigitalis.dev
# pfsense-ip: 10.50.1.1
# pfsense-api-port: 443

These are retained for historical document references — not active infrastructure.

Attribute categories — count by prefix
yq -r '.asciidoc.attributes | keys | .[]' docs/antora.yml | awk -F- '{print $1}' | sort | uniq -c | sort -rn | head -15
# Output (approximate):
#  12 port
#  10 stats
#   8 ise
#   7 vault
#   6 focus
#   5 vyos
#   5 origin
#   5 level
#   4 kvm
#   4 bt
#   3 ws
#   3 type
#   3 status
#   2 nas
#   2 mail

Combining yq key extraction with awk frequency counting.

Component Metadata

Read component name, title, version
yq '{name: .name, title: .title, version: .version, start_page: .start_page}' docs/antora.yml
# Output:
# name: captures
# title: Work Chronicles
# version: null
# start_page: ROOT:index.adoc
Check nav sources
yq '.nav[]' docs/antora.yml
# Output: modules/ROOT/nav.adoc

Cross-Repo Attribute Comparison

When multiple Antora components define the same attribute, drift happens. Use yq to compare attributes across repos.

Compare a specific attribute across two repos
echo "captures: $(yq -r '.asciidoc.attributes.domain' docs/antora.yml)"
echo "netapi:   $(yq -r '.asciidoc.attributes.domain' ~/atelier/_bibliotheca/domus-netapi-docs/docs/asciidoc/antora.yml 2>/dev/null || echo 'N/A')"
# Shows whether domain is consistent across components
Diff all shared attribute keys between two components
diff <(yq -r '.asciidoc.attributes | keys | .[]' docs/antora.yml | sort) \
     <(yq -r '.asciidoc.attributes | keys | .[]' ~/atelier/_bibliotheca/domus-netapi-docs/docs/asciidoc/antora.yml 2>/dev/null | sort) \
     2>/dev/null | head -30
# Shows attributes present in one but not the other

Process substitution with diff — no temp files needed.

Find attributes unique to this component
comm -23 <(yq -r '.asciidoc.attributes | keys | .[]' docs/antora.yml | sort) \
         <(yq -r '.asciidoc.attributes | keys | .[]' ~/atelier/_bibliotheca/domus-netapi-docs/docs/asciidoc/antora.yml 2>/dev/null | sort) \
         2>/dev/null | head -20
# Output: attributes defined here but not in netapi-docs

Playbook Queries

The Antora playbook (antora-playbook.yml) defines which repos Antora aggregates.

List content sources from a playbook
yq '.content.sources[].url' ~/atelier/_bibliotheca/domus-docs/antora-playbook.yml 2>/dev/null
# Output: URLs of all content source repos
Extract source URLs and branches
yq -r '.content.sources[] | "\(.url) [\(.branches // ["HEAD"] | join(", "))]"' ~/atelier/_bibliotheca/domus-docs/antora-playbook.yml 2>/dev/null
# Output: each repo with its configured branch
Check if a specific component is in the playbook
yq '.content.sources[] | select(.url | test("domus-captures"))' ~/atelier/_bibliotheca/domus-docs/antora-playbook.yml 2>/dev/null
# Output: the content source entry for this component
Show all sources with their start_path — deployment audit
yq '.content.sources[] | [.url, .start_path] | join(" → ")' ~/atelier/_bibliotheca/domus-docs/antora-playbook-ci.yml
# Output:
# ". → docs"
# "./components/domus-infra-ops → docs/asciidoc"
# "./components/domus-ise-linux → docs"
# "./components/domus-captures → docs"
# ...

Quick visual check for which spokes have been migrated from docs/asciidoc to docs.

Filter a specific component’s start_path — use test() not ==
yq '.content.sources[] | select(.url | test("ise-linux")) | .start_path' ~/atelier/_bibliotheca/domus-docs/antora-playbook-ci.yml
# Output: docs

select(.url == "glob") does not work — == is literal comparison. Use test() for regex matching.

Antora UI Configuration

Check UI bundle config
yq '.ui' ~/atelier/_bibliotheca/domus-docs/antora-playbook.yml 2>/dev/null
# Output: UI bundle URL, snapshot flag, supplemental files
List Antora extensions
yq '.antora.extensions[]' ~/atelier/_bibliotheca/domus-docs/antora-playbook.yml 2>/dev/null
# Output: registered Antora extensions

Attribute Validation

Check for empty string attributes (often intentional Antora flags)
yq -r '.asciidoc.attributes | to_entries[] | select(.value == "") | .key' docs/antora.yml
# Output:
# noindex
# icons
# experimental
# sectanchors
# sectlinks
# hide-uri-scheme

Empty string attributes in Antora are boolean flags — they are "set" by having any value, even empty. This is intentional, not a bug.

Check for null attributes (might indicate mistakes)
yq -r '.asciidoc.attributes | to_entries[] | select(.value == null) | .key' docs/antora.yml
# Output: (any keys with null values — these may be errors)
Verify attribute-missing is set to warn
yq '.asciidoc.attributes["attribute-missing"]' docs/antora.yml
# Output: warn@

The warn@ value tells Antora to emit a build warning when a page references an undefined {attribute-name}. This is the safety net against typos.