builds.parquet carried each build's reason, and the reasons private and removed said when a repo went private or away. The exports now say push, or other for everything else; the lake keeps the real reason. lib/insights.ts and the README also say what happens to a repo's facts when it goes public again: they are published with it, from while it was private too, as its whole history is then. Scenario: the lake has private and removed, the exports only push and other.
- commit
- 43f0cccc60bb3c7c724c54b683f5b1a2feb998e8
- parent
- 0573918c003ef590d27ecf8b263d254e423aa824
- author
- cat <admin@dev.site>
- ci
- ✓ passed in 158s, signed by cat
- kind
- feat risk score 1.9 of 3, Jev's estimate
- review
- #30 Security: sign-in, invites, owner pages, lake, caps and the edge
ci attestation
forge-attestation 1 type ci commit 43f0cccc60bb3c7c724c54b683f5b1a2feb998e8 tree 4f974807cf02ffdd39c05ba26a97b8c852333e3d script .forge/ci 8d2000a416f8160bcf710d98b72af9eb76287f58 result pass exit 0 started 2026-10-19T07:55:30Z duration 158s runner (not shown here; refs/notes/ci has it) system Darwin 25.5.0 arm64 env host log sha256:10a4b062811e966fdb94e6838f97323ec073a6c50f10ed9f44d089afbc8116ae 323 lines |pushed wip/i18n |a03c9af running .forge/ci: greet.sh: say what it is | | sh: /bin/sh | | ok greet |a03c9af pass in 0s, signed |pushed main |remote: review #4: /dami/greet/reviews/4/ |pushed wip/i18n |a9d186f running .forge/ci: wave at the world | | sh: /bin/sh | | FAIL greet : got 'hello, world o/', want 'hello, world' |a9d186f fail in 0s, signed |forge: 1 commit(s) did not pass |remote: review #6: /dami/greet/reviews/6/ |pushed ana/wave |fa42011 running .forge/ci: update the test for the wave | | sh: /bin/sh | | ok greet |fa42011 pass in 0s, signed |remote: review #6: /dami/greet/reviews/6/ |pushed ana/wave |warning: You appear to have cloned an empty repository. |site home: deployed aebef68 -> /sites/ana/dotfiles/home/ |created ana/notes |remote: review #1: /ana/notes/reviews/1/ |pushed ana/todo |landing #1 A todo list: ana/todo -> main |debd0fb running .forge/ci: web, server and Python versions of greet | | sh: /bin/sh | | ok greet |debd0fb pass in 0s, signed |pushed main |98ef3b8 running .forge/ci: messages: notes for the later regions | | sh: /bin/sh | | ok greet |98ef3b8 pass in 0s, signed |remote: review #7: /dami/greet/reviews/7/ |pushed dami/regions |created dami/forge |warning: You appear to have cloned an empty repository. |site guide: mkdir -p guide/fonts && cp site/assets/fonts/*.woff2 guide/fonts/ |site guide: deployed d6e2009 -> /sites/dami/forge/guide/ |(node:73466) ExperimentalWarning: stripTypeScriptTypes is an experimental feature and might change at any time |(Use `node --trace-warnings ...` to show where the warning was created) |built ana/dotfiles in 1s -> /var/folders/b4/mv8w4c8j0zj0_mldppxdbdw00000gn/T/forge-ci.Z7x7e8/wt/demo/root/.forge/www |(node:73643) ExperimentalWarning: stripTypeScriptTypes is an experimental feature and might change at any time |(Use `node --trace-warnings ...` to show where the warning was created) |built ana/notes in 1s -> /var/folders/b4/mv8w4c8j0zj0_mldppxdbdw00000gn/T/forge-ci.Z7x7e8/wt/demo/root/.forge/www |(node:73830) ExperimentalWarning: stripTypeScriptTypes is an experimental feature and might change at any time |(Use `node --trace-warnings ...` to show where the warning was created) |built dami/forge in 0s -> /var/folders/b4/mv8w4c8j0zj0_mldppxdbdw00000gn/T/forge-ci.Z7x7e8/wt/demo/root/.forge/www |(node:74010) ExperimentalWarning: stripTypeScriptTypes is an experimental feature and might change at any time |(Use `node --trace-warnings ...` to show where the warning was created) |built dami/greet in 1s -> /var/folders/b4/mv8w4c8j0zj0_mldppxdbdw00000gn/T/forge-ci.Z7x7e8/wt/demo/root/.forge/www |(node:74752) ExperimentalWarning: stripTypeScriptTypes is an experimental feature and might change at any time |(Use `node --trace-warnings ...` to show where the warning was created) |built - in 0s -> /var/folders/b4/mv8w4c8j0zj0_mldppxdbdw00000gn/T/forge-ci.Z7x7e8/wt/demo/root/.forge/www |235 of 235 pages render the same without 11ty |guide: 8 files, links ok |ok
Signature: good, cat
| M | README.md | 5 | ++++- |
| M | lib/ | 10 | ++++++++-- |
| A | test/ | 23 | +++++++++++++++++++++++ |
@@ -895,7 +895,10 @@ page and exports are in its pages in the private root, which `forge lake`
895895 keeps fresh the same way, for its readers only (see [Private896896 pages](#private-pages)); the mirror never sees them. Making a repo private897897 removes the forge's exports from `www` at once; the next run writes them898-without it.898+without it. Making it public again publishes its facts from while it was899+private as well, as its whole history becomes public then. The builds900+exports give a build's reason as `push` or `other`, since the others would901+say when a repo went private or away.899902 900903 The page has no query console. [DuckDB-Wasm](https://duckdb.org/docs/api/wasm/overview)901904 could run SQL over those files in the browser, but its build is 34.2 MiB@@ -9,7 +9,13 @@
99 // whose readers alone see them. publishInsights also puts them straight into1010 // the live pages after each run, since the pages fetch them and need no1111 // rebuild. The forge's cover public repos only: a private repo's facts are12-// in no public export.12+// in no public export. A repo made public again publishes its facts from13+// while it was private too, as it publishes all of its history then (the14+// secret check of ssh public reads every commit first); a removed one's15+// leave the lake (forge repo rm, lib/lake.ts forget), so a new repo of the16+// same name starts with none. A build's reason is "push" or "other" in the17+// exports: the others (private, removed, profile...) would say when a repo18+// went private or away.1319 import fs from 'node:fs';1420 import path from 'node:path';1521 import { listRepos } from './lake-sources.ts';@@ -94,7 +100,7 @@ async function exportScope(lake: Lake, s: Scope, publicRepos: string[]): Promise
94100 await lake.run(`COPY (${sql}) TO ${lit(path.join(tmp, file))} (FORMAT parquet, COMPRESSION zstd)`);95101 };96102 await copy('events.parquet', `SELECT t, repo, type, "user", review, refs, ms, rendered FROM lake.events WHERE ${s.where} ORDER BY t`);97- await copy('builds.parquet', `SELECT id, "at", code, reason, scope, ms_total, ms_data, ms_render, rss_mb, written, linked FROM lake.builds WHERE ${s.builds} ORDER BY "at"`);103+ await copy('builds.parquet', `SELECT id, "at", code, CASE reason WHEN 'push' THEN 'push' ELSE 'other' END AS reason, scope, ms_total, ms_data, ms_render, rss_mb, written, linked FROM lake.builds WHERE ${s.builds} ORDER BY "at"`);98104 await copy('reviews.parquet', `99105 SELECT repo, review, kind, ts, "user", rev, sha, base, tree, branch, title, NULL::BOOLEAN AS observed FROM lake.reviews WHERE ${s.where}100106 UNION ALL SELECT repo, review, kind, ts, "user", NULL, sha, NULL, NULL, NULL, NULL, observed FROM lake.review_ends WHERE ${s.where}@@ -0,0 +1,23 @@
1+# The builds.parquet exports say why a build ran only as push or other:2+# the lake keeps the real reason (private, removed, motd...), which would3+# say when a repo went private or away.4+. "$(dirname "$0")/../lib.sh"5+user dami6+repo dami/open7+clone dami dami/open "$T/w/open"8+at "$T/w/open" commit "first"9+ok push_as dami "$T/w/open" origin main10+FORGE_BUILD_REASON=push ok forge build dami/open11+FORGE_BUILD_REASON=private ok forge build -12+FORGE_BUILD_REASON=removed ok forge build -13+ok forge lake14+eq "$(lq "SELECT string_agg(DISTINCT reason, ' ' ORDER BY reason) FROM builds")" "private push removed"15+pq() { (cd "$T_HOME" && node --input-type=module -e "16+import { DuckDBInstance } from '@duckdb/node-api';17+const db = await DuckDBInstance.create(':memory:');18+const c = await db.connect();19+const r = await c.runAndReadAll(\"SELECT string_agg(DISTINCT reason, ' ' ORDER BY reason) FROM read_parquet('\" + process.argv[1] + \"')\");20+console.log(r.getRowsJson()[0][0] ?? '');21+" "$1"); }22+eq "$(pq "$FORGE_WWW/insights/builds.parquet")" "other push"23+eq "$(pq "$FORGE_WWW/dami/open/insights/builds.parquet")" "push"