@minnovate/shadow-publisher 0.15.0 → 0.15.2

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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "git-publisher",
3
3
  "displayName": "Git Publisher",
4
- "version": "0.15.0",
4
+ "version": "0.15.2",
5
5
  "description": "Publish an app folder's Git history to the serverless Git publishing backend and keep it updated (\"publish my app\", \"update my app\", \"fetch the engineered version\").",
6
6
  "author": { "name": "git-publisher project" },
7
7
  "keywords": ["git", "publish", "deploy", "serverless"]
@@ -136,9 +136,9 @@ fast-forward or a clean merge — it never rewrites the user's work), and publis
136
136
  them when the person asks why it was slow. Write
137
137
  the message in the user's words ("Add a contact page"), not git's.
138
138
 
139
- A published app runs with no internet access: **it may not load anything from other sites** — no
140
- CDN scripts, web fonts or remote images. When you write or change an app, keep every file it needs
141
- in its folder. The checks refuse an app that does not (see "When the checks find something").
139
+ A published app runs with no internet access: **apps can’t load anything from other sites** — no
140
+ CDN scripts, web fonts or remote images — and can’t call other sites for data: connect the data as
141
+ a data source instead. When you write or change an app, keep every file it needs in its folder. The checks refuse an app that does not (see "When the checks find something").
142
142
  Keep it small too: each file at most 4 MB, the whole app at most 10 MB, at most 500 files —
143
143
  a larger app is refused before it is checked, and the refusal names the file or the limit it broke.
144
144
 
@@ -182,7 +182,10 @@ following, for when the person asks not to wait.
182
182
  checked, and this organisation does not deploy automatically. `"failed"` with `findings`: it
183
183
  did not pass its checks, and `findings` says why — fix them as "When the checks find something"
184
184
  below says. `"failed"` without `findings`: it stopped at `failedAt`; the portal says why — do
185
- not guess the reason. `"stopped"`: a newer publication replaced it.
185
+ not guess the reason. A fault on our side can be tried again: to find out, run `publisher
186
+ question . --json` and follow the `sync-app` skill's section
187
+ "When it did not go live because of a fault on our side".
188
+ `"stopped"`: a newer publication replaced it.
186
189
  - `"moving"` or `"timed-out"`: still going; follow it as step 4 says. After about 15 minutes in
187
190
  all, stop and point them to the portal (`progress.portal`).
188
191
  - `"unauthorized"`: published, but the portal did not accept this sign-in; run `publisher login`
@@ -220,11 +223,17 @@ sentence, and `progress.next.action` is `"fix"`. Then:
220
223
  Their original app is still what is published; nothing broke.
221
224
  2. Fix every finding in the app folder, by its `kind`:
222
225
  - `external-resource`: the app loads `url` from another site (a CDN script, Google Fonts, an
223
- image). **Apps may not load anything from other sites.** Download the file into the app
226
+ image). **Apps can’t load anything from other sites.** Download the file into the app
224
227
  folder and point to it with a relative path, if it is at most 4 MB (a charting library
225
228
  such as Chart.js, about 200 KB, fits). Otherwise replace it with code of your own: a
226
229
  font falls back to a system font stack, a chart is drawn as inline SVG. Never keep the
227
230
  external address.
231
+ - `external-request`: the app CALLS `url` on another site for data (`fetch`, an API).
232
+ **Apps can't reach other sites.** Do not copy anything: remove the call, or bring the data
233
+ into the app as a data source (the `data_sources` tool, or `publisher data add`), and read
234
+ it from there.
235
+ - `server-start`: the app's server stopped before it answered `/`. `message` is the error it
236
+ printed and where. Fix that line, and run the server with `PORT` set to try it.
228
237
  - `console-error` / `application-error`: fix the code that logs or throws `message`.
229
238
  - `failed-request`: the app asks for `path` on its own site and gets `status`; add the file or
230
239
  stop requesting it.
