Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 49 additions & 9 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -874,10 +874,30 @@ jobs:
- name: πŸ“‹ Check README ↔ action.yaml input/output parity
shell: bash
run: |
# Fail if any input/output declared in an action.yaml is missing from
# its README's ## Inputs / ## Outputs table. yq is preinstalled on the
# GitHub-hosted ubuntu-latest runner image.
# Bidirectional README <-> action.yaml input/output parity check:
# forward β€” every input/output declared in an action.yaml must appear
# in its README's ## Inputs / ## Outputs table; and
# reverse β€” every name in those README tables must be a declared
# input/output (catches rows left stale by a rename/removal).
# yq is preinstalled on the GitHub-hosted ubuntu-latest runner image.
status=0

# Section body between '## <heading>' and the next '## ' heading.
section() { awk -v h="$1" '/^## /{f=0} f; $0 ~ "^## " h "$" {f=1}' "$2"; }
# First-column names from the markdown table under '## <heading>'
# (skips the header row and the |---|---| separator row).
table_names() {
awk -v h="$1" '
/^## / {f=0}
$0 ~ "^## " h "$" {f=1; next}
f && /^[ \t]*\|/ {
if ($0 ~ /^[ \t]*\|[ :|-]+\|?[ \t]*$/) next
line=$0; sub(/^[ \t]*\|/,"",line); split(line,a,"|"); cell=a[1]
gsub(/[`* \t]/,"",cell)
if (cell!="" && cell!="Input" && cell!="Output" && cell!="Name") print cell
}' "$2"
}

for action_yaml in */action.yaml; do
dir="$(dirname "$action_yaml")"
readme="$dir/README.md"
Expand All @@ -886,26 +906,46 @@ jobs:
status=1
continue
fi
# README section between '## Inputs'/'## Outputs' and the next '## ' heading.
inputs_doc="$(awk '/^## Inputs/{f=1;next} /^## /{f=0} f' "$readme")"
outputs_doc="$(awk '/^## Outputs/{f=1;next} /^## /{f=0} f' "$readme")"
inputs_doc="$(section Inputs "$readme")"
outputs_doc="$(section Outputs "$readme")"
declared_in="$(yq -r '.inputs // {} | keys | .[]' "$action_yaml")"
declared_out="$(yq -r '.outputs // {} | keys | .[]' "$action_yaml")"

# forward: declared -> documented
while IFS= read -r name; do
[[ -z "$name" ]] && continue
if ! grep -qF "\`$name\`" <<<"$inputs_doc"; then
echo "::error file=$action_yaml::input '$name' is declared in action.yaml but not documented in $readme (## Inputs)"
status=1
fi
done < <(yq -r '.inputs // {} | keys | .[]' "$action_yaml")
done <<<"$declared_in"
while IFS= read -r name; do
[[ -z "$name" ]] && continue
if ! grep -qF "\`$name\`" <<<"$outputs_doc"; then
echo "::error file=$action_yaml::output '$name' is declared in action.yaml but not documented in $readme (## Outputs)"
status=1
fi
done < <(yq -r '.outputs // {} | keys | .[]' "$action_yaml")
done <<<"$declared_out"

# reverse: documented -> declared
while IFS= read -r name; do
[[ -z "$name" ]] && continue
if ! grep -qxF "$name" <<<"$declared_in"; then
echo "::error file=$readme::'$name' is documented in ## Inputs but not declared in $action_yaml"
status=1
fi
done < <(table_names Inputs "$readme")
while IFS= read -r name; do
[[ -z "$name" ]] && continue
if ! grep -qxF "$name" <<<"$declared_out"; then
echo "::error file=$readme::'$name' is documented in ## Outputs but not declared in $action_yaml"
status=1
fi
done < <(table_names Outputs "$readme")
done

if [[ "$status" -eq 0 ]]; then
echo "README parity OK: every action.yaml input/output is documented."
echo "README parity OK: every declared input/output is documented and every documented row is declared."
fi
exit "$status"

Expand Down
Loading