From 76915a8e7d953ec8c2a1a5432f20ce5a4c6b6151 Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 11 May 2026 20:00:36 +0300 Subject: [PATCH 1/2] build: enforce README.md presence on every rule Adds scripts/check_readmes.sh (called from gen.sh) which fails the build if any rule directory under pkg/rules/ is missing or has an empty README.md. AGENTS.md documents the expectation for future contributors and agents. Refs SUB-7177. Signed-off-by: Ben --- .github/workflows/test.yml | 6 ++++++ AGENTS.md | 22 ++++++++++++++++++++++ gen.sh | 4 ++++ scripts/check_readmes.sh | 33 +++++++++++++++++++++++++++++++++ scripts/check_readmes_test.bats | 33 +++++++++++++++++++++++++++++++++ 5 files changed, 98 insertions(+) create mode 100644 AGENTS.md create mode 100755 scripts/check_readmes.sh create mode 100644 scripts/check_readmes_test.bats diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f2ea81a..5fa9302 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -52,6 +52,12 @@ jobs: name: codecov-umbrella fail_ci_if_error: false + - name: Install bats + run: sudo apt-get update && sudo apt-get install -y bats + + - name: Run README check tests + run: bats scripts/check_readmes_test.bats + - name: Generate Rules CRD run: make generate-rules-crd diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..3a709b6 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,22 @@ +# Agent Instructions for rulelibrary + +When you add, modify, or delete a rule under `pkg/rules/`: + +1. Each rule directory MUST contain a non-empty `README.md` that follows + the template used by sibling rules (see any existing rule's README.md + for the structure: metadata table + Description, Attack Technique, How + It Works, Investigation Steps, Remediation, False Positives). +2. If you add a new rule, generate its `README.md` in the same commit. +3. If you modify a rule's YAML (CEL expression, severity, MITRE fields, + profileDependency), update the affected sections of its `README.md` + in the same commit. +4. Do not commit a rule change without its corresponding README update — + the release build will fail. + +The release build's `gen.sh` invokes `scripts/check_readmes.sh`, which +exits non-zero if any rule under `pkg/rules/` is missing or has an empty +`README.md`. The README content is consumed downstream by the +`armo-rulelibrary` build (which embeds this repo as a submodule) and +shipped as the `documentation` field on each rule. + +See: `shared-designs-and-docs/rule-improvement-epic/rule-documentation-field-design.md` diff --git a/gen.sh b/gen.sh index 3ef0e61..17c91ae 100755 --- a/gen.sh +++ b/gen.sh @@ -49,6 +49,10 @@ if [ ! -d "$RULES_DIR" ]; then exit 1 fi +# Enforce that every rule directory has a non-empty README.md. +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +bash "$SCRIPT_DIR/scripts/check_readmes.sh" "$RULES_DIR" + # Find all YAML files in rule directories RULE_FILES=$(find "$RULES_DIR" -name "*.yaml" -type f | sort) diff --git a/scripts/check_readmes.sh b/scripts/check_readmes.sh new file mode 100755 index 0000000..4534955 --- /dev/null +++ b/scripts/check_readmes.sh @@ -0,0 +1,33 @@ +#!/usr/bin/env bash +# Verify every rule directory under the given path has a non-empty README.md. +# Used by the release build as a hard gate. + +set -euo pipefail + +RULES_DIR="${1:-pkg/rules}" + +if [ ! -d "$RULES_DIR" ]; then + echo "check_readmes: directory not found: $RULES_DIR" >&2 + exit 1 +fi + +failed=0 +while IFS= read -r -d '' rule_dir; do + readme="$rule_dir/README.md" + if [ ! -f "$readme" ]; then + echo "check_readmes: missing README.md in $(basename "$rule_dir")" >&2 + failed=1 + continue + fi + if [ ! -s "$readme" ]; then + echo "check_readmes: empty README.md in $(basename "$rule_dir")" >&2 + failed=1 + fi +done < <(find "$RULES_DIR" -mindepth 1 -maxdepth 1 -type d -name 'r[0-9]*' -print0) + +if [ "$failed" -ne 0 ]; then + echo "check_readmes: one or more rules are missing or have empty README.md" >&2 + exit 1 +fi + +echo "check_readmes: OK" diff --git a/scripts/check_readmes_test.bats b/scripts/check_readmes_test.bats new file mode 100644 index 0000000..478a9a6 --- /dev/null +++ b/scripts/check_readmes_test.bats @@ -0,0 +1,33 @@ +#!/usr/bin/env bats + +setup() { + TEST_DIR=$(mktemp -d) + export RULES_DIR="$TEST_DIR/pkg/rules" + mkdir -p "$RULES_DIR/r0001-good" "$RULES_DIR/r0002-bad" + echo "# Rule" > "$RULES_DIR/r0001-good/README.md" + # r0002-bad has no README +} + +teardown() { + rm -rf "$TEST_DIR" +} + +@test "check_readmes.sh fails when a rule directory is missing README.md" { + run bash "$BATS_TEST_DIRNAME/check_readmes.sh" "$RULES_DIR" + [ "$status" -ne 0 ] + [[ "$output" == *"r0002-bad"* ]] +} + +@test "check_readmes.sh passes when all rule directories have README.md" { + echo "# Rule 2" > "$RULES_DIR/r0002-bad/README.md" + run bash "$BATS_TEST_DIRNAME/check_readmes.sh" "$RULES_DIR" + [ "$status" -eq 0 ] +} + +@test "check_readmes.sh fails when README.md exists but is empty" { + echo "# Rule 2" > "$RULES_DIR/r0002-bad/README.md" + : > "$RULES_DIR/r0001-good/README.md" + run bash "$BATS_TEST_DIRNAME/check_readmes.sh" "$RULES_DIR" + [ "$status" -ne 0 ] + [[ "$output" == *"r0001-good"* ]] +} From 37f944853d2462f82cc19dff6e2a342622602224 Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 11 May 2026 20:06:15 +0300 Subject: [PATCH 2/2] fix(build): address code review findings on README gate - gen.sh: guard against missing scripts/check_readmes.sh path - AGENTS.md: drop broken reference to internal design doc - CI: replace unpinned apt-get bats install with pinned action Refs SUB-7177. Signed-off-by: Ben --- .github/workflows/test.yml | 2 +- AGENTS.md | 2 -- gen.sh | 4 ++++ 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5fa9302..b5b3eca 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -53,7 +53,7 @@ jobs: fail_ci_if_error: false - name: Install bats - run: sudo apt-get update && sudo apt-get install -y bats + uses: bats-core/bats-action@3.0.0 - name: Run README check tests run: bats scripts/check_readmes_test.bats diff --git a/AGENTS.md b/AGENTS.md index 3a709b6..37ef783 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -18,5 +18,3 @@ exits non-zero if any rule under `pkg/rules/` is missing or has an empty `README.md`. The README content is consumed downstream by the `armo-rulelibrary` build (which embeds this repo as a submodule) and shipped as the `documentation` field on each rule. - -See: `shared-designs-and-docs/rule-improvement-epic/rule-documentation-field-design.md` diff --git a/gen.sh b/gen.sh index 17c91ae..b2ebf38 100755 --- a/gen.sh +++ b/gen.sh @@ -51,6 +51,10 @@ fi # Enforce that every rule directory has a non-empty README.md. SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +if [ ! -f "$SCRIPT_DIR/scripts/check_readmes.sh" ]; then + echo "Error: scripts/check_readmes.sh not found relative to gen.sh" >&2 + exit 1 +fi bash "$SCRIPT_DIR/scripts/check_readmes.sh" "$RULES_DIR" # Find all YAML files in rule directories