diff options
Diffstat (limited to 'src/infrastructure/scripts')
-rwxr-xr-x | src/infrastructure/scripts/report.sh | 209 |
1 files changed, 152 insertions, 57 deletions
diff --git a/src/infrastructure/scripts/report.sh b/src/infrastructure/scripts/report.sh index c766d41..0b63ffc 100755 --- a/src/infrastructure/scripts/report.sh +++ b/src/infrastructure/scripts/report.sh @@ -4,7 +4,7 @@ set -eu usage() { cat <<-'EOF' Usage: - report [-C REPO] -o DIRECTORY + report -o DIRECTORY [-K] [-S STEP] report -h EOF } @@ -14,8 +14,9 @@ help() { Options: - -C REPO change to REPO when doing Git operations (default: $PWD) -o DIRECTORY the directory where to place the generated files + -K keep intermediary files + -S STEP which substep of the report to perform (default: top) -h, --help show this message @@ -92,15 +93,19 @@ for flag in "$@"; do esac done -REPO="$PWD" -while getopts 'C:o:h' flag; do +KEEP_FILES=false +STEP=top +while getopts 'o:KS:h' flag; do case "$flag" in - C) - REPO="$OPTARG" - ;; o) OUTDIR="$OPTARG" ;; + K) + KEEP_FILES=true + ;; + S) + STEP="$OPTARG" + ;; h) usage help @@ -119,6 +124,7 @@ if [ -z "${OUTDIR:-}" ]; then exit 2 fi + if [ -r src/infrastructure/config/conf.env ]; then CONF=src/infrastructure/config/conf.env else @@ -129,7 +135,7 @@ fi . "$CONF" -esc() { +escape_html() { sed \ -e 's|&|\&|g' \ -e 's|<|\<|g' \ @@ -138,18 +144,93 @@ esc() { -e "s|'|\'|g" } -mkdir -p "$OUTDIR" -cd "$OUTDIR" -mkdir -p logs data -for c in $(git -C "$REPO" notes list | cut -d' ' -f2); do - git -C "$REPO" notes --ref=refs/notes/ci-data show "$c" > data/FILENAME-tmp - FILENAME="$(grep '^filename ' data/FILENAME-tmp | cut -d' ' -f2-)" - mv data/FILENAME-tmp data/"$FILENAME" - git -C "$REPO" notes --ref=refs/notes/ci-logs show "$c" > logs/"$FILENAME" -done -{ +emit_stage0_make() { + git notes list | awk -v OUT="$OUTDIR" '{ + printf "all: %s/stage0/%s\n\n", OUT, $2 + printf "%s/stage0/%s:\n", OUT, $2 + printf "\tgit notes --ref=refs/notes/ci-data show %s > $@\n\n", $2 + }' + printf 'all:\n' + printf '\tprintf "%%s\\n" "$?" | tr " " "\\n"\n' +} + +emit_stage1_make() { + awk -F/ -vCMD="'$0'" -vOUT="$OUTDIR" '{ + printf "all: %s/stage1/%s.mk\n\n", OUT, $(NF) + printf "%s/stage1/%s.mk:\n", OUT, $(NF) + printf "\t%s -o \"%s\" -S stage1-exec < %s/stage0/%s > $@\n", CMD, OUT, OUT, $(NF) + }' + printf 'all:\n' + printf '\tcat -- "%s"/stage1/*.mk\n' "$OUTDIR" +} + +stage1_exec() { + awk -vOUT="$OUTDIR" -vCMD="'$0'" ' + { d[$1] = $2 } + END { + escaped = d["filename"] + gsub(/:/, "\\:", escaped) + + gsub(/"/, "", d["duration"]) + + printf "all: %s/data/%s\n\n", OUT, escaped + printf "%s/data/%s:\n", OUT, escaped + printf "\tln -- %s/stage0/%s $@\n\n\n", OUT, d["sha"] + + printf "all: %s/logs/%s\n\n", OUT, escaped + printf "%s/logs/%s:\n", OUT, escaped + printf "\tgit notes --ref=refs/notes/ci-logs show %s > $@\n\n\n", d["sha"] + + printf "all: %s/msgs/%s\n\n", OUT, escaped + printf "%s/msgs/%s:\n", OUT, escaped + printf "\tif ! git show %s 1>/dev/null 2>&1; then \\\n", d["sha"] + printf "\t\tgit fetch origin %s; \\\n", d["sha"] + printf "\tfi\n" + printf "\tgit log -1 --format=%%B %s > $@\n\n\n", d["sha"] + + printf "all: %s/html/%s\n\n", OUT, escaped + printf "%s/html/%s: %s/msgs/%s\n", OUT, escaped, OUT, escaped + printf "\t%s -o \"%s\" -S html-item \"%s\" \"%s\" \"%s\" \"%s\" \"%s/msgs/%s\" \"%s\" > $@\n\n\n", + CMD, OUT, d["status"], d["sha"], d["filename"], d["duration"], OUT, d["filename"], CGIT_URL + } + ' +} + +emit_html_item() { + STATUS="$1" + SHA="$2" + FILENAME="$3" + DURATION="$4" + MESSAGE_F="$5" + CGIT_URL="$6" + + PASS='✅' # ✅ + WARN='🐌' # 🐌 + FAIL='❌' # ❌ + if [ "$STATUS" = 0 ]; then + if [ "$DURATION" -le 60 ]; then + STATUS_MARKER="$PASS" + else + STATUS_MARKER="$WARN" + fi + else + STATUS_MARKER="$FAIL" + fi + cat <<-EOF + <li id="$FILENAME"> + <a href="#$FILENAME"><pre>#</pre></a> + $STATUS_MARKER - <pre>${DURATION}s</pre> + <pre>(<a href="${CGIT_URL}${SHA}">commit</a>)</pre> + <a href="logs/$FILENAME"><pre>$FILENAME</pre></a> + <br /> + <code><pre>$(escape_html < "$MESSAGE_F")</pre></code> + </li> + EOF +} + +emit_html_index() { cat <<-EOF <!DOCTYPE html> <html lang="en"> @@ -212,48 +293,62 @@ done <ol> EOF + echo "$OUTDIR"/html/* | + tr ' ' '\n' | + LANG=C.UTF-8 sort -r | + xargs cat -- - PASS='✅' # ✅ - WARN='🐌' # 🐌 - FAIL='❌' # ❌ - find data/ -type f | LANG=C.UTF-8 sort -r | while read -r f; do - STATUS="$( grep '^status ' "$f" | cut -d' ' -f2- | esc)" - SHA="$( grep '^sha ' "$f" | cut -d' ' -f2- | esc)" - FILENAME="$(grep '^filename ' "$f" | cut -d' ' -f2- | esc)" - DURATION="$(grep '^duration ' "$f" | cut -d' ' -f2- | cut -d'"' -f1 | esc)" - MESSAGE="$({ - git -C "$REPO" log -1 --format=%B "$SHA" || { - git fetch origin "$SHA" - git -C "$REPO" log -1 --format=%B "$SHA" - } - } | esc)" - - if [ "$STATUS" = 0 ]; then - if [ "$DURATION" -le 60 ]; then - STATUS_MARKER="$PASS" - else - STATUS_MARKER="$WARN" - fi - else - STATUS_MARKER="$FAIL" - fi - - cat <<-EOF - <li id="$FILENAME"> - <a href="#$FILENAME"><pre>#</pre></a> - $STATUS_MARKER - <pre>${DURATION:-?}s</pre> - <pre>(<a href="${CGIT_URL}${SHA}">commit</a>)</pre> - <a href="logs/$FILENAME"><pre>$FILENAME</pre></a> - <br /> - <code><pre>$MESSAGE</pre></code> - </li> - EOF - done - - cat <<-EOF + cat <<-'EOF' </ol> </main> </body> </html> EOF -} > index.html +} + + + +case "$STEP" in + top) + for d in stages stage0 stage1 data logs html msgs; do + mkdir -p -- "$OUTDIR/$d" + done + + "$0" -o "$OUTDIR" -S stage0-make | + tee -- "$OUTDIR"/stages/stage0.mk | + make -sf- | + "$0" -o "$OUTDIR" -S stage1-make | + tee -- "$OUTDIR"/stages/stage1.mk | + make -sf- | + tee -- "$OUTDIR"/stages/stage2.mk | + make -sf- + + "$0" -o "$OUTDIR" -S html + + if [ "$KEEP_FILES" = false ]; then + for d in stages stage0 stage1 html msgs; do + rm -rf "${OUTDIR:?}/$d" + done + fi + ;; + stage0-make) + emit_stage0_make + ;; + stage1-make) + emit_stage1_make + ;; + stage1-exec) + stage1_exec + ;; + html-item) + emit_html_item "$@" + ;; + html) + emit_html_index > "$OUTDIR"/index.html + ;; + *) + printf 'Unsupported STEP type: "%s"\n\n' "$STEP" >&2 + usage >&2 + exit 2 + ;; +esac |