@intentius/behold 0.24.0 → 0.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +100 -0
- package/dist/cli.js +2088 -473
- package/package.json +1 -1
- package/web/app.js +101 -2
- package/web/history-picker.js +85 -0
- package/web/history-picker.test.js +77 -0
- package/web/index.html +35 -0
- package/web/terragucci-estate.js +328 -0
- package/web/terragucci-estate.test.js +114 -0
- package/web/terragucci-lifecycle.js +143 -0
- package/web/terragucci-lifecycle.test.js +60 -0
- package/web/terragucci-progress.js +127 -0
- package/web/terragucci-progress.test.js +59 -0
- package/web/terragucci-timeline.js +118 -0
- package/web/terragucci-timeline.test.js +56 -0
package/AGENTS.md
CHANGED
|
@@ -78,6 +78,68 @@ and none is the checkout's git remote) adds two reads, in
|
|
|
78
78
|
"terragucci-report"}`. `?fresh=1` skips the 30 s cache.
|
|
79
79
|
- `GET /api/terragucci/file?key=<key>`: one report file from the source,
|
|
80
80
|
sandboxed.
|
|
81
|
+
- `GET /api/terragucci/timeline?root=<path>&limit=<n>` (#506): terragucci's
|
|
82
|
+
audit record (`audit.jsonl` at the top of the prefix, one GET) as `{source,
|
|
83
|
+
project, validation, read, record: {key, present}, absent?, files, root?,
|
|
84
|
+
total, limit, entries[]}`, newest first, 200 by default and 1000 at most.
|
|
85
|
+
An entry is `{id, kind, at, who, what, wave?, digest, result, roots[], run:
|
|
86
|
+
{commit?, job_url?, run_id?, pull_request?, report?}, evidence, detail?}`;
|
|
87
|
+
`run.report` opens at `files` + the key. An approval takes the roots and
|
|
88
|
+
report of its wave's other entries (same gate and digest). No
|
|
89
|
+
`audit.jsonl` is `present: false` plus an `absent` sentence, never an
|
|
90
|
+
empty history; a bad line is the `422 terragucci-report` refusal naming it.
|
|
91
|
+
`src/terragucci-timeline.ts` holds the read and the check (terragucci's
|
|
92
|
+
`dist/audit.schema.json` when it resolves, structural otherwise). The SPA
|
|
93
|
+
draws it in the Terragucci tab and, filtered to the card's root, in the
|
|
94
|
+
inspect pane (`web/terragucci-timeline.js`); an export carries it as one
|
|
95
|
+
snapshot and does not fail on it.
|
|
96
|
+
- `GET /api/terragucci/lifecycle` (#505): the repo's `chant/lifecycle` lane,
|
|
97
|
+
`{branch, found, via, origin?, fetch: {ok, error?}, commit?: {sha,
|
|
98
|
+
committed}, read: {at}, gates[], locks[], note}`. `gates[]` is one entry per
|
|
99
|
+
`wave-<k>` in `_gates/tf-apply.jsonl` and `_gates/tf-apply/applied.jsonl`:
|
|
100
|
+
`state` (`waiting | expired | approved | applied | failed`), `digest`,
|
|
101
|
+
`pending`, `approval` (by, at, signed), `applied`, the kept reports under
|
|
102
|
+
`_gates/tf-apply/wave-<k>/`, and `command` when it waits. `locks[]` is
|
|
103
|
+
`_locks/tf-apply.json`, one per root (`pr, by, at, head, via?, stage?`).
|
|
104
|
+
Every gate and lock carries `source: {commit, committed, path}`, the newest
|
|
105
|
+
commit of the branch that changed its file. The branch is fetched from the
|
|
106
|
+
checkout's origin URL into `<tmpdir>/behold-lifecycle-<hash of the URL>`, a
|
|
107
|
+
bare repo behold owns (`assertScratch`), with the person's own git
|
|
108
|
+
credentials and no prompt; the checkout is never fetched into and no ref of
|
|
109
|
+
it moves. A failed fetch falls back to the checkout's own
|
|
110
|
+
`refs/remotes/origin/chant/lifecycle`, read-only (`via: "checkout-ref"`,
|
|
111
|
+
`fetch.error`); a remote without the branch is `found: false, via:
|
|
112
|
+
"fetch"`, not an error. 30 s cache, `?fresh=1` skips it. Reader:
|
|
113
|
+
`src/terragucci-lifecycle.ts`.
|
|
114
|
+
- `GET /api/terragucci/events` (#505): SSE. While at least one page holds it
|
|
115
|
+
open, a timer (`--terragucci-poll <secs>`, default 30, 0 off) asks
|
|
116
|
+
whether `index.json` changed (`If-None-Match` with the last ETag for S3 and
|
|
117
|
+
http, mtime for a directory) and fetches `chant/lifecycle` again. Events:
|
|
118
|
+
`hello {pollSecs}`, `reports {at, tag}` (the page reads `/api/terragucci`
|
|
119
|
+
again), `lifecycle <the whole answer>` when the read differs from the last,
|
|
120
|
+
and `polled {at, reports, lifecycle}` after every tick. The last page
|
|
121
|
+
leaving stops the timer (`src/terragucci-poll.ts`). Neither route writes,
|
|
122
|
+
approves, locks or unlocks.
|
|
123
|
+
- `GET /api/terragucci/progress` (#511): a choudoufu wave's progress per
|
|
124
|
+
resource from the run view of the newest commit `index.json` names a
|
|
125
|
+
`tf-apply` run of (one GET of `index.json`, one of
|
|
126
|
+
`<project dir>/runs/<commit>/run.json`, the directory taken from the index
|
|
127
|
+
row's own path). `{source, kind, project, validation, read, run: {commit,
|
|
128
|
+
key, present, updated?, html?} | null, absent?, files, watching, waves[],
|
|
129
|
+
cards{}, unmatched[]}`. A wave is `{number, state, gate, read, counts,
|
|
130
|
+
resources[]}`, a resource `{root, address, action, status: done | in-flight
|
|
131
|
+
| waiting | not-applied, done_at?, card?}`. `cards` is keyed by the same ids
|
|
132
|
+
as `/api/terragucci`'s marks (root path to `attrs.root`, instance to block),
|
|
133
|
+
one entry per wave with the wave's records `read` time and the card's
|
|
134
|
+
status (not applied, else in flight, else waiting, else done). It is a
|
|
135
|
+
dated corner tag, never a fill. No `run.json` is `run.present: false` plus
|
|
136
|
+
an `absent` sentence. `watching` is true while a wave is applying or a
|
|
137
|
+
resource is in flight or waiting; only then does the poll ask whether that
|
|
138
|
+
`run.json` changed (`If-None-Match`, mtime for a directory) and push a
|
|
139
|
+
`progress` event with the whole answer, and `polled` carries `progress:
|
|
140
|
+
{asked, key?, changed?, error?}`. Checked against `dist/run.schema.json`
|
|
141
|
+
when `@intentius/terragucci` resolves, structurally otherwise; reader
|
|
142
|
+
`src/terragucci-progress.ts`, page `web/terragucci-progress.js`.
|
|
81
143
|
|
|
82
144
|
The reads are `src/terragucci-reports.ts` (index, each run's report, estate;
|
|
83
145
|
terragucci's JSON Schemas when `@intentius/terragucci` resolves, a structural
|
|
@@ -87,6 +149,30 @@ schemas cached by its path and files' mtimes, #500) and the join is `src/terragu
|
|
|
87
149
|
operator's `aws s3 cp <key> -`. There is no approve route, by design: hand the
|
|
88
150
|
operator `waiting[].command`.
|
|
89
151
|
|
|
152
|
+
A control repo (#509), one whose terragucci config has `projects:` and whose
|
|
153
|
+
checkout declares no Terraform root (`controlRepo` in
|
|
154
|
+
`src/terragucci-estate.ts`), gets one more read, and `/api/project` carries
|
|
155
|
+
`terragucciControl: {config, projects}`:
|
|
156
|
+
|
|
157
|
+
- `GET /api/terragucci/estate`: `{source, kind, config, validation: {estate,
|
|
158
|
+
run}, read, estate: {key, html, generated}, gets, projects[], edges[],
|
|
159
|
+
files}`. It reads `estate.json` and each project's newest run view,
|
|
160
|
+
`<project>/runs/<commit>/run.json`, one GET each (the commit is the
|
|
161
|
+
project's `run_view.commit`, else its `apply.commit`). A project is
|
|
162
|
+
`{project, status, index?, counts: {drifted, failed, waiting, dated},
|
|
163
|
+
waiting[], run? | missing? | refused?, checkout?, configured}`. Every
|
|
164
|
+
figure carries `dated: {key, at}`: estate.json's `generated`, or the run
|
|
165
|
+
view's `updated`. `waiting[].command` is the run view's approve line when it
|
|
166
|
+
holds that wave. `edges[]` is `{from, to, cross}`, `to` reading `from`'s
|
|
167
|
+
state; a cross edge matches a root's `external` read to another project's
|
|
168
|
+
root `state`, as terragucci's `estateGraph` does. A malformed run view is
|
|
169
|
+
`refused: {code: "terragucci-report"}` on its project only; a missing or
|
|
170
|
+
malformed `estate.json` is a 422. Not a control repo: 404 `code:
|
|
171
|
+
"terragucci-not-control"`. Run views are checked against
|
|
172
|
+
`@intentius/terragucci`'s `dist/run.schema.json` when it resolves, a
|
|
173
|
+
structural check otherwise. The page (`web/terragucci-estate.js`) draws it
|
|
174
|
+
in a layer over the graph area.
|
|
175
|
+
|
|
90
176
|
## Getting a server
|
|
91
177
|
|
|
92
178
|
```sh
|
|
@@ -698,6 +784,20 @@ uploading (no list call) and, after `index.html`, deletes the
|
|
|
698
784
|
Nothing outside the prefix is deleted. A refused delete stops the sweep with
|
|
699
785
|
a warning naming `s3:DeleteObject`, and the publish still succeeds.
|
|
700
786
|
|
|
787
|
+
Since #510 the bundle goes to `<prefix>/<commit>/` (the checkout's HEAD, or
|
|
788
|
+
`--commit`), with publishBundle's order and sweep one level down, and
|
|
789
|
+
`src/publish-snapshots.ts` then writes, in order, `history.json` (newest
|
|
790
|
+
first, `{commit, at, project, generated}`, one GET of the old one),
|
|
791
|
+
`latest.json` (`{commit}`) and the root `index.html`, a no-cache page that
|
|
792
|
+
opens `<latest>/index.html`, so old links keep working. `--keep <n>` (30)
|
|
793
|
+
drops older commits from `history.json` and then deletes their files as each
|
|
794
|
+
commit's `manifest.json` lists them (`files`, which runExport now writes,
|
|
795
|
+
plus `keyToFile`), best effort with the same `s3:DeleteObject` warning. A
|
|
796
|
+
view from before the layout keeps its files; only its `index.html` is
|
|
797
|
+
replaced. With `--publish` the default `--reports-base` is `../../../`. The
|
|
798
|
+
view's history picker (`web/history-picker.js`) reads `../history.json` and
|
|
799
|
+
only navigates.
|
|
800
|
+
|
|
701
801
|
A choudoufu estate member (#366) adds no exception. A move there is one tag
|
|
702
802
|
write through choudoufu's own `live-mv`, and behold never makes it: `GET
|
|
703
803
|
/api/choudoufu/moves` reads a plan (`carve.json`) from inside a served member,
|