@@ -42,6 +42,18 @@ A value that is not an option is refused before anything is sent; `error.details
42
42
  the choices. Exit 4 means this sign-in may not answer (an owner or admin can); exit 3 means ask
43
43
  again. Then `publisher follow . --publication <id> --until-change --timeout 100 --json` to see it go live, telling them each step as `publish-app` step 4 says.
44
44
 
45
+ ## When it did not go live because of a fault on our side
46
+
47
+ When `publisher question . --json` shows a `blocked` preparation with `canRetry: true`, the fault
48
+ was on our side, not in the app (its `message` says so). Do not change the app. Try it again once:
49
+
50
+ ```bash
51
+ publisher retry . --json
52
+ ```
53
+
54
+ Then follow it again. If it fails a second time, or `canRetry` is `false`, tell the person, and
55
+ give them the portal page.
56
+
45
57
  ## After it is live
46
58
 
47
59
  These run in the app's folder and answer `say` (tell the person) and `next` (what to do now):
@@ -5549,6 +5549,9 @@ function readPreparation(input, opts) {
5549
5549
  function answerPreparation(input, opts) {
5550
5550
  return call(input, opts, { id: input.id, revision: input.revision, action: "answers", answers: input.answers });
5551
5551
  }
5552
+ function retryPreparation(input, opts) {
5553
+ return call(input, opts, { id: input.id, revision: input.revision, action: "retry" });
5554
+ }
5552
5555
  async function call(input, opts, body) {
5553
5556
  const url2 = `${input.portal.replace(/\/+$/, "")}/api/v1/terminal/repositories/${encodeURIComponent(input.repoId)}/preparation`;
5554
5557
  const answer2 = await new PortalSession(opts).ask(url2, body);
@@ -5608,7 +5611,16 @@ function readView(body) {
5608
5611
  if (isRecord(publication) && typeof publication["status"] === "string" && typeof publication["message"] === "string") {
5609
5612
  pub = { status: publication["status"], message: publication["message"], ...typeof publication["url"] === "string" ? { url: publication["url"] } : {} };
5610
5613
  }
5611
- return { id, revision, status: status2, message, questions: read2, publication: pub, findings: readFindings(body["findings"]) };
5614
+ return {
5615
+ id,
5616
+ revision,
5617
+ status: status2,
5618
+ message,
5619
+ questions: read2,
5620
+ publication: pub,
5621
+ findings: readFindings(body["findings"]),
5622
+ canRetry: body["canRetry"] === true
5623
+ };
5612
5624
  }
5613
5625
  function readFindings(value) {
5614
5626
  if (!Array.isArray(value)) {
@@ -6454,6 +6466,10 @@ var Publisher = class {
6454
6466
  async answerPreparation(input) {
6455
6467
  return answerPreparation(input, this.portalCall());
6456
6468
  }
6469
+ /** The repository's current preparation tried again, when it could not finish because of a fault on our side. */
6470
+ async retryPreparation(input) {
6471
+ return retryPreparation(input, this.portalCall());
6472
+ }
6457
6473
  /**
6458
6474
  * One of the creator's tools at the portal that serves this endpoint — starters, status, history,
6459
6475
  * going back, suggestions, sharing — with this publisher's credential and its one refresh. The
@@ -7089,7 +7105,7 @@ async function followPublication(p, endpoint, o, opts) {
7089
7105
  return {
7090
7106
  ...outcome2,
7091
7107
  portal,
7092
- hint: `It did not pass its checks (${findings.length === 1 ? "one finding" : `${findings.length} findings`}). Fix each finding in the app folder, then run next.command to publish again.`,
7108
+ hint: `It didn\u2019t pass its checks (${findings.length === 1 ? "one finding" : `${findings.length} findings`}). Fix each finding in the app folder, then run next.command to publish again.`,
7093
7109
  findings,
7094
7110
  next: { action: "fix", command: `publisher sync ${dir} --until-change --json` }
7095
7111
  };
@@ -7874,6 +7890,20 @@ async function answerAt(p, endpoint, repoId, specs, opts = {}) {
7874
7890
  }
7875
7891
  return shown(at.portal, await p.answerPreparation({ portal: at.portal, repoId, id: read2.preparation.id, revision: read2.preparation.revision, answers }));
7876
7892
  }
7893
+ async function retryAt(p, endpoint, repoId, opts = {}) {
7894
+ const read2 = await questionAt(p, endpoint, repoId, opts);
7895
+ if (read2.kind !== "view") {
7896
+ return read2;
7897
+ }
7898
+ if (read2.preparation.status !== "blocked") {
7899
+ throw new PublisherError("LOCAL_STATE", `nothing to try again (the preparation is ${read2.preparation.status})`);
7900
+ }
7901
+ if (!read2.preparation.canRetry) {
7902
+ throw new PublisherError("LOCAL_STATE", "this version cannot be tried again: only one that stopped because of a fault on our side can, three times at most");
7903
+ }
7904
+ const tried = shown(read2.portal, await p.retryPreparation({ portal: read2.portal, repoId, id: read2.preparation.id, revision: read2.preparation.revision }));
7905
+ return tried.kind === "view" ? { ...tried, hint: "It is being tried again. Run: publisher follow, or watch it in the portal." } : tried;
7906
+ }
7877
7907
  function parseSpecs(specs) {
7878
7908
  if (specs.length === 0) {
7879
7909
  throw new PublisherError("INVALID_REQUEST", "answer takes one or more question=value");
@@ -7960,6 +7990,16 @@ var question = {
7960
7990
  return 0;
7961
7991
  }
7962
7992
  };
7993
+ var retry = {
7994
+ git: false,
7995
+ async run(inv) {
7996
+ const dir = inv.dirArg(1);
7997
+ const { p, endpoint } = await inv.client(dir);
7998
+ const repoId = await inv.repoId(dir);
7999
+ inv.out({ repoId, ...await retryAt(p, endpoint, repoId) });
8000
+ return 0;
8001
+ }
8002
+ };
7963
8003
  var answer = {
7964
8004
  git: false,
7965
8005
  async run(inv) {
@@ -8450,6 +8490,8 @@ Usage:
8450
8490
  with each option's value (answering needs owner or admin)
8451
8491
  publisher answer <question>=<value>... [--repo <id>] answer it from this folder; a value that is not one of
8452
8492
  the question's options is refused before anything is sent
8493
+ publisher retry [dir] [--repo <id>] try the app's newest version again, when it did not go
8494
+ live because of a fault on our side (three tries at most)
8453
8495
  publisher starters [what you want to stop doing] working apps to start from, the ones that fit first
8454
8496
  publisher start <starter> [--name <n>] [--replaces <what>] a new app made from a starter, live in about a minute
8455
8497
  publisher history this folder's app: the versions that went live, newest first
@@ -8506,6 +8548,7 @@ var COMMANDS = /* @__PURE__ */ new Map([
8506
8548
  ["follow", follow],
8507
8549
  ["question", question],
8508
8550
  ["answer", answer],
8551
+ ["retry", retry],
8509
8552
  ["skills", skills],
8510
8553
  ["merge-check", mergeCheck2],
8511
8554
  ["info", info],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@minnovate/shadow-publisher",
3
- "version": "0.15.0",
3
+ "version": "0.15.2",
4
4
  "description": "publisher: publish an app's Git history to the serverless Git backend",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",