aboutsummaryrefslogtreecommitdiff
path: root/aux
diff options
context:
space:
mode:
Diffstat (limited to 'aux')
-rw-r--r--aux/assert-clang-format.sh0
-rwxr-xr-xaux/assert-shellcheck.sh6
-rwxr-xr-xaux/ci/ci-build.sh56
-rwxr-xr-xaux/ci/git-post-receive.sh14
-rwxr-xr-xaux/ci/git-pre-push.sh10
-rwxr-xr-xaux/ci/report.sh69
-rw-r--r--aux/guix/manifest.scm18
-rw-r--r--aux/guix/pinned-channels.scm11
-rwxr-xr-xaux/guix/with-container.sh14
-rwxr-xr-xaux/workflow/README.sh43
-rwxr-xr-xaux/workflow/TODOs.sh28
-rwxr-xr-xaux/workflow/assert-changelog.sh14
-rwxr-xr-xaux/workflow/assert-todos.sh57
-rwxr-xr-xaux/workflow/commonmark.sh17
-rwxr-xr-xaux/workflow/dist.sh28
-rw-r--r--aux/workflow/preamble.md16
-rw-r--r--aux/workflow/public.sh15
-rwxr-xr-xaux/workflow/sign-tarballs.sh17
-rw-r--r--aux/workflow/style.css46
19 files changed, 479 insertions, 0 deletions
diff --git a/aux/assert-clang-format.sh b/aux/assert-clang-format.sh
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/aux/assert-clang-format.sh
diff --git a/aux/assert-shellcheck.sh b/aux/assert-shellcheck.sh
new file mode 100755
index 0000000..334a875
--- /dev/null
+++ b/aux/assert-shellcheck.sh
@@ -0,0 +1,6 @@
+#!/bin/sh
+set -eux
+
+git ls-files -z | \
+ xargs -0 awk 'FNR==1 && /^#!\/bin\/sh$/ { print FILENAME }' | \
+ xargs shellcheck
diff --git a/aux/ci/ci-build.sh b/aux/ci/ci-build.sh
new file mode 100755
index 0000000..1c033fe
--- /dev/null
+++ b/aux/ci/ci-build.sh
@@ -0,0 +1,56 @@
+#!/bin/sh
+set -eux
+
+PACKAGE="$1"
+LOGS_DIR="$2"
+read -r _ SHA _ # oldrev newrev refname
+FILENAME="$(date -Is)-$SHA.log"
+LOGFILE="$LOGS_DIR/$FILENAME"
+
+{
+ echo "Starting CI job at: $(date -Is)"
+
+ finish() {
+ STATUS="$?"
+ printf "\n\n>>> exit status was %s\n" "$STATUS"
+ echo "Finishing CI job at: $(date -Is)"
+ cd -
+ NOTE=$(cat <<EOF
+See CI logs with:
+ git notes --ref=refs/notes/ci-logs show $SHA
+ git notes --ref=refs/notes/ci-data show $SHA
+EOF
+)
+ git notes --ref=refs/notes/ci-data add -f -m "$STATUS $FILENAME"
+ git notes --ref=refs/notes/ci-logs add -f -F "$LOGFILE"
+ git notes append -m "$NOTE"
+
+ cd -
+ if [ -f ./aux/ci/report.sh ]; then
+ sh aux/ci/report.sh "$PACKAGE"
+ rsync -avzzP public/ "/srv/http/$PACKAGE/"
+ fi
+
+ printf "\n>>>\n>>> CI logs added as Git note.\n>>>\n>>> Run status was %s" "$STATUS"
+ }
+ trap finish EXIT
+
+ unset GIT_DIR
+ REMOTE="$PWD"
+ cd "$(mktemp -d)"
+ git clone "$REMOTE" .
+ git config --global user.email git@euandre.org
+ git config --global user.name 'EuAndreh CI'
+ git fetch origin refs/notes/*:refs/notes/*
+ git annex get ||:
+
+ if [ -f aux/guix/with-container.sh ]; then
+ RUNNER='./aux/guix/with-container.sh'
+ else
+ RUNNER='sh -c'
+ fi
+
+ $RUNNER 'make clean dev-check public'
+
+ rsync -avzzP public/ "/srv/http/$PACKAGE/" --delete
+} 2>&1 | tee "$LOGFILE"
diff --git a/aux/ci/git-post-receive.sh b/aux/ci/git-post-receive.sh
new file mode 100755
index 0000000..f8986ed
--- /dev/null
+++ b/aux/ci/git-post-receive.sh
@@ -0,0 +1,14 @@
+#!/bin/sh
+set -eu
+
+for n in $(seq 0 $((GIT_PUSH_OPTION_COUNT - 1))); do
+ opt="$(eval "echo \$GIT_PUSH_OPTION_$n")"
+ if [ "$opt" = skip-ci ] || [ "$opt" = ci-skip ]; then
+ printf "\n'%s' option detected, not running ci-build.sh\n\n" "$opt"
+ exit 0
+ fi
+done
+
+PACKAGE="$(basename "$PWD" | cut -d. -f1)" # remove .git suffix
+LOGS_DIR="/opt/ci/$PACKAGE/logs"
+"/opt/ci/$PACKAGE/ci-build.sh" "$PACKAGE" "$LOGS_DIR"
diff --git a/aux/ci/git-pre-push.sh b/aux/ci/git-pre-push.sh
new file mode 100755
index 0000000..951d353
--- /dev/null
+++ b/aux/ci/git-pre-push.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+set -eux
+
+PACKAGE="$(basename "$PWD")"
+LOGS_DIR="/opt/ci/$PACKAGE/logs"
+REMOTE_GIT_DIR="/srv/git/$PACKAGE.git"
+
+ssh git.euandreh.xyz mkdir -p "$LOGS_DIR"
+scp aux/ci/ci-build.sh "git.euandreh.xyz:$(dirname "$LOGS_DIR")/ci-build.sh"
+scp aux/ci/git-post-receive.sh "git.euandreh.xyz:$REMOTE_GIT_DIR/hooks/post-receive"
diff --git a/aux/ci/report.sh b/aux/ci/report.sh
new file mode 100755
index 0000000..b82c061
--- /dev/null
+++ b/aux/ci/report.sh
@@ -0,0 +1,69 @@
+#!/bin/sh
+set -eu
+
+PROJECT_UC="$1"
+
+PASS='✅'
+FAIL='❌'
+
+mkdir -p public/ci-logs public/ci-data
+
+OUT="$(mktemp)"
+chmod 644 "$OUT"
+
+git fetch origin refs/notes/*:refs/notes/* ||:
+
+for c in $(git notes list | cut -d\ -f2); do
+ DATA="$(git notes --ref=refs/notes/ci-data show "$c")"
+ FILENAME="$(echo "$DATA" | cut -d\ -f2)"
+ echo "$DATA" > "public/ci-data/$FILENAME"
+ git notes --ref=refs/notes/ci-logs show "$c" > "public/ci-logs/$FILENAME"
+done
+
+cat <<EOF >> "$OUT"
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="UTF-8" />
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
+
+ <style>
+ pre {
+ display: inline;
+ }
+ </style>
+ </head>
+ <body>
+ <h1>
+ CI logs for $PROJECT_UC
+ </h1>
+ <ul>
+EOF
+
+for f in $(find public/ci-data/ -type f | LANG=C.UTF-8 sort -r); do
+ DATA="$(cat "$f")"
+ STATUS="$(echo "$DATA" | cut -d\ -f1)"
+ FILENAME="$(echo "$DATA" | cut -d\ -f2)"
+
+ if [ "$STATUS" = 0 ]; then
+ STATUS_MARKER="$PASS"
+ else
+ STATUS_MARKER="$FAIL"
+ fi
+
+ cat <<EOF >> "$OUT"
+ <li>
+ <a href="ci-logs/$FILENAME">
+ $STATUS_MARKER <pre>$FILENAME</pre>
+ </a>
+ </li>
+EOF
+done
+
+cat <<EOF >> "$OUT"
+ </ul>
+ </body>
+</html>
+EOF
+
+mv "$OUT" public/ci.html
diff --git a/aux/guix/manifest.scm b/aux/guix/manifest.scm
new file mode 100644
index 0000000..9d3b266
--- /dev/null
+++ b/aux/guix/manifest.scm
@@ -0,0 +1,18 @@
+(specifications->manifest
+ (map symbol->string
+ '(bash
+ coreutils
+ findutils
+ diffutils
+ grep
+ sed
+ git
+ tar
+ gzip
+ gawk
+ make
+ perl
+ shellcheck
+ gettext
+ groff
+ pandoc)))
diff --git a/aux/guix/pinned-channels.scm b/aux/guix/pinned-channels.scm
new file mode 100644
index 0000000..b026813
--- /dev/null
+++ b/aux/guix/pinned-channels.scm
@@ -0,0 +1,11 @@
+(cons*
+ (channel
+ (name 'xyz-euandreh)
+ (url "git://git.euandreh.xyz/package-repository")
+ (branch "main")
+ (introduction
+ (make-channel-introduction
+ "d749e053e6db365069cb9b2ef47a78b06f9e7361"
+ (openpgp-fingerprint
+ "5BDA E9B8 B2F6 C6BC BB0D 6CE5 81F9 0EC3 CD35 6060"))))
+ %default-channels)
diff --git a/aux/guix/with-container.sh b/aux/guix/with-container.sh
new file mode 100755
index 0000000..6561b2c
--- /dev/null
+++ b/aux/guix/with-container.sh
@@ -0,0 +1,14 @@
+#!/bin/sh
+set -eux
+
+if [ -z "${1:-}" ]; then
+ guix time-machine -C aux/guix/pinned-channels.scm -- \
+ environment -m aux/guix/manifest.scm
+elif [ "$1" = '-p' ]; then
+ guix time-machine -C aux/guix/pinned-channels.scm -- \
+ environment --pure -C -m aux/guix/manifest.scm
+else
+ guix time-machine -C aux/guix/pinned-channels.scm -- \
+ environment --pure -C -m aux/guix/manifest.scm -- \
+ sh -c "$@"
+fi
diff --git a/aux/workflow/README.sh b/aux/workflow/README.sh
new file mode 100755
index 0000000..e30344f
--- /dev/null
+++ b/aux/workflow/README.sh
@@ -0,0 +1,43 @@
+#!/bin/sh
+set -eu
+
+mkdir -p public
+
+PROJECT_UC="$1"
+PROJECT="$2"
+MAILING_LIST="$3"
+
+RELEASES_LIST="$(mktemp)"
+for version in $(git tag | perl -e 'print reverse <>'); do
+ echo "- version [$version](https://git.euandreh.xyz/$PROJECT/snapshot/$PROJECT-$version.tar.gz) ([sig](https://git.euandreh.xyz/$PROJECT/snapshot/$PROJECT-$version.tar.gz.asc)), released in $(git log -1 --format=%cd --date=short "$version")" >> "$RELEASES_LIST"
+done
+
+RELEASES="$(mktemp)"
+if [ -s "$RELEASES_LIST" ]; then
+ printf '\n# Releases\n\n' >> "$RELEASES"
+ cat "$RELEASES_LIST" >> "$RELEASES"
+fi
+
+LINKS="$(mktemp)"
+cat <<EOF > "$LINKS"
+
+# Links
+
+- [home page](https://$PROJECT.euandreh.xyz)
+- [source code](https://git.euandreh.xyz/$PROJECT/about/)
+- [bug tracking](https://$PROJECT.euandreh.xyz/TODOs.html)
+- [mailing list](https://lists.sr.ht/~euandreh/$MAILING_LIST?search=%5B$PROJECT%5D)
+- [CI logs](https://$PROJECT.euandreh.xyz/ci.html)
+- [CHANGELOG](https://$PROJECT.euandreh.xyz/CHANGELOG.html)
+EOF
+
+cat "README.md" "$LINKS" "$RELEASES" | \
+ pandoc --toc \
+ --highlight-style pygments \
+ --toc-depth=2 \
+ -s \
+ --metadata title="$PROJECT_UC - README" \
+ --metadata lang=en \
+ -r commonmark \
+ -w html \
+ > public/index.html
diff --git a/aux/workflow/TODOs.sh b/aux/workflow/TODOs.sh
new file mode 100755
index 0000000..00fef6f
--- /dev/null
+++ b/aux/workflow/TODOs.sh
@@ -0,0 +1,28 @@
+#!/bin/sh
+set -eu
+
+mkdir -p public
+
+export PROJECT_UC="$1"
+export PROJECT="$2"
+export MAILING_LIST="$3"
+
+TODOS_REGEX='s/^## (TODO|DOING|WAITING|MEETING|INACTIVE|NEXT|CANCELLED|DONE) (.*) \{#(.*?)\}$/## <a href="#\3"><span class="\1">\1<\/span> \2<\/a>\n<span class="header-anchor" id="\3">#\3<\/span>\n/'
+
+TAGS_REGEX='s/tag:([\w-]+)/<span class="tag">\1<\/span>/g'
+
+envsubst < aux/workflow/preamble.md | \
+ printf '%s\n\n%s' \
+ "$(cat -)" \
+ "$(perl -pe "$TODOS_REGEX" TODOs.md | \
+ perl -pe "$TAGS_REGEX")" | \
+ pandoc --toc \
+ --highlight-style pygments \
+ --toc-depth=2 \
+ -s \
+ --metadata title="$PROJECT_UC - TODOs" \
+ --metadata lang=en \
+ -r commonmark \
+ -w html \
+ -H aux/workflow/style.css \
+ > public/TODOs.html
diff --git a/aux/workflow/assert-changelog.sh b/aux/workflow/assert-changelog.sh
new file mode 100755
index 0000000..d39f527
--- /dev/null
+++ b/aux/workflow/assert-changelog.sh
@@ -0,0 +1,14 @@
+#!/bin/sh
+set -eu
+
+PROJECT="$1"
+
+for VVERSION in $(git tag); do
+ VERSION="${VVERSION#v}"
+ DATE="$(git log -1 --format=%cd --date=short "$VVERSION")"
+ CHANGELOG_ENTRY="# [$VERSION](https://git.euandreh.xyz/$PROJECT/commit/?id=$VVERSION) - $DATE"
+ if ! grep -qF "$CHANGELOG_ENTRY" CHANGELOG.md; then
+ echo "Missing '$CHANGELOG_ENTRY' entry from CHANGELOG.md" >&2
+ exit 1
+ fi
+done
diff --git a/aux/workflow/assert-todos.sh b/aux/workflow/assert-todos.sh
new file mode 100755
index 0000000..203d465
--- /dev/null
+++ b/aux/workflow/assert-todos.sh
@@ -0,0 +1,57 @@
+#!/bin/sh
+set -eu
+
+if git grep FIXME | grep -v '^TODOs.md' | grep -v '^aux/workflow/assert-todos.sh' | grep -v '^aux/docbook-xsl/'; then
+ echo "Found dangling FIXME markers on the project."
+ echo "You should write them down properly on TODOs.md."
+ exit 1
+fi
+
+awk -F'{#' '
+BEGIN {
+ exitstatus = 0
+ h2flag = 0
+ h2status = ""
+ prevline = ""
+ idx = 0
+ delete ids[0]
+}
+h2flag == 1 {
+ split($0, l, " ")
+ timelinestatus = l[2]
+ if (h2status != timelinestatus) {
+ print "h2/timeline status mismatch for line " NR-1
+ print prevline
+ print $0
+ exitstatus = 1
+ }
+ h2status = ""
+ h2flag = 0
+}
+
+/^## (TODO|DOING|WAITING|MEETING|INACTIVE|NEXT|CANCELLED|DONE)/ {
+ if (match($0, / \{#.*?\}$/) == 0) {
+ print "Missing ID for line " NR ":\n" $0
+ exitstatus = 1
+ }
+ id_with_prefix = substr($2, 0, length($2) - 1)
+ match(id_with_prefix, /^\w+-/)
+ id = substr(id_with_prefix, RLENGTH + 1)
+ if (id in arr) {
+ print "Duplicate ID: " id
+ exitstatus = 1
+ } else {
+ arr[id] = 1
+ }
+
+ split($0, l, " ")
+ h2status = l[2]
+ h2flag = 1
+ prevline = $0
+}
+
+
+/^# Scratch$/ {
+ exit exitstatus
+}
+' TODOs.md
diff --git a/aux/workflow/commonmark.sh b/aux/workflow/commonmark.sh
new file mode 100755
index 0000000..e9609c2
--- /dev/null
+++ b/aux/workflow/commonmark.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+set -eu
+
+mkdir -p public
+
+PROJECT_UC="$1"
+F="$2"
+
+pandoc --toc \
+ --highlight-style pygments \
+ --toc-depth=2 \
+ -s \
+ --metadata title="$PROJECT_UC - ${F%.*}" \
+ --metadata lang=en \
+ -r commonmark \
+ -w html \
+ < "$F" > "public/${F%.*}.html"
diff --git a/aux/workflow/dist.sh b/aux/workflow/dist.sh
new file mode 100755
index 0000000..0ae0ec4
--- /dev/null
+++ b/aux/workflow/dist.sh
@@ -0,0 +1,28 @@
+#!/bin/sh
+set -eu
+
+DATE="$1"
+VERSION="$2"
+VVERSION="v$2"
+PROJECT="$3"
+
+if git show "$VVERSION" 1>/dev/null 2>/dev/null; then
+ echo "Version '$VVERSION' already exists." >&2
+ exit 1
+fi
+
+if [ "$DATE" != "$(git log -1 --format=%cd --date=short HEAD)" ]; then
+ echo "Date '$DATE' is not up-to-date." >&2
+ exit 1
+fi
+
+if [ "Release $VVERSION" != "$(git log --format=%B -1 HEAD | head -n1)" ]; then
+ echo "Commit message isn't 'Release $VVERSION'." >&2
+ exit 1
+fi
+
+sh aux/workflow/assert-changelog.sh "$DATE" "$VERSION" "$PROJECT"
+
+git tag "$VVERSION"
+
+sh aux/workflow/sign-tarballs.sh "$PROJECT"
diff --git a/aux/workflow/preamble.md b/aux/workflow/preamble.md
new file mode 100644
index 0000000..7413f58
--- /dev/null
+++ b/aux/workflow/preamble.md
@@ -0,0 +1,16 @@
+# About
+
+TODOs for $PROJECT_UC.
+
+See also [$PROJECT.euandreh.xyz](https://$PROJECT.euandreh.xyz/) and [CI logs](https://$PROJECT.euandreh.xyz/ci.html).
+
+Register a new one at
+[~euandreh/$MAILING_LIST@lists.sr.ht](mailto:~euandreh/$MAILING_LIST@lists.sr.ht?subject=%5B$PROJECT%5D%20BUG%20or%20TASK%3A%20%3Cdescription%3E)
+and see [existing discussions](https://lists.sr.ht/~euandreh/$MAILING_LIST?search=%5B$PROJECT%5D).
+
+*Você também pode escrever em português*.
+
+*Vous pouvez aussi écrire en français*.
+
+*Vi povas ankaŭ skribi esperante*.
+
diff --git a/aux/workflow/public.sh b/aux/workflow/public.sh
new file mode 100644
index 0000000..4c90225
--- /dev/null
+++ b/aux/workflow/public.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+set -eu
+
+PROJECT_UC="$1"
+PROJECT="$2"
+MAILING_LIST="$3"
+
+sh aux/workflow/TODOs.sh "$PROJECT_UC" "$PROJECT" "$MAILING_LIST"
+sh aux/workflow/README.sh "$PROJECT_UC" "$PROJECT" "$MAILING_LIST"
+
+if [ -f CHANGELOG.md ]; then
+ sh aux/workflow/commonmark.sh "$PROJECT" CHANGELOG.md
+fi
+
+sh aux/ci/report.sh "$PROJECT"
diff --git a/aux/workflow/sign-tarballs.sh b/aux/workflow/sign-tarballs.sh
new file mode 100755
index 0000000..b88ff33
--- /dev/null
+++ b/aux/workflow/sign-tarballs.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+set -eu
+
+PROJECT="$1"
+
+SIGNATURES="$(git notes --ref=refs/notes/signatures/tar.gz list | cut -d\ -f2)"
+for tag in $(git tag); do
+ COMMIT="$(git rev-list -n1 "$tag")"
+ if ! echo "$SIGNATURES" | grep -qF "$COMMIT"; then
+ echo "Adding missing signature to $tag" >&2
+ git notes --ref=refs/notes/signatures/tar.gz add -f -C "$(
+ git archive --format tar.gz --prefix "$PROJECT-${tag#v}/" "$tag" |
+ gpg --output - --armor --detach-sign |
+ git hash-object -w --stdin
+ )" "$tag"
+ fi
+done
diff --git a/aux/workflow/style.css b/aux/workflow/style.css
new file mode 100644
index 0000000..d7935d0
--- /dev/null
+++ b/aux/workflow/style.css
@@ -0,0 +1,46 @@
+<style>
+ hr {
+ background-color: #ccc;
+ }
+
+ div.header-anchor {
+ opacity: 0.5;
+ }
+
+ span.tag {
+ font-family: monospace;
+ font-size: 70%;
+ background-color: lightgray;
+ padding: 3px;
+ border-radius: 5px;
+ }
+
+ /*
+ Replicate colors from:
+ https://git.euandreh.xyz/dotfiles/tree/spacemacs.el?id=fcd9f9c4ef399d45d54927382dc1cdde251ebb0a#n866
+ */
+
+ .TODO {
+ color: brown;
+ }
+
+ .DOING {
+ color: yellowgreen;
+ }
+
+ .WAITING, .MEETING {
+ color: gray;
+ }
+
+ .INACTIVE {
+ color: orange;
+ }
+
+ .NEXT {
+ color: red;
+ }
+
+ .CANCELLED, .DONE {
+ color: green;
+ }
+</style>