Drill 03: Composition

gron discovers, jq extracts, yq bridges YAML. All three together.

Run This Drill

bash ~/atelier/_bibliotheca/domus-captures/docs/modules/ROOT/examples/gron-drills/03-composition.sh

Drill Script

#!/bin/bash
# GRON DRILL 03: COMPOSITION
# Paste this entire script into your terminal
# Topics: Multi-tool pipelines — gron + jq + yq

echo "=================================================================="
echo "             GRON DRILL 03: COMPOSITION                           "
echo "=================================================================="
echo ""

# ---------------------------------------------------------------------------
echo "------------------------------------------------------------------"
echo "DRILL 3.1: YAML → JSON → GRON"
echo "yq converts YAML, gron explores the JSON"
echo "------------------------------------------------------------------"
echo ""
ANTORA="$HOME/atelier/_bibliotheca/domus-captures/docs/asciidoc/antora.yml"
if [[ -f "$ANTORA" ]]; then
    echo "Command: yq -o=json '.' $ANTORA | gron | head -20"
    yq -o=json '.' "$ANTORA" | gron | head -20
    echo "  ..."
    echo ""
    echo "Command: yq -o=json '.' $ANTORA | gron | grep -E '[0-9]+\\.[0-9]+\\.[0-9]+'"
    yq -o=json '.' "$ANTORA" | gron | grep -E '[0-9]+\.[0-9]+\.[0-9]+' | head -10
    echo ""
else
    echo "(Skipped — domus-captures not found)"
    echo ""
fi

# ---------------------------------------------------------------------------
echo "------------------------------------------------------------------"
echo "DRILL 3.2: GRON → JQ — THE HANDOFF"
echo "gron discovers structure, jq does the heavy lifting"
echo "------------------------------------------------------------------"
echo ""
cat << 'EOF' > /tmp/gron-complex.json
{
  "cluster": {
    "name": "domus-k3s",
    "nodes": [
      {"hostname": "k3s-master", "ip": "10.50.1.80", "role": "control-plane", "cpu": 4, "memory_gb": 16},
      {"hostname": "k3s-worker-01", "ip": "10.50.1.81", "role": "worker", "cpu": 8, "memory_gb": 32},
      {"hostname": "k3s-worker-02", "ip": "10.50.1.82", "role": "worker", "cpu": 8, "memory_gb": 32}
    ],
    "services": {
      "ingress": {"type": "traefik", "port": 443},
      "monitoring": {"type": "prometheus", "port": 9090},
      "logging": {"type": "loki", "port": 3100}
    }
  }
}
EOF
echo "Step 1 — Discover with gron:"
echo "Command: gron /tmp/gron-complex.json | grep memory"
gron /tmp/gron-complex.json | grep memory
echo ""
echo "Step 2 — Extract with jq:"
echo "Command: jq '[.cluster.nodes[] | {hostname, memory_gb}]' /tmp/gron-complex.json"
jq '[.cluster.nodes[] | {hostname, memory_gb}]' /tmp/gron-complex.json
echo ""
echo "Step 3 — Aggregate with jq:"
echo "Command: jq '.cluster.nodes | map(.memory_gb) | add' /tmp/gron-complex.json"
echo "Total cluster memory (GB):"
jq '.cluster.nodes | map(.memory_gb) | add' /tmp/gron-complex.json
echo ""

# ---------------------------------------------------------------------------
echo "------------------------------------------------------------------"
echo "DRILL 3.3: FIND NULLS AND EMPTIES"
echo "Debugging pattern: find missing data"
echo "------------------------------------------------------------------"
echo ""
cat << 'EOF' > /tmp/gron-debug.json
{"users":[{"name":"alice","email":"alice@domus.dev","team":"infra"},{"name":"bob","email":null,"team":"infra"},{"name":"carol","email":"carol@domus.dev","team":null}]}
EOF
echo "Command: gron /tmp/gron-debug.json | grep null"
gron /tmp/gron-debug.json | grep null
echo ""
echo "(Instantly shows: bob has no email, carol has no team)"
echo ""

# ---------------------------------------------------------------------------
echo "------------------------------------------------------------------"
echo "DRILL 3.4: CROSS-REPO ATTRIBUTE INVENTORY"
echo "yq + gron + awk across multiple repos"
echo "------------------------------------------------------------------"
echo ""
echo "Command: Compare attribute counts across domus repos"
found_repos=0
for f in ~/atelier/_bibliotheca/domus-*/docs/asciidoc/antora.yml; do
    [[ -f "$f" ]] || continue
    found_repos=1
    repo=$(basename "$(dirname "$(dirname "$(dirname "$f")")")")
    count=$(yq -o=json '.asciidoc.attributes // {}' "$f" | gron | grep -v '= {}' | wc -l)
    printf "%-30s %s attributes\n" "$repo" "$count"
done
if [[ $found_repos -eq 0 ]]; then
    echo "(No domus repos found at expected paths)"
fi
echo ""

# ---------------------------------------------------------------------------
echo "------------------------------------------------------------------"
echo "DRILL 3.5: GIT LOG → JSON → GRON → JQ"
echo "Full pipeline across tools"
echo "------------------------------------------------------------------"
echo ""
echo "Command: git log as JSON, explore with gron, summarize with jq"
git -C ~/atelier/_bibliotheca/domus-captures log --pretty=format:'{"hash":"%h","date":"%aI","subject":"%s"}' -5 2>/dev/null |
  jq -s '.' > /tmp/gron-log.json 2>/dev/null

if [[ -s /tmp/gron-log.json ]]; then
    echo "gron view:"
    gron /tmp/gron-log.json | head -10
    echo "  ..."
    echo ""
    echo "jq extraction:"
    jq -r '.[] | "\(.date | split("T")[0]) \(.subject)"' /tmp/gron-log.json
    echo ""
else
    echo "(Skipped — domus-captures not found)"
    echo ""
fi

# ---------------------------------------------------------------------------
echo "------------------------------------------------------------------"
echo "YOUR TURN - TRY THESE:"
echo "------------------------------------------------------------------"
echo ""
echo "1. Explore your nvim config as JSON:"
echo "   yq -o=json '.' ~/atelier/_projects/personal/domus-nvim/lazy-lock.json | gron | grep catppuccin"
echo ""
echo "2. Find all service ports in the cluster JSON:"
echo "   gron /tmp/gron-complex.json | grep port"
echo "   jq '.cluster.services | to_entries[] | {name: .key, port: .value.port}' /tmp/gron-complex.json"
echo ""
echo "3. Build a summary: gron counts depth, jq aggregates:"
echo "   gron /tmp/gron-complex.json | awk -F'.' '{print NF}' | sort -n | uniq -c | sort -rn"
echo ""
echo "------------------------------------------------------------------"
echo "TOOL DECISION GUIDE:"
echo "1. Don't know the shape? → gron | grep"
echo "2. Know the path, need the value? → jq '.path'"
echo "3. Input is YAML? → yq -o=json | then jq or gron"
echo "4. Need a filtered JSON subset? → gron | grep | ungron"
echo "5. Need aggregation/reshaping? → jq (always jq)"
echo "------------------------------------------------------------------"