Files
member-console/scripts/spdx-headers.sh
T
cgalo5758 fe19ee415c Add CLA and SPDX headers, fix docs
- Pin Dockerfile to Go 1.23 to match go.mod
- Record README front-door audit findings
2026-09-07 21:32:14 -05:00

110 lines
3.9 KiB
Bash
Executable File

#!/usr/bin/env bash
#
# Stamp SPDX license headers on hand-written source files.
#
# member-console is dual-licensed: AGPL-3.0-only for everyone, or a separate
# commercial license from the copyright holder (see COMMERCIAL.md). Every
# hand-written source file carries the dual identifier so the offer is legible
# from the file itself, not only from the repository root.
#
# Covered: Go, SQL migrations and seeds, the Go HTML templates under
# internal/, and the first-party JavaScript and CSS under internal/. Not
# covered: sqlc query files (sqlc copies every comment preceding the first
# "-- name:" line into the generated Go as that query's doc comment, so a
# header there pollutes the generated code; the generated .sql.go beside each
# query file carries the header instead), the vendored browser assets listed
# below (their own licenses, see NOTICE), configuration, shell, documentation,
# images. Repository-wide coverage of those, and a check that fails on a bare
# new file, is what REUSE tooling provides; adopting it is deferred until CI
# exists (status/issues.md, "LicenseRef-Commercial has no resolvable text").
#
# sqlc rewrites its output on every run and has no option for emitting a
# header, so `make sqlc-generate` invokes this script afterwards to restore the
# headers it drops. Run `make spdx-headers` to stamp the whole tree.
#
# Usage:
# scripts/spdx-headers.sh # every tracked eligible file
# scripts/spdx-headers.sh DIR [DIR..] # every eligible file on disk under
# # DIR, including files not yet tracked
#
# Idempotent: a file whose first lines already carry an SPDX-License-Identifier
# is left untouched, so a changed identifier must be rewritten deliberately.
#
# Templates get the {{- /* */ -}} form: an HTML comment would be sent to every
# browser, and the trim markers keep the rendered output byte-identical.
set -euo pipefail
IDENTIFIER="AGPL-3.0-only OR LicenseRef-Commercial"
COPYRIGHT="2025-2026 Christian Galo"
# Third-party assets redistributed under their own licenses; see NOTICE.
VENDORED=(
internal/embeds/static/bootstrap.bundle.js
internal/embeds/static/bootstrap.css
internal/embeds/static/htmx.min.js
internal/embeds/static/sortable.min.js
)
cd "$(git rev-parse --show-toplevel)"
# Go and SQL are eligible anywhere; templates and assets only under internal/,
# which keeps archived review pages and exploration dossiers out.
eligible() {
local f="$1"
for v in "${VENDORED[@]}"; do
[ "$f" = "$v" ] && return 1
done
case "$f" in
*/queries/*.sql) return 1 ;;
*.go | *.sql) return 0 ;;
internal/*.html | internal/*.js | internal/*.css) return 0 ;;
*) return 1 ;;
esac
}
header() {
case "$1" in
*.go | *.js)
printf '// SPDX-License-Identifier: %s\n// SPDX-FileCopyrightText: %s\n\n' "$IDENTIFIER" "$COPYRIGHT"
;;
*.sql)
printf -- '-- SPDX-License-Identifier: %s\n-- SPDX-FileCopyrightText: %s\n\n' "$IDENTIFIER" "$COPYRIGHT"
;;
*.css)
printf '/* SPDX-License-Identifier: %s */\n/* SPDX-FileCopyrightText: %s */\n\n' "$IDENTIFIER" "$COPYRIGHT"
;;
*.html)
printf '{{- /* SPDX-License-Identifier: %s */ -}}\n{{- /* SPDX-FileCopyrightText: %s */ -}}\n\n' "$IDENTIFIER" "$COPYRIGHT"
;;
esac
}
if [ "$#" -gt 0 ]; then
mapfile -t candidates < <(find "$@" -type f \( -name '*.go' -o -name '*.sql' -o -name '*.html' -o -name '*.js' -o -name '*.css' \) | sed 's#^\./##' | sort)
else
mapfile -t candidates < <(git ls-files -- '*.go' '*.sql' 'internal/*.html' 'internal/*.js' 'internal/*.css')
fi
stamped=0
eligible_count=0
for f in "${candidates[@]}"; do
[ -n "$f" ] || continue
eligible "$f" || continue
eligible_count=$((eligible_count + 1))
if head -n 3 "$f" | grep -q 'SPDX-License-Identifier:'; then
continue
fi
tmp="$(mktemp)"
{
header "$f"
cat "$f"
} >"$tmp"
# Copy through rather than mv so the file keeps its original mode.
cat "$tmp" >"$f"
rm -f "$tmp"
stamped=$((stamped + 1))
done
printf 'spdx-headers: stamped %d of %d eligible files\n' "$stamped" "$eligible_count"