#!/bin/sh # Make the wiki repository of this repo hold exactly the converter output. # # wiki-push.sh # # Environment: # WIKI_TOKEN token with write access to the wiki (required) # GITHUB_SERVER_URL set by the runner; GITHUB_REPOSITORY likewise # WIKI_REMOTE overrides the wiki clone URL (the tests point it at a local repository) # # The wiki is a mirror, never a source: every file in it is replaced by the converter output, so # a page the converter no longer produces disappears. Afterwards the working tree minus .git/ and # the output directory are compared, and any difference fails the script before anything is # pushed. An unchanged result ends with exit 0 and no commit. set -eu out="${1:?usage: wiki-push.sh }" version="${2:?usage: wiki-push.sh }" if [ -z "${WIKI_TOKEN:-}" ]; then echo "ERROR WIKI_TOKEN is empty: the wiki mirror needs a token that may push to the wiki repository." >&2 echo " The job token (gitea.token) is used with 'permissions: wiki: write'; if Gitea still refuses it," >&2 echo " the repository's Actions settings cap the token, or the operator adds a secret with write access." >&2 exit 1 fi [ -f "$out/Home.md" ] || { echo "ERROR $out/Home.md is missing - not a converter output" >&2; exit 1; } server="${GITHUB_SERVER_URL:-}" repo="${GITHUB_REPOSITORY:-}" remote="${WIKI_REMOTE:-${server}/${repo}.wiki.git}" api="${server}/api/v1/repos/${repo}" # The token travels in a header, not in the URL, so it appears in no git message or process list. auth="Authorization: Basic $(printf 'wiki-mirror:%s' "$WIKI_TOKEN" | base64 | tr -d '\n')" git_remote() { git -c "http.extraheader=${auth}" "$@"; } work="$(mktemp -d)" trap 'rm -rf "$work"' EXIT wiki="$work/wiki" if ! git_remote clone -q "$remote" "$wiki" 2>"$work/clone.err"; then echo "Cloning ${remote} failed:" cat "$work/clone.err" # A wiki that has never had a page has no repository yet; the first page created through # the API brings it into existence. echo "Creating the first page through the API to bring the wiki repository into existence." content="$(base64 < "$out/Home.md" | tr -d '\n')" jq -n --arg title Home --arg content "$content" --arg message "Mirror docs at v${version}" \ '{title: $title, content_base64: $content, message: $message}' > "$work/first-page.json" status="$(curl -sS -o "$work/first-page.out" -w '%{http_code}' -X POST "${api}/wiki/new" \ -H "Authorization: token ${WIKI_TOKEN}" -H 'Content-Type: application/json' \ --data-binary @"$work/first-page.json")" case "$status" in 2??) ;; *) echo "ERROR the API refused the first page (HTTP ${status}):" >&2 cat "$work/first-page.out" >&2 exit 1 ;; esac git_remote clone -q "$remote" "$wiki" fi find "$wiki" -mindepth 1 -maxdepth 1 ! -name .git -exec rm -rf {} + cp -R "$out"/. "$wiki"/ git -C "$wiki" add -A if ! diff -r -x .git "$out" "$wiki" > "$work/diff.txt"; then echo "ERROR the wiki working tree differs from the converter output after copying:" >&2 cat "$work/diff.txt" >&2 exit 1 fi if git -C "$wiki" diff --cached --quiet; then echo "Wiki already matches v${version}" exit 0 fi git -C "$wiki" -c user.name='Wiki Mirror' -c user.email='wiki-mirror@noreply.invalid' \ commit -q -m "Mirror docs at v${version}" git_remote -C "$wiki" push -q origin HEAD echo "Wiki now mirrors v${version}"