- Shell 65.1%
- TypeScript 17.3%
- CSS 9.7%
- Pug 4.5%
- HTML 2.4%
- Other 1%
|
All checks were successful
ci / build (push) Successful in 14s
Reviewed-on: #6 |
||
|---|---|---|
| .forgejo/workflows | ||
| .vscode | ||
| brand | ||
| members | ||
| release | ||
| scripts | ||
| src | ||
| static | ||
| .gitignore | ||
| brand.lock | ||
| build.ts | ||
| deno.lock | ||
| Justfile | ||
| nginx.conf | ||
| README.md | ||
Realliance website
Live at realliance.net. The source lives on the Realliance forge, git.realliance.net/realliance/realliance.net.
Developing
Install requirements
Arch Linux users: pacman -S just deno watchexec
Running locally
# Build
just
# Build and serve locally
just serve
# Build and serve with directory watching to rebuild (recommended)
just watch
The build runs with --frozen: it uses exactly what deno.lock records and fails if an import
would change it. After changing an import, run deno cache --lock=deno.lock build.ts once and
commit the lock. The build names member images by a hash of their content, so two builds of one commit
give the same files.
scripts/deno-build.sh runs the build with the narrowest Deno permissions it needs (read this
directory, write build/, and run nothing else). Member about.toml values reach the page as data, which
pug escapes, and links must be https://. scripts/test-members.sh builds a copy with a hostile
member to check that, and CI runs it.
Brand files
Fonts, logo and favicons come from the Realliance brand. The sync script copies them into static/brand/ (never loaded from a CDN).
scripts/sync-brand.sh --tag vX.Y.Z clones a signed tag of realliance/brand, checks the signature against
brand/release-signers.*, checks every file in brand/uses.txt against the tag manifest, and writes static/brand/,
brand/map.json and brand.lock. Sources use {{brand:<logical name>}} tokens, which build.ts resolves through
brand/map.json (file names carry a content hash). scripts/sync-brand.sh --check --release verifies static/
against brand.lock and requires a release tag (CI runs it).
The image
The repo has no Dockerfile. just image (or scripts/ci.sh build) does what CI does:
scripts/ci-tools.shdownloads Deno and crane at pinned versions and checks their sha256.scripts/test-members.sh, then the frozen Deno build writesbuild/.scripts/build-image.shpacksbuild/andnginx.confinto one deterministic layer (sorted, owned by root, dated by the commit) and appends it to the pinnednginx:stable-alpinebase. It does this inside a throwaway local registry, so it needs no credentials.scripts/check-image.shchecks the result: the base's config, except port 8080 and the source and revision labels; manifest annotations that match those labels; the base's layers plus exactly one; only the site andnginx.confin it.
The result is .ci/image/oci and its digest in .ci/image/digest. The same commit gives the same
digest, given the pinned Deno, crane and base, and GNU tar, which writes the layer (the build log prints its version
next to the digest). To check a published image, check out its commit and run
scripts/check-image.sh <ref>.
scripts/build-image.sh pins the nginx base by digest. Nothing bumps it automatically:
change the digest by hand, run just image, and review the change.
CI
.forgejo/workflows/ci.yaml runs on the forge's general runner:
- every pull request runs
scripts/ci.sh buildand pushes nothing; - a push to
mainalso publishesgit.realliance.net/realliance/realliance.net:sha-<7>; - a tag
X.Y.Zalso publishes:X.Y.Z, but only for an annotated tag signed by a release signer (release/signers.ascandrelease/signers.fpr). A lightweight or unsigned tag fails the publish step before it uses any credential. The runner has no gpg, so the check isscripts/verify-release-tag.ts(Deno and openpgp.js, locked inrelease/deno.lock). Runjust test-release-taglocally after changing it; CI does not run that test.
Publishing never moves a tag. If a tag already points at another digest, the job fails with
refusing to move <tag>. Never approve workflow runs from fork pull requests.
Releasing
- Merge the PR into
main(fast-forward or squash; commits need no signature) and wait for its CI run to publishsha-<7>. - Tag the same commit with a signed tag and push it:
git tag -s 2.4.1 -m "realliance.net 2.4.1: <what changed>" origin/main && git push origin 2.4.1. - CI publishes
:2.4.1at the same digest assha-<7>. A different digest means the build is not reproducible: the job fails, and nobody deploys that build. - Each new
X.Y.Ztag deploys to galaxy automatically. The cluster runs the image pinned by digest in luma-homeops (cluster/realliance.net/home.yaml). Its Renovate rule opens a re-pin for the new tag and automerges it, and Argo rolls the site within about an hour. Push only a release tag you mean to ship. Never push tags in bulk (git push --tags): a stray local tag would publish only if signed and annotated, but treat it as live.
The release signers are the Owners and maintainers who may push [0-9]* tags. release/signers.fpr lists
their primary fingerprints and release/signers.asc their public keys (today only Chris's key). To add a
signer, add the key and fingerprint in a reviewed PR; a tag signed by anyone else does not publish.