All checks were successful
standards workspaces build + test / which workspaces this change touches (pull_request) Successful in 7s
standards workspaces build + test / macOS energy backends (pull_request) Has been skipped
repository checks / lockfiles, advisories, tests in CI, workflow hygiene, spec and section references, public text (pull_request) Successful in 2m30s
Both checks skipped wai/extensions/oer-receipts.md, wai/wai-rs/src/oer.rs and wai/oer-conformance/ as settled text "which no change may edit". OER/2's minor version 1 (#542) edits all three, and its new text would have gone unchecked. Every one of those files passes both checks, at main and at #544's head, so nothing needed the exclusion: it is gone, and a change to them is checked as a change to any other file is. Co-Authored-By: Claude Opus 5.5 <[email protected]>
136 lines
5 KiB
Shell
Executable file
136 lines
5 KiB
Shell
Executable file
#!/usr/bin/env bash
|
|
#
|
|
# check-public-names.sh
|
|
#
|
|
# Holds WAI's public text to its naming rule: it names no company, vendor,
|
|
# customer or commercial product. Standards, standards bodies, protocols,
|
|
# papers and open-source projects may be named, factually.
|
|
#
|
|
# The patterns are NOT in this repository. They are read from the
|
|
# environment variable WAI_NAME_DENYLIST: newline-separated POSIX extended
|
|
# regular expressions, matched case-sensitively (write `[Ff]oo` where both
|
|
# cases matter). In CI the variable comes from a forge Actions secret of the
|
|
# same name; locally, export it from a private file before committing:
|
|
#
|
|
# WAI_NAME_DENYLIST="$(cat /path/to/private/patterns)" scripts/check-public-names.sh
|
|
#
|
|
# A public list would itself publish the names it exists to keep out.
|
|
#
|
|
# Scope: the tracked files under wai/ with the extensions .md .rs .toml .py
|
|
# .sh .mjs .js .json .html .css .ttl .h .c .txt, and wai/'s .gitignore files;
|
|
# or, when files are given as arguments, those files (the self-test,
|
|
# scripts/test-public-text-checks.sh, uses this), each a path relative to the
|
|
# directory the script is run from, or absolute. No file is excluded: the
|
|
# OER/2 documents and corpus once were, as settled text, until a minor version
|
|
# edited them; they pass, and a change to them is checked like any other.
|
|
#
|
|
# Opt-out, for a functional identifier only (a model-hub id a tool defaults
|
|
# to, a repository URL, an OS API name, a security advisory id, a capability
|
|
# string): put `allow-name: <reason>` on the same line, in a comment of the
|
|
# file's own syntax (`<!-- allow-name: reason -->`, `// allow-name: reason`,
|
|
# `# allow-name: reason`). The reason is required: it must contain a letter or
|
|
# a digit. Prose around such an identifier describes the standard or the
|
|
# function, not the owner.
|
|
#
|
|
# Exit status: 0 clean; 1 a hit; 2 WAI_NAME_DENYLIST unset or empty, a pattern
|
|
# grep cannot compile, a file given that is not a readable regular file (each
|
|
# such file is named), or any other grep error. The check never reads an error
|
|
# as "clean".
|
|
|
|
set -euo pipefail
|
|
|
|
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
# The files given as arguments are paths from the caller's directory: remember it
|
|
# before moving to the repository's root, where the default scope is listed.
|
|
CALLER_DIR="$(pwd)"
|
|
cd "$REPO_ROOT"
|
|
|
|
if [ -z "${WAI_NAME_DENYLIST:-}" ]; then
|
|
echo "WAI_NAME_DENYLIST is not set: nothing to check against (see the header of $0)" >&2
|
|
exit 2
|
|
fi
|
|
|
|
patterns="$(mktemp)"
|
|
out="$(mktemp)"
|
|
trap 'rm -f "$patterns" "$out"' EXIT
|
|
printf '%s\n' "$WAI_NAME_DENYLIST" | grep -v '^[[:space:]]*$' > "$patterns" || true
|
|
if [ ! -s "$patterns" ]; then
|
|
echo "WAI_NAME_DENYLIST holds no pattern" >&2
|
|
exit 2
|
|
fi
|
|
# Compile every pattern once before scanning. grep exits 1 when nothing matches
|
|
# and 2 on an error; only 0 and 1 mean the patterns are usable. grep's message
|
|
# is suppressed: it could quote a private pattern.
|
|
set +e
|
|
grep -E -f "$patterns" /dev/null >/dev/null 2>&1
|
|
rc=$?
|
|
set -e
|
|
if [ $rc -gt 1 ]; then
|
|
echo "::error::WAI_NAME_DENYLIST holds a pattern grep cannot compile (grep exit $rc); nothing was checked" >&2
|
|
exit 2
|
|
fi
|
|
|
|
files=()
|
|
if [ $# -gt 0 ]; then
|
|
for f in "$@"; do
|
|
case "$f" in
|
|
/*) files+=("$f") ;;
|
|
*) files+=("$CALLER_DIR/$f") ;;
|
|
esac
|
|
done
|
|
else
|
|
while IFS= read -r f; do
|
|
files+=("$f")
|
|
done < <(git ls-files 'wai/*.md' 'wai/*.rs' 'wai/*.toml' 'wai/*.py' 'wai/*.sh' 'wai/*.mjs' 'wai/*.js' \
|
|
'wai/*.json' 'wai/*.html' 'wai/*.css' 'wai/*.ttl' 'wai/*.h' 'wai/*.c' 'wai/*.txt' \
|
|
'wai/*.gitignore' 'wai/*.wgsl')
|
|
fi
|
|
if [ ${#files[@]} -eq 0 ]; then
|
|
echo "::error::no file to check" >&2
|
|
exit 2
|
|
fi
|
|
|
|
# A file grep cannot read makes it exit 2 with the whole list unchecked; name each
|
|
# such file instead of reporting a bare grep failure. File names are not private.
|
|
unreadable=0
|
|
for f in "${files[@]}"; do
|
|
if [ ! -f "$f" ] || [ ! -r "$f" ]; then
|
|
echo "::error::not a readable file: $f" >&2
|
|
unreadable=$((unreadable + 1))
|
|
fi
|
|
done
|
|
if [ $unreadable -gt 0 ]; then
|
|
echo "::error::$unreadable of ${#files[@]} files given cannot be read; nothing was checked" >&2
|
|
exit 2
|
|
fi
|
|
|
|
set +e
|
|
grep -HnE -f "$patterns" -- "${files[@]}" > "$out" 2>/dev/null
|
|
rc=$?
|
|
set -e
|
|
if [ $rc -gt 1 ]; then
|
|
echo "::error::grep failed (exit $rc) while scanning; nothing was checked" >&2
|
|
exit 2
|
|
fi
|
|
|
|
hits=0
|
|
while IFS= read -r line; do
|
|
content="${line#*:}"
|
|
content="${content#*:}"
|
|
if printf '%s' "$content" | grep -qE 'allow-name:[[:space:]]*[[:alnum:]]'; then
|
|
continue
|
|
fi
|
|
# Print the location only: the matched text may be a name the list keeps private.
|
|
if [ $hits -eq 0 ]; then
|
|
echo "::error::public text names a company, vendor, customer or product (patterns: WAI_NAME_DENYLIST)"
|
|
fi
|
|
echo "${line%%:*}:$(printf '%s' "${line#*:}" | cut -d: -f1)"
|
|
hits=$((hits + 1))
|
|
done < "$out"
|
|
|
|
if [ $hits -gt 0 ]; then
|
|
echo "Fix: name the standard, the standards body, the open-source project or the function instead;"
|
|
echo "for a functional identifier, mark the line with allow-name: <reason>."
|
|
exit 1
|
|
fi
|
|
echo "public-name check: clean (${#files[@]} files)"
|