Перейти до вмісту

The public snapshot

Checklist: publishing-checklist.md

Tabula is published at tabula-cms/tabula. That repository is not this one made public: it is produced from this repository’s tree as a fresh history — one commit, no past — and then lives on its own. This repository stays private as the first installation’s development and deployment repository.

Why a fresh history rather than git filter-repo: the old commits carry the first installation’s content from before the database (data/*.json, statute and council PDFs, photos), its name in every other file, and migration 0013 with its texts. A filtered history has to find every one of them; a fresh one never had them. Authorship and blame of the old commits are the price, and stay here.

Path Why
docs/audits/ Reviews of the first installation’s site; they quote its content, pages and addresses.
docs/design/ The design hand-off drawn for the first installation (its name, texts, photos).
.github/workflows/deploy-prod.yml Continuous deploy of one installation: its server, its secrets, its prod branch.
.github/workflows/monitor.yml Uptime and certificate check of that installation’s domain.
.github/workflows/guard-prod-merge.yml Guards the prod branch that only deploy-prod.yml deploys from.
.github/workflows/cleanup-images.yml Prunes the prod-<sha> images only deploy-prod.yml publishes, and needs the Admin role on that package.

Everything else ships, including:

  • DEPLOYMENT.md — written with placeholders; it describes the four workflows above as what an installation with its own deployment repository sets up, and says they are not in the public repository.
  • scripts/deploy-env.sh and its test — generic (quotes one .env line), and a deployment repository sources it.
  • docs/issues/** — the specs, scrubbed of the first installation’s name, domain and city. Their references to docs/audits/ and docs/design/ stay as the record of where a decision came from; those files are here, not there.
  • Migrations 0006-menus.sql and 0009-albums.sql as they are. Their comments and their legacy guard mention the first installation (its SITE_SLUG, its album’s slug and title), and they cannot change: their checksums are recorded in every installation’s database, and in production a changed applied file stops the server (src/db/migrate.js, writing-a-migration.md). test/neutralTemplate.test.js exempts exactly these two files.

Not in the snapshot because it is not in the tree any more: migration 0013-seed-original-site-texts.sql (the first installation’s texts — already in its database; the runner ignores an applied file that is gone, test/dbMigrateMissingFile.test.js), the one-off legacy import (src/db/importLegacy.js, src/db/registerFile.js, src/db/pagesSeed.js, scripts/import-legacy.js) and public/images/emblema.jpg.

  • The full history, and with it every file above.
  • The four deploy workflows, run from this repository with its variables (APP_DIR, SITE_DOMAIN, SITE_SLUG) and secrets — DEPLOYMENT.md is its runbook.
  • docs/audits/ and docs/design/.
  • Its own values: domain, directory, SITE_SLUG, mail — in GitHub variables and secrets and in its database, never in the tree.

Its running site does not change with the snapshot: its texts are in its database, its slug, cookie and archive names come from its own SITE_SLUG, and its deploy names the image after this repository (github.repository).

From a clean checkout of the commit to publish (after the PR is merged and CI is green):

Terminal window
COMMIT=<sha> # the commit being published
OUT=../tabula-public # an empty directory outside this repository
mkdir "$OUT"
git archive "$COMMIT" | tar -x -C "$OUT" # tracked files only: no .env, data-*, node_modules
cd "$OUT"
rm -rf docs/audits docs/design \
.github/workflows/deploy-prod.yml .github/workflows/monitor.yml \
.github/workflows/guard-prod-merge.yml .github/workflows/cleanup-images.yml

Check it before the first commit:

Terminal window
# the first installation's words — each split in two quoted halves the shell joins back, so this
# page does not match itself; expect only the two frozen migrations
git grep --no-index -il -e 'koro''liov' -e 'Корол''ьов' -e 'Жито''мир' -e 'li''cey' .
npm ci && NODE_ENV=test npm test && npm run lint && npm run format:check

Then one commit and the first push:

Terminal window
git init -b main
git add -A
git commit -m "Initial public release of Tabula"
gitleaks detect --source . --log-opts="--all" --redact # the new history, before it is public
git remote add origin git@github.com:tabula-cms/tabula.git
git push -u origin main

The remaining steps — the first release tag, the package’s visibility, branch and tag protection, private vulnerability reporting, a walk-through on a throwaway server — are in publishing-checklist.md, sections 6–8.

The two repositories then move independently. How later changes travel between them (a pull of the public main into this repository’s develop, or the other way round) is decided with the first change that needs it, and recorded here.