| author | Alan Dipert
<alan@tailrecursion.com> 2026-11-10 05:59:34 UTC |
| committer | Alan Dipert
<alan@tailrecursion.com> 2026-11-10 05:59:34 UTC |
| parent | d78609e6a831b8e74c24a06619357a7bcc98bdce |
| .forgejo/workflows/ci.yml | +34 | -13 |
| README.md | +14 | -19 |
diff --git a/.forgejo/workflows/ci.yml b/.forgejo/workflows/ci.yml index 10d5c23..82101b5 100644 --- a/.forgejo/workflows/ci.yml +++ b/.forgejo/workflows/ci.yml @@ -1,22 +1,43 @@ -name: CI +name: Check + on: push: pull_request: + workflow_dispatch: + jobs: - verify: - runs-on: ubuntu-latest + check: + runs-on: homepage + timeout-minutes: 40 steps: - - name: Checkout + - name: Checkout source and website media env: - FORGEJO_TOKEN: ${{ github.token }} + CHECKOUT_TOKEN: ${{ github.token }} + GIT_LFS_SKIP_SMUDGE: '1' run: | - set -eu - git init . - git remote add origin "https://minerva/forgejo/${{ github.repository }}.git" - auth=$(printf 'x-access-token:%s' "$FORGEJO_TOKEN" | base64 -w0) - git -c http.extraheader="AUTHORIZATION: basic $auth" fetch --depth=1 origin "${{ github.sha }}" + git init -q + git remote add origin "$GITHUB_SERVER_URL/$GITHUB_REPOSITORY.git" + auth=$(printf 'x-access-token:%s' "$CHECKOUT_TOKEN" | base64 -w0) + export GIT_CONFIG_COUNT=1 GIT_CONFIG_KEY_0=http.extraHeader + export GIT_CONFIG_VALUE_0="Authorization: Basic $auth" + git fetch --no-tags --depth=1 origin "$GITHUB_SHA" git checkout --detach FETCH_HEAD - - name: Repository sanity checks + git lfs fetch --include='md/**' --exclude='' origin HEAD + git lfs checkout md + - name: Build pinned toolchain + run: make container-image + - name: Test and verify reproducible output + run: make verify-reproducible + - name: Build website + run: make container-build + - name: Request repository publication + if: github.event_name == 'push' && github.ref == 'refs/heads/master' + env: + PUBLISH_TOKEN: ${{ secrets.PUBLISH_TOKEN }} run: | - test -s README.md || test -s README.org || true - git status --short + curl --fail-with-body --silent --show-error --config - \ + --header 'Content-Type: application/json' \ + --data "{\"ref\":\"master\",\"inputs\":{\"repository\":\"$GITHUB_REPOSITORY\",\"commit\":\"$GITHUB_SHA\",\"source_run\":\"$GITHUB_RUN_ID\"}}" \ + "$GITHUB_SERVER_URL/api/v1/repos/alan/repos-publisher/actions/workflows/publish.yml/dispatches" <<EOF + header = "Authorization: token $PUBLISH_TOKEN" + EOF diff --git a/README.md b/README.md index 7eb73f1..615adbf 100644 --- a/README.md +++ b/README.md @@ -38,6 +38,16 @@ make verify-reproducible The `Containerfile` pins both the Debian base-image digest and a dated Debian package snapshot. Update those two values together only when intentionally refreshing the toolchain. +## Continuous integration and public source + +Forgejo CI uses the pinned builder to run the tests, compare two independent builds, and build the website. It downloads only the LFS media needed by the website. Successful pushes to `master` request publication of the source at [tailrecursion.com/repos/](https://tailrecursion.com/repos/r/homepage.git/). + +```sh +git clone https://tailrecursion.com/repos/git/homepage.git +``` + +The public mirror includes LFS objects referenced by the published history. For a smaller checkout without archive media, use `GIT_LFS_SKIP_SMUDGE=1 git clone ...`, followed by `git lfs pull --include='md/**' --exclude=''` when building the website. Source publication and website deployment are separate: CI does not run `make deploy`. + ## Local fallback The host build is optional. It requires `cmark-gfm`, Python 3.11 or newer, rsync, Make, and Git: @@ -82,19 +92,9 @@ git lfs fsck The DreamHost upstream uses Git LFS's pure-SSH transport. Maintainer remotes must use standard `ssh://user@host/absolute/path` syntax; a colon between the host and absolute path prevents Git LFS from identifying the endpoint. -Preservation-only material lives under `archive/`, outside the generated -website. `archive/techworks/` holds event media and source snapshots; -`archive/open-source/` holds complete repository and gist bundles; and -`archive/forums/` holds repository-only captures of the `wooby` accounts on -Hacker News, Slashdot, and Halfbakery. ProblemScan and recovered personal-site -history have their own adjacent directories. +Preservation-only material lives under `archive/`, outside the generated website. `archive/techworks/` holds event media and source snapshots; `archive/open-source/` holds complete repository and gist bundles; and `archive/forums/` holds repository-only captures of the `wooby` accounts on Hacker News, Slashdot, and Halfbakery. ProblemScan and recovered personal-site history have their own adjacent directories. -Verify the complete corpus with `make container-archive-audit` (or -`make archive-audit` when FFmpeg and Poppler are installed locally). Refresh -checksums after an intentional capture with `make archive-checksums`. To -prepare a checksummed recovery directory containing Git history, LFS objects, -repository bundles, and preserved files, run -`make archive-export DEST=/absolute/path`. +Verify the complete corpus with `make container-archive-audit` (or `make archive-audit` when FFmpeg and Poppler are installed locally). Refresh checksums after an intentional capture with `make archive-checksums`. To prepare a checksummed recovery directory containing Git history, LFS objects, repository bundles, and preserved files, run `make archive-export DEST=/absolute/path`. Network capture is always explicit and resumable: @@ -109,11 +109,6 @@ make archive-fetch-open-source-evidence make archive-checksums ``` -The maximum-preservation Git corpus is several gigabytes. Git bundles, WARCs, -release archives, and large media below `archive/` use Git LFS. A metadata-only -checkout can skip automatic LFS downloads with `GIT_LFS_SKIP_SMUDGE=1`. +The maximum-preservation Git corpus is several gigabytes. Git bundles, WARCs, release archives, and large media below `archive/` use Git LFS. A metadata-only checkout can skip automatic LFS downloads with `GIT_LFS_SKIP_SMUDGE=1`. -The Archive.org fetch maps every archive link in public Markdown to a local -WARC response; linked book items retain their public pages and metadata, not -restricted book files. The gist-footprint fetch is resumable and records API -context for all inventoried gists or selected `--gist-id` values. +The Archive.org fetch maps every archive link in public Markdown to a local WARC response; linked book items retain their public pages and metadata, not restricted book files. The gist-footprint fetch is resumable and records API context for all inventoried gists or selected `--gist-id` values.