76 lines
3.2 KiB
JavaScript
76 lines
3.2 KiB
JavaScript
|
|
/// <reference path="../pb_data/types.d.ts" />
|
||
|
|
|
||
|
|
// What the release gate found, run by run.
|
||
|
|
//
|
||
|
|
// The catalogue in amber-app (`docs/e2e/catalogue.yaml`) says what a person must
|
||
|
|
// be able to do before a build goes out; the runner executes it and writes one
|
||
|
|
// record here per run. The dashboard's Testy tab reads them.
|
||
|
|
//
|
||
|
|
// WHY A COLLECTION AND NOT A SERVICE: the owner's call, and the right one. A
|
||
|
|
// whole application to display a table of results would cost more to keep alive
|
||
|
|
// than the thing it displays, and the VPS's disk is already the scarce resource
|
||
|
|
// (old releases eat it, not databases).
|
||
|
|
//
|
||
|
|
// **The screenshots live here too, for as long as the run does.** A result whose
|
||
|
|
// evidence has been deleted is a claim again rather than a record, and they are
|
||
|
|
// small next to a release artifact. Deleting a run takes its evidence with it,
|
||
|
|
// which is the retention policy in one sentence.
|
||
|
|
//
|
||
|
|
// Superuser-only, like the status dashboard it appears in: this is operator
|
||
|
|
// data, it names internal ids and it carries screenshots of a signed-in app.
|
||
|
|
// There is no reason for a family account to be able to read it.
|
||
|
|
|
||
|
|
migrate(
|
||
|
|
(app) => {
|
||
|
|
const runs = new Collection({
|
||
|
|
type: "base",
|
||
|
|
name: "e2e_runs",
|
||
|
|
listRule: null,
|
||
|
|
viewRule: null,
|
||
|
|
createRule: null,
|
||
|
|
updateRule: null,
|
||
|
|
deleteRule: null,
|
||
|
|
fields: [
|
||
|
|
// The run's own stamp, e.g. 2026-09-10T00-31-02Z — the directory name on
|
||
|
|
// the machine that ran it, so a record can be traced back to its files.
|
||
|
|
{ type: "text", name: "run", required: true, max: 40 },
|
||
|
|
// linux | windows | phone | tv | attach
|
||
|
|
{ type: "text", name: "target", required: true, max: 20 },
|
||
|
|
// What was under test, not what wrote the record: the app's version and
|
||
|
|
// the commit the cases came from. Without both, a green run a month old
|
||
|
|
// says nothing about which build it green-lit.
|
||
|
|
{ type: "text", name: "appVersion", required: true, max: 40 },
|
||
|
|
{ type: "text", name: "commit", required: true, max: 40 },
|
||
|
|
{ type: "number", name: "catalogueVersion", onlyInt: true },
|
||
|
|
// { pass, fail, blocked, unsupported, unimplemented }
|
||
|
|
{ type: "json", name: "counts", maxSize: 2000 },
|
||
|
|
// One entry per case: id, outcome, blocker, how, ms, evidence, error.
|
||
|
|
// The evidence entries name their screenshot files, which is how the
|
||
|
|
// dashboard pairs a claim with the picture that proves it.
|
||
|
|
{ type: "json", name: "cases", maxSize: 2000000 },
|
||
|
|
{
|
||
|
|
type: "file",
|
||
|
|
name: "shots",
|
||
|
|
maxSelect: 200,
|
||
|
|
maxSize: 8388608,
|
||
|
|
mimeTypes: ["image/png"],
|
||
|
|
},
|
||
|
|
// Anything the run wants to say for itself — usually why a target could
|
||
|
|
// not start at all, which is a result worth keeping rather than an
|
||
|
|
// absence of one.
|
||
|
|
{ type: "text", name: "note", max: 2000 },
|
||
|
|
{ type: "autodate", name: "created", onCreate: true },
|
||
|
|
],
|
||
|
|
indexes: [
|
||
|
|
"CREATE INDEX idx_e2e_runs_created ON e2e_runs (created)",
|
||
|
|
"CREATE INDEX idx_e2e_runs_target ON e2e_runs (target, created)",
|
||
|
|
],
|
||
|
|
});
|
||
|
|
app.save(runs);
|
||
|
|
},
|
||
|
|
(app) => {
|
||
|
|
const c = app.findCollectionByNameOrId("e2e_runs");
|
||
|
|
if (c) app.delete(c);
|
||
|
|
},
|
||
|
|
);
|