diff options
Diffstat (limited to 'src/infrastructure/scripts')
-rwxr-xr-x | src/infrastructure/scripts/backup.sh | 149 | ||||
-rwxr-xr-x | src/infrastructure/scripts/check.sh | 92 | ||||
-rwxr-xr-x | src/infrastructure/scripts/cicd.sh | 168 | ||||
-rwxr-xr-x | src/infrastructure/scripts/cronjob.sh | 169 | ||||
-rwxr-xr-x | src/infrastructure/scripts/deploy.sh | 72 | ||||
-rwxr-xr-x | src/infrastructure/scripts/gc.sh | 146 | ||||
-rwxr-xr-x | src/infrastructure/scripts/reconfigure.sh | 147 | ||||
-rwxr-xr-x | src/infrastructure/scripts/report.sh | 260 |
8 files changed, 0 insertions, 1203 deletions
diff --git a/src/infrastructure/scripts/backup.sh b/src/infrastructure/scripts/backup.sh deleted file mode 100755 index bea63b2..0000000 --- a/src/infrastructure/scripts/backup.sh +++ /dev/null @@ -1,149 +0,0 @@ -#!/bin/sh -set -eu - -usage() { - cat <<-'EOF' - Usage: - backup [-q] [-C COMMENT] [-x] [ARCHIVE_TAG] - backup -h - EOF -} - -help() { - cat <<-'EOF' - - - Options: - -q disable verbose mode, useful for batch sessions - -C COMMENT the comment text to be attached to the archive - -x enable checking the repository after creating the backup - -h, --help show this message - - ARCHIVE_TAG the tag used to create the new - backup (default: "manual") - - - The repository is expected to have been create with: - - $ borg init -e repokey-blake2 - - The following environment variables are expected to be exported: - - $BORG_PASSCOMMAND - $BORG_REPO - $BORG_REMOTE_PATH - - Password-less SSH access is required, usually done via adding - /root/.ssh/id_rsa.pub to the ssh remote's - $THE_REMOTE:.ssh/authorized_keys - - Root permission is also required. - - - Examples: - - Run backup from cronjob: - - $ backup - - - Run backup from cronjob: - - $ backup -q cronjob - - - Create backup with a comment, a tag, and verbose mode active, and do - verify the repository afterwards: - - $ backup -xC 'The backup has a comment' - EOF -} - - -for flag in "$@"; do - case "$flag" in - --) - break - ;; - --help) - usage - help - exit - ;; - *) - ;; - esac -done - -VERBOSE_FLAGS='--verbose --progress' -COMMENT=' ' -CHECK=false -while getopts 'qC:xh' flag; do - case "$flag" in - q) - VERBOSE_FLAGS='' - ;; - C) - COMMENT="$OPTARG" - ;; - x) - CHECK=true - ;; - h) - usage - help - exit - ;; - *) - usage >&2 - exit 2 - ;; - esac -done -shift $((OPTIND - 1)) - -ARCHIVE_TAG="${1:-manual}" - - -if [ "$(id -un)" != 'root' ]; then - printf 'This script must be run as root.\n\n' >&2 - usage >&2 - exit 2 -fi - - -run() { - STATUS=0 - set -x - # shellcheck disable=2086 - sudo -i borg create \ - $VERBOSE_FLAGS \ - --comment "$COMMENT" \ - --stats \ - --compression lzma,9 \ - "$BORG_REPO::$(hostname)-{now}-$ARCHIVE_TAG" \ - /mnt/production/ \ - /root/ \ - /home/ \ - /etc/ \ - /var/ \ - /opt/ \ - /srv/ || STATUS=$? - set +x - - if [ "$STATUS" = 0 ]; then - return 0 - elif [ "$STATUS" = 1 ]; then - printf 'WARNING, but no ERROR.\n' >&2 - return 0 - else - return "$STATUS" - fi -} - -run - -if [ "$CHECK" = true ]; then - # shellcheck disable=2086 - sudo -i borg check $VERBOSE_FLAGS --verify-data "$BORG_REPO" -fi diff --git a/src/infrastructure/scripts/check.sh b/src/infrastructure/scripts/check.sh deleted file mode 100755 index 5c63816..0000000 --- a/src/infrastructure/scripts/check.sh +++ /dev/null @@ -1,92 +0,0 @@ -#!/bin/sh -set -eu - -usage() { - cat <<-'EOF' - Usage: - check - check -h - EOF -} - -help() { - cat <<-'EOF' - - - Options: - -h, --help show this message - - - Run system sanity checks, such as email reachability, alarms - reachability, filesystem checks, etc. - - - Examples: - - Just run it - - $ check - EOF -} - - -for flag in "$@"; do - case "$flag" in - --) - break - ;; - --help) - usage - help - exit - ;; - *) - ;; - esac -done - -while getopts 'h' flag; do - case "$flag" in - h) - usage - help - exit - ;; - *) - usage >&2 - exit 2 - ;; - esac -done -shift $((OPTIND - 1)) - - -if [ "$(id -un)" != 'root' ]; then - printf 'This script must be run as root.\n\n' >&2 - usage >&2 - exit 2 -fi - - -uuid() { - od -xN20 /dev/urandom | - head -n1 | - awk '{OFS="-"; print $2$3,$4,$5,$6,$7$8$9}' -} - -for alias in abuse admin postmaster hostmaster; do - uuid | mail -s "\"$alias\" alias test from $(id -un)@$(hostname)" "$alias@$(hostname)" -done - - -PARTITIONS=' -/dev/vda3 -/dev/vdb1 -/dev/vdc1 -' -set -x - -for part in $PARTITIONS; do - btrfs scrub start -B "$part" - btrfs check --force -p "$part" -done diff --git a/src/infrastructure/scripts/cicd.sh b/src/infrastructure/scripts/cicd.sh deleted file mode 100755 index 58f4fce..0000000 --- a/src/infrastructure/scripts/cicd.sh +++ /dev/null @@ -1,168 +0,0 @@ -#!/bin/sh -set -eu - -usage() { - cat <<-'EOF' - Usage: - cicd [-n] NAME [SHA] - cicd -h - EOF -} - -help() { - cat <<-'EOF' - - - Options: - -n build the system, but don't switch to it (dry-run) - -h, --help show this message - - NAME the name of the project - SHA the repository SHA to checkout (default: main) - - - Do a CI/CD run of the project called NAME, located at - /srv/git/$NAME.git. If -n is given, only build, otherwise - also do the deploy when the build is successfull. - - A "build" consists of: - - doing a fresh clone of the project on a temporary directory; - - checkout the project to version $SHA; - - when a "manifest.scm" file exists in the root of the project, - use it to launch a containerized Guix shell; otherwise use a - fallback template for a containerized Guix shell; - - build the "dev" target of the Makefile via "make dev". - - A "deploy" consists of: - - copying the "description" metadata file to - /srv/git/$NAME.git/description, in order to update the project - repository's description; - - upgrading the "pre-receive" Git hook, so that future runs are - affected by it; - - copying the "public/" directory that the "dev" target built to - the /srv/www/s/$NAME/ directory, so that the projects "public/" - directory is accessible via the web address - "https://euandre.org/s/$NAME/". - - This command must be ran as root. - - - Examples: - - Build and deploy the "remembering" project on the default branch: - - $ sudo cicd remembering - - - Build the "urubu" project on a specific commit, but don't deploy: - - $ sudo cicd -n urubu 916dafc092f797349a54515756f2c8e477326511 - EOF -} - - -for flag in "$@"; do - case "$flag" in - --) - break - ;; - --help) - usage - help - exit - ;; - *) - ;; - esac -done - -DRY_RUN=false -while getopts 'nh' flag; do - case "$flag" in - n) - DRY_RUN=true - ;; - h) - usage - help - exit - ;; - *) - usage >&2 - exit 2 - ;; - esac -done -shift $((OPTIND - 1)) - -NAME="${1:-}" -SHA="${2:-main}" -REPO="/srv/git/$NAME.git" - -if [ -z "$NAME" ]; then - printf 'Missing NAME.\n\n' >&2 - usage >&2 - exit 2 -fi - -if [ "$(id -un)" != 'root' ]; then - printf 'This script must be run as root.\n\n' >&2 - usage >&2 - exit 2 -fi - - -set +eu -# shellcheck source=/dev/null -. /etc/rc -set -eu - - -uuid() { - od -xN20 /dev/urandom | - head -n1 | - awk '{OFS="-"; print $2$3,$4,$5,$6,$7$8$9}' -} - -tmpname() { - printf '%s/uuid-tmpname with spaces.%s' "${TMPDIR:-/tmp}" "$(uuid)" -} - -mkdtemp() { - name="$(tmpname)" - mkdir -- "$name" - printf '%s' "$name" -} - - -TMP="$(mkdtemp)" -trap 'rm -rf "$TMP"' EXIT - - -set -x -chown deployer:deployer "$TMP" -cd "$TMP" -sudo -u deployer git clone "$REPO" . -sudo -u deployer --preserve-env=GIT_CONFIG_GLOBAL git checkout "$SHA" -guix system describe - -if [ -f manifest.scm ]; then - guix shell -Cv3 -m manifest.scm -- make dev -else - guix shell -Cv3 -- make dev -fi - -if [ "$DRY_RUN" = false ]; then - # COMMENT: pre-receive is always running the previous version! - # The same is true for the reconfigure script itself. - sudo cp description "$REPO"/description - sudo cp aux/ci/git-pre-receive.sh "$REPO"/hooks/pre-receive - - sudo -u deployer rsync \ - --delete \ - --chmod=D775,F664 \ - --chown=deployer:deployer \ - --exclude 'ci/*' \ - -a \ - public/ /srv/www/s/"$NAME"/ -fi diff --git a/src/infrastructure/scripts/cronjob.sh b/src/infrastructure/scripts/cronjob.sh deleted file mode 100755 index 8abe510..0000000 --- a/src/infrastructure/scripts/cronjob.sh +++ /dev/null @@ -1,169 +0,0 @@ -#!/bin/sh -set -eu - -usage() { - cat <<-'EOF' - Usage: - cronjob COMMAND... - cronjob -h - EOF -} - -help() { - cat <<-'EOF' - - - Options: - -h, --help show this message - - COMMAND the command to be executed - - - Execute the given command, and send the output to email, with - special treatment to the status code. It kills the job it it - lasts more than one hour. - - It load the appropriate files, so that the actual cron - declaration is smaller. - - - Examples: - - Run a backup: - - $ cronjob backup -q cron - EOF -} - - -for flag in "$@"; do - case "$flag" in - --) - break - ;; - --help) - usage - help - exit - ;; - *) - ;; - esac -done - -while getopts 'h' flag; do - case "$flag" in - h) - usage - help - exit - ;; - *) - usage >&2 - exit 2 - ;; - esac -done -shift $((OPTIND - 1)) - -if [ -z "${1:-}" ]; then - printf 'Missing COMMAND.\n\n' >&2 - usage >&2 - exit 2 -fi - -if [ "$(id -un)" != 'root' ]; then - printf 'This script must be run as root.\n\n' >&2 - usage >&2 - exit 2 -fi - - -set +eu -# shellcheck source=/dev/null -. /etc/rc -set -eu - - - -epoch() { - awk 'BEGIN { srand(); print(srand()); }' -} - -now() { - date '+%Y-%m-%dT%H:%M:%S%:z' -} - - -uuid() { - od -xN20 /dev/random | - head -n1 | - awk '{OFS="-"; print $2$3,$4,$5,$6,$7$8$9}' -} - -mkstemp() { - name="${TMPDIR:-/tmp}/uuid-tmpname with spaces.$(uuid)" - touch "$name" - printf '%s' "$name" -} - -pre() { - # Same as: - # sed -u "s|^|[$CMD]: |" - # but the "-u" option is not POSIX - IFS='' - while read -r line; do - printf '[%s]: %s\n' "$CMD" "$line" - done -} - -duration() { - minutes=$((${1} / 60)) - seconds=$((${1} % 60)) - printf '%sm%ss' "$minutes" "$seconds" -} - - -CMD="$*" -HOSTNAME="$(hostname)" -FROM="cronjob@$HOSTNAME" -TIMEOUT='14400' # four hours -STATUS_F="$(mkstemp)" -OUT="$(mkstemp)" - -email() { - { - cat <<-EOF - Content-Type: text/plain; charset=UTF-8 - Content-Transfer-Encoding: 8bit - From: $FROM - To: root@localhost - Subject: (exit status: $(cat "$STATUS_F")) - $HOSTNAME: $CMD - - EOF - cat "$OUT" - } | sendmail -t -f "$FROM" - rm -f "$OUT" "$STATUS_F" -} -trap email EXIT - -{ - cat <<-EOF - Running commad: $CMD - Starting at: $(now) - - EOF - - START="$(epoch)" - STATUS=0 - timeout "$TIMEOUT" "$@" || STATUS=$? - printf '%s' "$STATUS" > "$STATUS_F" - END="$(epoch)" - DURATION_SECONDS=$((END - START)) - - cat <<-EOF - - Finished at: $(now) - Duration: $(duration "$DURATION_SECONDS") - EOF -} 2>&1 | pre | ts '%Y-%m-%dT%H:%M:%S' | tee "$OUT" >> /var/log/cronjobs.log diff --git a/src/infrastructure/scripts/deploy.sh b/src/infrastructure/scripts/deploy.sh deleted file mode 100755 index 7b3f0f4..0000000 --- a/src/infrastructure/scripts/deploy.sh +++ /dev/null @@ -1,72 +0,0 @@ -#!/bin/sh -set -eu - -usage() { - cat <<-'EOF' - Usage: - deploy - deploy -h - EOF -} - -help() { - cat <<-'EOF' - - - Options: - -h, --help show this message - - - Do a blue/green deployment of the relevant service. It makes - sure that the new service is up and running before shutting - down the old one. - - - Examples: - - Just do the deploy: - - $ deploy - EOF -} - - -for flag in "$@"; do - case "$flag" in - --) - break - ;; - --help) - usage - help - exit - ;; - *) - ;; - esac -done - -while getopts 'h' flag; do - case "$flag" in - h) - usage - help - exit - ;; - *) - usage >&2 - exit 2 - ;; - esac -done -shift $((OPTIND - 1)) - - -if [ "$(id -un)" != 'root' ]; then - printf 'This script must be run as root.\n\n' >&2 - usage >&2 - exit 2 -fi - - -: sudo herd restart a-service diff --git a/src/infrastructure/scripts/gc.sh b/src/infrastructure/scripts/gc.sh deleted file mode 100755 index e037f3c..0000000 --- a/src/infrastructure/scripts/gc.sh +++ /dev/null @@ -1,146 +0,0 @@ -#!/bin/sh -set -eu - -usage() { - cat <<-'EOF' - Usage: - gc [TYPE] - gc -h - EOF -} - -help() { - cat <<-'EOF' - - - Options: - -h, --help show this message - - TYPE what to do GC on (default: all): - - guix - - deploy - - trash - - tmpdir - - logs - - - GC the server, deleting old, unusable data, in order to free - disk space system-wide. - - - Examples: - - Just run it, for all: - - $ gc - - - Cleanup tmpdir: - - $ gc tmpdir - EOF -} - - -for flag in "$@"; do - case "$flag" in - --) - break - ;; - --help) - usage - help - exit - ;; - *) - ;; - esac -done - -while getopts 'h' flag; do - case "$flag" in - h) - usage - help - exit - ;; - *) - usage >&2 - exit 2 - ;; - esac -done -shift $((OPTIND - 1)) - - -if [ "$(id -un)" != 'root' ]; then - printf 'This script must be run as root.\n\n' >&2 - usage >&2 - exit 2 -fi - - -disk() { - df -h / /mnt/backup/ | - tail -n +2 | - awk '{ printf "%s\t%s/%s\t%s\n", $4, $3, $2, $6 }' -} - -today() { - date '+%Y-%m-%d' -} - -gc_guix() { - sudo -i guix system delete-generations 1m - sudo -i guix gc -d 1m -} - -gc_deploy() { - find /opt/deploy \ - ! -path /opt/deploy -prune \ - -type d \ - -not -name "$(today)*" \ - -exec rm -rvf "{}" ';' -} - -gc_trash() { - yes | sudo -i trash-empty -} - -gc_tmpdir() { - find "${TMPDIR:-/tmp}" -atime +10 -exec rm -vf "{}" ';' -} - -gc_logs() { - find /var/log/ci/ -atime +10 -exec rm -vf "{}" ';' -} - - -gc_all() { - gc_guix - gc_deploy - gc_trash - gc_tmpdir - gc_logs -} - - -TYPE="${1:-all}" -CMD=gc_"$TYPE" -if ! command -v "$CMD" >/dev/null; then - printf 'Invalid TYPE: "%s".\n\n' "$TYPE" >&2 - usage >&2 - exit 2 -fi - -BEFORE="$(disk)" -set -x -"$CMD" -set +x -AFTER="$(disk)" - -cat <<-EOF - Disk space: - before: $BEFORE - after: $AFTER -EOF diff --git a/src/infrastructure/scripts/reconfigure.sh b/src/infrastructure/scripts/reconfigure.sh deleted file mode 100755 index 7a3b84e..0000000 --- a/src/infrastructure/scripts/reconfigure.sh +++ /dev/null @@ -1,147 +0,0 @@ -#!/bin/sh -set -eu - -usage() { - cat <<-'EOF' - Usage: - reconfigure [-n] [-U] [SHA] - reconfigure -h - EOF -} - -help() { - cat <<-'EOF' - - - Options: - -n build the system, but don't switch to it (dry-run) - -U pull the latest channels before reconfiguring - -h, --help show this message - - SHA the repository SHA to checkout (default: main) - - - Run a "guix system reconfigure" as root via "sudo -i". If a -U - flag is given, perform a "guix pull" (in root profile) prior to - the reconfigure. The user must be able to become the "deployer" - user, either via "sudo reconfigure" or by being member of the - "become-deployer" group. - - - Examples: - - Reconfigure the system: - - $ reconfigure - - - Build the system on a custom SHA, but don't switch to it: - - $ reconfigure -n 916dafc092f797349a54515756f2c8e477326511 - - - Update and upgrade: - - $ reconfigure -U - EOF -} - - -for flag in "$@"; do - case "$flag" in - --) - break - ;; - --help) - usage - help - exit - ;; - *) - ;; - esac -done - -UPDATE=false -DRY_RUN=false -while getopts 'nUh' flag; do - case "$flag" in - n) - DRY_RUN=true - ;; - U) - UPDATE=true - ;; - h) - usage - help - exit - ;; - *) - usage >&2 - exit 2 - ;; - esac -done -shift $((OPTIND - 1)) - -# shellcheck source=/dev/null -. /etc/conf.env -SHA="${1:-main}" -REPO="/srv/git/$REPO_NAME" -NOW="$(date '+%Y-%m-%dT%H:%M:%S%:z')" -NOW_DIR=/opt/deploy/"$NOW" -NPROC=$(($(nproc) * 2 + 1)) - - -if [ "$(id -un)" != 'root' ]; then - printf 'This script must be run as root.\n\n' >&2 - usage >&2 - exit 2 -fi - - -set +eu -# shellcheck source=/dev/null -. /etc/rc -set -eu - - -if [ "$UPDATE" = true ] && [ "$DRY_RUN" = false ]; then - sudo -i guix pull -v3 -fi - -set -x -sudo -u deployer git clone --depth=1 "file://$REPO" "$NOW_DIR" -sudo -u deployer rm -f /opt/deploy/current -sudo -u deployer ln -rs "$NOW_DIR" /opt/deploy/current -cd /opt/deploy/current -sudo -u deployer git fetch --depth=1 "file://$REPO" "$SHA" -sudo -u deployer --preserve-env=GIT_CONFIG_GLOBAL git checkout "$SHA" -guix system describe - -if [ "$DRY_RUN" = true ]; then - sudo -i guix system -c$NPROC -v3 build "$PWD"/src/infrastructure/guix/system.scm -else - # COMMENT: pre-receive is always running the previous version! - # The same is true for the reconfigure script itself. - sudo cp description "$REPO"/description - sudo cp src/infrastructure/ci/git-pre-receive.sh "$REPO"/hooks/pre-receive - sudo rm -f /etc/guix/channels.scm /etc/guix/system.scm - sudo cp \ - src/infrastructure/guix/channels.scm \ - src/infrastructure/guix/system.scm \ - /etc/guix/ - - sudo -i guix system -c$NPROC -v3 reconfigure /etc/guix/system.scm - - sudo -u deployer rsync \ - --delete \ - --chmod=D775,F664 \ - --chown=deployer:deployer \ - --exclude "$CI_SUFFIX/*" \ - -a \ - /run/current-system/profile/share/doc/"$NAME"/ "$HTML_OUTDIR_TOP"/ - - deploy -fi diff --git a/src/infrastructure/scripts/report.sh b/src/infrastructure/scripts/report.sh deleted file mode 100755 index e14e40a..0000000 --- a/src/infrastructure/scripts/report.sh +++ /dev/null @@ -1,260 +0,0 @@ -#!/bin/sh -set -eu - -usage() { - cat <<-'EOF' - Usage: - report [-C REPO] -o DIRECTORY - report -h - EOF -} - -help() { - cat <<-'EOF' - - - Options: - -C REPO change to REPO when doing Git operations (default: $PWD) - -o DIRECTORY the directory where to place the generated files - -h, --help show this message - - - Gather data from Git Notes, and generate an HTML report on CI runs. - - Two refs with notes are expected: - 1. refs/notes/ci-data: contains metadata abount the CI runs, - with timestamps, filenames and exit status; - 2. refs/notes/ci-logs: contains the content of the log. - - When reconstructing the CI run, the $FILENAME present in - the refs/notes/ci-data ref names the file, and its content comes - from refs/notes/ci-logs. - - On a CI run that generated the numbers from 1 to 10, for a file named - 'my-ci-run-2020-01-01-deadbeef.log' that exited successfully, the - expected output on the target directory "public" is: - - $ tree public/ - public/ - index.html - data/ - my-ci-run-2020-01-01-deadbeef.log - ... - logs/ - my-ci-run-2020-01-01-deadbeef.log - ... - - $ cat public/data/my-ci-run-2020-01-01-deadbeef.log - 0 deadbeef my-ci-run-2020-01-01-deadbeef.log - - $ cat public/logs/my-ci-run-2020-01-01-deadbeef.log - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 - 10 - - The generated 'index.html' is a webpage with the list of all known - CI runs, their status, a link to the commit and a link to the - log file. - - To enable fetching these refs by default, do so in the git config: - - $ git config --add remote.origin.fetch '+refs/notes/*:refs/notes/*' - - - Examples: - - Generate the report on the 'www' directory: - - $ report -o www - EOF -} - - -for flag in "$@"; do - case "$flag" in - --) - break - ;; - --help) - usage - help - exit - ;; - *) - ;; - esac -done - -REPO="$PWD" -while getopts 'C:o:h' flag; do - case "$flag" in - C) - REPO="$OPTARG" - ;; - o) - OUTDIR="$OPTARG" - ;; - h) - usage - help - exit - ;; - *) - exit 2 - ;; - esac -done -shift $((OPTIND - 1)) - -if [ -z "${OUTDIR:-}" ]; then - printf 'Missing -o OUTDIR.\n\n' >&2 - usage >&2 - exit 2 -fi - -if [ -r src/infrastructure/config/conf.env ]; then - CONF=src/infrastructure/config/conf.env -else - CONF=/etc/conf.env -fi - -# shellcheck source=/dev/null -. "$CONF" - - -esc() { - sed \ - -e 's|&|\&|g' \ - -e 's|<|\<|g' \ - -e 's|>|\>|g' \ - -e 's|"|\"|g' \ - -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 - -{ - cat <<-EOF - <!DOCTYPE html> - <html lang="en"> - <head> - <meta charset="UTF-8" /> - <meta name="viewport" content="width=device-width, initial-scale=1" /> - <meta name="description" content="CI logs for $NAME" /> - <link rel="icon" type="image/svg+xml" href="/favicon.svg" /> - <title>$NAME - CI logs</title> - <style> - body { - max-width: 800px; - margin: 0 auto; - } - - code { - display: block; - margin: 1em 0em 3em 3em; - overflow: auto; - } - - pre { - display: inline; - } - - ol { - list-style-type: disc; - } - - pre, code { - background-color: #ddd; - } - - @media(prefers-color-scheme: dark) { - :root { - color: white; - background-color: black; - } - - a { - color: hsl(211, 100%, 60%); - } - - a:visited { - color: hsl(242, 100%, 80%); - } - - pre, code { - background-color: #222; - } - } - </style> - </head> - <body> - <main> - <h1> - CI logs for - <a href="$HOMEPAGE">$NAME</a> - </h1> - <ol> - EOF - - - 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> - <pre>(<a href="data/$FILENAME">data</a>)</pre> - <br /> - <code><pre>$MESSAGE</pre></code> - </li> - EOF - done - - cat <<-EOF - </ol> - </main> - </body> - </html> - EOF -} > index.html |