@outerlayer/cli 0.16.1 → 0.18.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/CHANGELOG.md +64 -0
- package/README.md +26 -11
- package/dist/agent-setup-RBTEACYU.js +28 -0
- package/dist/artifact-link-cmd-AVM2EKTV.js +25 -0
- package/dist/{build-BG2YENGK.js → build-TQ6X5PYN.js} +5 -4
- package/dist/build-info.json +1 -1
- package/dist/{builder-2D3WSOOY.js → builder-DUI2ZH2H.js} +5 -6
- package/dist/{check-CNTMSGOG.js → check-5C4YDZYV.js} +53 -50
- package/dist/{chunk-R7PF5OOU.js → chunk-3CWUOFV6.js} +21 -14
- package/dist/{chunk-R4ZQQ7U2.js → chunk-3OFZM4X6.js} +551 -72
- package/dist/{chunk-2MNPHL23.js → chunk-47TTLEDX.js} +6 -5
- package/dist/{chunk-PLMTLGYH.js → chunk-52NC2FIU.js} +4 -3
- package/dist/chunk-6CHIYEZZ.js +564 -0
- package/dist/{chunk-TI7B7UEO.js → chunk-AMFWYESY.js} +1 -1
- package/dist/{chunk-YRYMNBGQ.js → chunk-ANPNT6PM.js} +2 -1
- package/dist/{chunk-JJEGKEFV.js → chunk-B3UKB46N.js} +6 -6
- package/dist/{chunk-JXYVA45C.js → chunk-BMYGAGBJ.js} +1050 -304
- package/dist/{chunk-4Q7OMKAT.js → chunk-BQXFBI7T.js} +81 -5
- package/dist/chunk-CRB3POP4.js +34 -0
- package/dist/{chunk-F47JBIAW.js → chunk-DSF2FWAZ.js} +2 -1
- package/dist/{chunk-N5FOE5PS.js → chunk-ECODQ7II.js} +4 -33
- package/dist/{chunk-NBGDBTO2.js → chunk-ESC6UR76.js} +6 -5
- package/dist/{chunk-HHJDN6AU.js → chunk-ESVW4MJY.js} +1 -1
- package/dist/{chunk-42ZI52JW.js → chunk-F4XSVQJ4.js} +4 -3
- package/dist/{chunk-FWX735W7.js → chunk-FUB7LRUE.js} +7 -7
- package/dist/chunk-G2YNJIGF.js +44 -0
- package/dist/{chunk-QKFB4K7X.js → chunk-GGOMT6KF.js} +1 -1
- package/dist/{chunk-CA3XMYFN.js → chunk-GOBOJMOJ.js} +6 -6
- package/dist/{chunk-N6LURUEF.js → chunk-GOSFARMS.js} +1 -1
- package/dist/chunk-JBJTC3UU.js +35 -0
- package/dist/{chunk-U3HXXRTY.js → chunk-JF42URPU.js} +16 -15
- package/dist/{chunk-ADJRGVZC.js → chunk-KDVIU23F.js} +1 -1
- package/dist/{chunk-6QRMLNH3.js → chunk-KK4VBOH6.js} +93 -37
- package/dist/{chunk-KMDLFI4P.js → chunk-L2USZT6T.js} +1 -1
- package/dist/{chunk-WTE3MQML.js → chunk-LXAY4A2G.js} +3 -12
- package/dist/{chunk-V7NIVOFD.js → chunk-M2ZWWTWZ.js} +1 -1
- package/dist/{chunk-ERI5GBNI.js → chunk-MLAAT4S6.js} +3 -3
- package/dist/{chunk-POJMEEJJ.js → chunk-MNTSH4CL.js} +1 -1
- package/dist/{chunk-WUYTWNMA.js → chunk-MQJSXHV7.js} +1 -1
- package/dist/{chunk-O765JR4W.js → chunk-MTP2QEVO.js} +1 -1
- package/dist/{chunk-ZM2IMMYN.js → chunk-N2PXGQRL.js} +9 -1
- package/dist/{chunk-J5M7BSJQ.js → chunk-N3CUDFCW.js} +9 -3
- package/dist/{chunk-4KSQKQXE.js → chunk-NACDBXUG.js} +19 -15
- package/dist/{chunk-RSPXEVDX.js → chunk-NL4XPC7W.js} +1 -1
- package/dist/{chunk-EHAAPRWY.js → chunk-QQM2UJ6T.js} +31 -26
- package/dist/{chunk-5FEK6PNE.js → chunk-RAZTWYZN.js} +10 -9
- package/dist/{chunk-4NPZVMJU.js → chunk-S26M3YBJ.js} +60 -4
- package/dist/{chunk-UGP76IZ5.js → chunk-S5PCA3SN.js} +1 -1
- package/dist/{chunk-YDSMROTB.js → chunk-S76AYB4M.js} +25 -20
- package/dist/{chunk-RMWLBUCJ.js → chunk-SADUQSO4.js} +1 -1
- package/dist/{chunk-OZGHL5Y5.js → chunk-SWCTGCSC.js} +2 -2
- package/dist/{chunk-GQD22KKN.js → chunk-T2Q7ISPE.js} +2 -1
- package/dist/{chunk-C5Y5ZJJZ.js → chunk-T4Y6SCG3.js} +5 -4
- package/dist/{chunk-6JNURGOA.js → chunk-ULSIJGLS.js} +45 -13
- package/dist/{chunk-ONRCEE6D.js → chunk-UYOYTKE2.js} +4 -4
- package/dist/{chunk-PTW6W5NR.js → chunk-VYAL7PUE.js} +1 -1
- package/dist/{chunk-JEHRUE3F.js → chunk-W5VPCONO.js} +166 -196
- package/dist/{chunk-NPQWKGUA.js → chunk-WBT5X3NH.js} +5 -4
- package/dist/{chunk-RLYZLUQ7.js → chunk-WGAUY5LE.js} +2 -2
- package/dist/{chunk-RSNSZ2LJ.js → chunk-X5H2WYMB.js} +1 -1
- package/dist/{chunk-OHVJA253.js → chunk-X5N6KC6V.js} +47 -29
- package/dist/{chunk-22RMZBGW.js → chunk-XGP3VYOG.js} +1 -1
- package/dist/{chunk-HYZRY4KZ.js → chunk-XNGMQ27R.js} +16 -6
- package/dist/{chunk-W3EKCZSQ.js → chunk-Y5GE76XC.js} +180 -53
- package/dist/{chunk-EWORLJMO.js → chunk-Y5MXET4M.js} +277 -526
- package/dist/{chunk-XCK2YAY5.js → chunk-YVZJ6GKF.js} +3 -2
- package/dist/{chunk-YO4PSLVB.js → chunk-ZRL6HKBY.js} +1 -1
- package/dist/claude-launcher-YVXI76NX.js +102 -0
- package/dist/{cli-AEWH62UE.js → cli-C77H54BV.js} +489 -174
- package/dist/{command-HHPBR6CS.js → command-H5CILO4S.js} +40 -37
- package/dist/{config-N3C6DFQA.js → config-FXDG4NPJ.js} +2 -3
- package/dist/connect-cmd-ZW5FV3ZW.js +17 -0
- package/dist/{context-adopt-VMMGFRUZ.js → context-adopt-O5OFXMKI.js} +13 -12
- package/dist/context-materialize-Y5IJ4MQT.js +23 -0
- package/dist/{dist-LKDWQWZ7.js → dist-QTX4RSCL.js} +2 -2
- package/dist/{docker-4J77Q2BF.js → docker-RC3PRX3Q.js} +7 -8
- package/dist/{doctor-N6Y7HKK3.js → doctor-2NQQML6P.js} +47 -39
- package/dist/{emit-artifact-cmd-H5MH3AOP.js → emit-artifact-cmd-7MP63KXU.js} +25 -22
- package/dist/emit-cmd-PPN4QQF2.js +14 -0
- package/dist/{emit-criteria-cmd-HBP6XS5C.js → emit-criteria-cmd-3RXPDLNK.js} +16 -14
- package/dist/{emit-finding-cmd-ZXDRL6PG.js → emit-finding-cmd-OL7JB6H3.js} +18 -16
- package/dist/{emit-result-cmd-RFKALS5Z.js → emit-result-cmd-UZVMOCF4.js} +20 -17
- package/dist/{exec-client-CQV746UF.js → exec-client-7UMESIE2.js} +3 -4
- package/dist/governing-source-BUU4IABS.js +35 -0
- package/dist/guest-init-KPBQOFE5.js +9 -0
- package/dist/hidden-prompt-UXBFMQC5.js +68 -0
- package/dist/{hook-fast-D7HV4IXG.js → hook-fast-W5MKHMJT.js} +4 -1
- package/dist/host-key-U4B5QETR.js +8 -0
- package/dist/{import-capture-cmd-EQ35EARA.js → import-capture-cmd-ZO6KGHI2.js} +7 -5
- package/dist/{import-ruler-cmd-BGAZXCQM.js → import-ruler-cmd-KJMWL5V6.js} +5 -3
- package/dist/index.js +8 -4
- package/dist/init-VWXIZEAN.js +54 -0
- package/dist/{init-FBCA4DRA.js → init-WNXXYMO7.js} +80 -53
- package/dist/{init-cmd-CAG572UE.js → init-cmd-WS6TIRYT.js} +28 -24
- package/dist/{init-update-VDFF4K3B.js → init-update-E3J6TVIN.js} +27 -26
- package/dist/{install-HDBIPHTX.js → install-CBWIEF3R.js} +4 -5
- package/dist/{install-cmd-5HYMXLEW.js → install-cmd-QDOTR4OM.js} +5 -4
- package/dist/{login-browser-QZCS3WW6.js → login-browser-O63QZN7D.js} +4 -3
- package/dist/{logout-cmd-QAUFDJ6J.js → logout-cmd-5V5MMBSY.js} +3 -2
- package/dist/{logs-H55NWW4H.js → logs-AMLKC3VP.js} +3 -1
- package/dist/loop-UGI2BJOT.js +76 -0
- package/dist/machine-JOW4RNZ7.js +49 -0
- package/dist/{mcp-install-cmd-FDTPQQS6.js → mcp-install-cmd-GGWB3JJ2.js} +3 -2
- package/dist/{mcp-serve-cmd-3KVYEUXG.js → mcp-serve-cmd-DOTY5FKY.js} +10 -8
- package/dist/paths-7XP63OAX.js +7 -0
- package/dist/pending-532ABZYC.js +8 -0
- package/dist/{pidfile-UZRH774M.js → pidfile-3DM4OBKO.js} +4 -2
- package/dist/{record-C43U4PKS.js → record-3WP6V2K5.js} +3 -2
- package/dist/{runner-env-EN7YE7QX.js → runner-env-4NB2GA7O.js} +5 -6
- package/dist/runner-key-TC3NFWFV.js +177 -0
- package/dist/{session-sender-24L5EW25.js → session-sender-NNVPSPY7.js} +17 -14
- package/dist/spec-cmd-OWVTBB4J.js +116 -0
- package/dist/{starter-pack-KF66HGZR.js → starter-pack-OPWUDOWX.js} +7 -5
- package/dist/{status-XHSGEYO5.js → status-TKCLLKFG.js} +42 -39
- package/dist/{statusline-fast-SVTMBMD7.js → statusline-fast-KN3BX67H.js} +2 -1
- package/dist/{sync-cmd-5G5EIEHD.js → sync-cmd-Q6VYNPWG.js} +16 -13
- package/dist/{watch-UTOXO4SE.js → watch-ARAGADTF.js} +16 -13
- package/dist/{work-claim-cmd-RKHYFE5Y.js → work-claim-cmd-34FERLYX.js} +25 -27
- package/dist/work-cmd-7S5B2H2P.js +25 -0
- package/dist/{work-comment-cmd-A55CUSYE.js → work-comment-cmd-SZJSPM5S.js} +15 -13
- package/dist/{work-launch-R5HTAP6X.js → work-launch-LEQ2MPM3.js} +3 -1
- package/dist/{work-open-pr-cmd-E6O53IJD.js → work-open-pr-cmd-RPXKCBWS.js} +17 -15
- package/dist/work-pr-cmd-5LGANL32.js +26 -0
- package/package.json +3 -2
- package/skill-pack/maintained/outerlayer-amend/SKILL.md +6 -2
- package/skill-pack/maintained/outerlayer-cli/SKILL.md +2 -0
- package/skill-pack/maintained/outerlayer-evidence/SKILL.md +4 -2
- package/skill-pack/maintained/outerlayer-findings/SKILL.md +2 -0
- package/skill-pack/shipped.json +27 -5
- package/skill-pack/template/build/SKILL.md +25 -10
- package/skill-pack/template/build/references/agent-briefs.md +3 -1
- package/skill-pack/template/build/references/criteria-judge.md +27 -0
- package/skill-pack/template/build/references/release.md +27 -34
- package/skill-pack/template/build/scripts/criterion-citations.mjs +8 -3
- package/skill-pack/template/build/scripts/record-criteria.mjs +8 -2
- package/skill-pack/template/spec/SKILL.md +37 -10
- package/skill-pack/validators/acceptance-criteria.yaml +25 -25
- package/skill-pack/validators/code-review.yaml +6 -5
- package/dist/agent-setup-K3ABU5NL.js +0 -27
- package/dist/chunk-BYT5O5RV.js +0 -61
- package/dist/connect-cmd-JUAW6MU4.js +0 -16
- package/dist/context-materialize-2WXTS4CW.js +0 -22
- package/dist/emit-cmd-IJ3GVRFD.js +0 -12
- package/dist/guest-init-LJP5GPZF.js +0 -9
- package/dist/host-key-YMLXY6QB.js +0 -7
- package/dist/init-MYX7YMIH.js +0 -51
- package/dist/loop-75J4YXLZ.js +0 -73
- package/dist/machine-A6ZCTUGS.js +0 -46
- package/dist/paths-OYKMVYJP.js +0 -6
- package/dist/pending-MXLSRYMO.js +0 -7
- package/dist/runner-key-W25ISHI3.js +0 -155
- package/dist/work-cmd-DJQJEZVB.js +0 -23
- package/dist/work-pr-cmd-L77K32WK.js +0 -24
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,69 @@
|
|
|
1
1
|
# @outerlayer/cli
|
|
2
2
|
|
|
3
|
+
## 0.18.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 2ef9133: Add `outerlayer claude`, which starts Claude Code with the repository's control plane attached. A governed build reads its control plane from a directory outside the checkout, so nothing from it is written into the checkout.
|
|
8
|
+
- e92982d: A session now takes its control plane from the one the factory stores, chosen in the factory's Settings with Use as control plane in the Repositories list. Nothing reads a `governs` list in a control plane's config any more, and `doctor` reports a list left there as unused. A gateway older than 0.17.0 does not store the answer, and the CLI says so instead of guessing.
|
|
9
|
+
|
|
10
|
+
A validator or policy `when` can name `repositories`, so a check applies only to pull requests in those repositories.
|
|
11
|
+
|
|
12
|
+
A session that could not reach the gateway, or reached a gateway too old to answer, no longer reads the retry guess it wrote as a confirmed answer on the next start. A build that cannot write the staged control-plane files now says so, and no longer reports that a credential cannot read the control plane.
|
|
13
|
+
|
|
14
|
+
- 2cb58e8: A container or microVM build now runs on the devcontainer of the repository that governs it. For a governed repository that is the control plane's `.devcontainer/devcontainer.json` (or `.devcontainer.json`), read at the commit the build's instructions come from. A governed repository's own devcontainer is not read, and the build log says so. A repository that governs itself builds from its own devcontainer, as before. `outerlayer runner image --repository <name>` builds the same image a build of that repository uses.
|
|
15
|
+
|
|
16
|
+
Before upgrading a runner host, copy the devcontainer your builds rely on into the control plane. A control plane with no devcontainer gives its builds the runner's default image. A factory whose only repository is its own control plane needs no move.
|
|
17
|
+
|
|
18
|
+
In a build with more than one repository, every repository is at `/build/work/repos/<owner>/<repo>`, the primary included. The primary is also at `/build/work/checkout`. The control plane devcontainer's setup commands run once, in the control plane's checkout, so they can name each repository by its fixed path. Host checks check out every repository at the same paths, each at the branch the build pushed there or else at its default branch.
|
|
19
|
+
|
|
20
|
+
- 07bb510: A `where: host` check can declare `run.judge.brief` instead of `run.command`. After a build ends well, the runner stops everything the build left running, checks that the image's Claude Code is unchanged, and runs a read-only Claude Code session with that brief. It records the verdict under the check's name with the host's own key and links the judge's report.
|
|
21
|
+
|
|
22
|
+
The starter `acceptance-criteria` check now uses this form, and the starter `/build` skill no longer records its own `acceptance-criteria` pass. Run `outerlayer doctor` to see an unedited copy of the old file as outdated, and `outerlayer init --update` to replace it.
|
|
23
|
+
|
|
24
|
+
- d776d34: `outerlayer spec` files and edits specs through OuterLayer, with no tracker tool of your own. `spec target` says where a spec would be filed. `spec search <query>` finds open and closed issues that match. `spec file --title <text> --body-file <path>` creates the issue and prints its key, URL and the `work build` command for it. `spec edit <key> --body-file <path>` replaces an issue's body, and `--updated-at` refuses the edit if the issue changed since you read it.
|
|
25
|
+
|
|
26
|
+
Filing works for GitHub today. An API key needs the new `spec.insert` permission to file and `spec.update` to edit, so re-mint keys that should do either. A GitHub organization admin must also approve the OuterLayer App's Issues write permission once.
|
|
27
|
+
|
|
28
|
+
### Patch Changes
|
|
29
|
+
|
|
30
|
+
- 8f46b70: The starter `/build` skill reads the issue from `outerlayer work status --json`, under the new `issue` field, instead of from a tracker tool. A build on a host holds no Linear or Jira credential, so it could not read those issues before. The build saves the issue to `build-reports/issue.md` and gives every agent that file. `/outerlayer-amend` reads the issue the same way.
|
|
31
|
+
|
|
32
|
+
To pick up the new `/build`, run `outerlayer init --update`. A copy you edited is left as it is.
|
|
33
|
+
|
|
34
|
+
- fe8bb20: Printed command hints now name the command the way you ran the CLI. Run it through `npx @outerlayer/cli` (or `pnpm dlx`, `yarn dlx` or `bunx`) and a hint says `npx @outerlayer/cli login`, not an `outerlayer login` that is not on your PATH. `--help` usage lines follow the same rule.
|
|
35
|
+
|
|
36
|
+
`work build --local` no longer prints a branch name. The session it hands off to works on a branch of its own, so the printed name was never used. `--json` still carries the `branch` field.
|
|
37
|
+
|
|
38
|
+
`doctor` no longer warns when Claude Code is newer than the newest version this release was tested with. It passes, and names that tested version. A Claude Code older than the tested range still warns.
|
|
39
|
+
|
|
40
|
+
- 9b898aa: Session cost estimates price Claude Haiku 5.5 requests over 100,000 input tokens at Haiku 5.5's long-context rates. Token buckets now start a new input band at 100,000 tokens.
|
|
41
|
+
- 5cc77dc: Builds no longer print a Node warning on the stderr of every Node process. The runner sets `NODE_USE_ENV_PROXY` so Node uses the build's proxy, and Node 22 then warns `[UNDICI-EHPA] EnvHttpProxyAgent is experimental`. A test that expects a child process's stderr to be empty failed in a build and passed on a laptop.
|
|
42
|
+
|
|
43
|
+
The runner now adds `--disable-warning=UNDICI-EHPA` to `NODE_OPTIONS` in container, microVM and process builds. It keeps the options the image, the recipe's `containerEnv` or a named host variable already set. A build run through a provision hook's `exec` is left as it was. Node before 20.11 does not know the flag and refuses to start with it.
|
|
44
|
+
|
|
45
|
+
- daac363: Uploaded sessions record the input band boundaries their token buckets were grouped by. The server uses them to tell when a bucket cannot be priced at a single rate, and prices that model from its individual requests instead.
|
|
46
|
+
- 7a16e3f: `outerlayer work status`, `work remove`, `work claim`, `work renew` and `work release` take a Linear or Jira key in `--issue`, such as `--issue ENG-142`. Pass `--tracker linear` or `--tracker jira` when both trackers hold the key. Before, `--issue` took only a GitHub issue number, so a Linear or Jira item could be named only with `--item`.
|
|
47
|
+
|
|
48
|
+
A runner's `repos.include` and `repos.exclude` now match a Linear or Jira item by the repository it was added with (`work build --repo`), instead of skipping it. A runner using `builtin:process`, or its own provision hook, now clones the repository the claim chose, so it can build an item that was added without a repository.
|
|
49
|
+
|
|
50
|
+
## 0.17.0
|
|
51
|
+
|
|
52
|
+
### Minor Changes
|
|
53
|
+
|
|
54
|
+
- 420b0db: `outerlayer runner init` takes `--factory <org>/<factory>`, the same name `outerlayer init --factory` takes, so a runner host no longer needs the Factory Id copied from the dashboard. With no factory named, a login that can use exactly one factory uses it and says which. A login that can use several is refused with each `--factory` value listed. `--app-id` still works, and a `--factory` and `--app-id` that name different factories are refused.
|
|
55
|
+
|
|
56
|
+
### Patch Changes
|
|
57
|
+
|
|
58
|
+
- a3ac4ae: Count a test title such as `WC-01: counts words` as citing criterion WC-01. The starter `/build` skill's `criterion-citations.mjs` linked no test whose title put a colon straight after the id, so a build could report 0 of 4 criteria linked. A longer id such as `WC-010`, `WC-01a` or `WC-01:b` still does not cite WC-01.
|
|
59
|
+
- a897c68: The README says to install the CLI globally with `npm install -g @outerlayer/cli`, because `/build` and the other skills run the `outerlayer` command.
|
|
60
|
+
- 2a59794: Fix review results never being recorded on a new factory. The starter code-review and acceptance-criteria checks and the starter `/build` skill told agents to copy each report's link from the pull request's evidence comment, which a factory never posts until comments are turned on. They now take the link from the line `outerlayer sync` prints. A new `outerlayer sync --link <artifact id>` prints the link of an artifact an earlier sync already uploaded.
|
|
61
|
+
- 8196dc9: `outerlayer runner init` names the factory once when it picks the only one the login can use. A refused pasted key no longer repeats the gateway's "Mint a fresh key" advice beside its own step to create a new key with the Runner preset.
|
|
62
|
+
- 8196dc9: `outerlayer runner init` no longer tries to create the runner key with your login, which the gateway never allows. With no key in the config file, it prints the link to the factory's API keys page, asks you to paste a key made with the Runner preset (nothing is shown as you paste), checks it, and goes on. With no terminal it stops and prints the link and the config-file lines to use. `--key-name` is removed. Its output now marks warnings with `!` instead of a tick, no longer doubles ticks for lines from the VM, drops the PATH note about the VM's shell, and says whether capture on the Mac is affected when the runner key moves into the VM.
|
|
63
|
+
- 3ba60cd: No change in behaviour: the runner's wait for a stopped session sender's exit is simplified, and its tests check that the wait ends when the exit is logged.
|
|
64
|
+
- 0b7e87c: The starter skills run the CLI through `npx @outerlayer/cli` when `outerlayer` is not on PATH.
|
|
65
|
+
- f7553df: `outerlayer context materialize` and a container build now fetch the control plane and commit that OuterLayer stores for a repository, and read no `governs` list for it. `outerlayer doctor` reports which control plane governs the repository, its ref and the stored commit. `outerlayer connect` picks the factory that owns a repository linked to two factories, the one with the oldest connection, without asking.
|
|
66
|
+
|
|
3
67
|
## 0.16.1
|
|
4
68
|
|
|
5
69
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -13,12 +13,13 @@ network, and when, is below.
|
|
|
13
13
|
Launch a session naming the work it's for, then sync:
|
|
14
14
|
|
|
15
15
|
```
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
16
|
+
npm install -g @outerlayer/cli # puts `outerlayer` on your PATH, once per machine
|
|
17
|
+
outerlayer login # sign in, once per machine
|
|
18
|
+
outerlayer init # connect this repository to a factory, install the capture hooks
|
|
19
|
+
outerlayer work build --issue 42 --local # create the work item; prints its number
|
|
20
|
+
OUTERLAYER_WORK=7 claude # launch a session naming that number
|
|
21
|
+
outerlayer sync --dry-run # see exactly what would leave your machine
|
|
22
|
+
outerlayer sync # upload sessions launched that way
|
|
22
23
|
```
|
|
23
24
|
|
|
24
25
|
## Privacy, stated plainly
|
|
@@ -94,6 +95,12 @@ content:
|
|
|
94
95
|
list and read items, and `work.claim` to claim, renew or release — `work.claim`
|
|
95
96
|
is not granted to a dashboard role by default, since a claim is a host's
|
|
96
97
|
lease, not a person's.
|
|
98
|
+
- **`outerlayer spec target`, `search`, `file` and `edit`** each make one
|
|
99
|
+
request to your gateway (`GET /v1/specs/target`, `GET /v1/specs/search`,
|
|
100
|
+
`POST /v1/specs`, `PATCH /v1/specs/{key}`). `search` sends your query, and
|
|
101
|
+
`file` and `edit` send the title and the Markdown body you give them.
|
|
102
|
+
Your gateway files the issue in your tracker; the CLI never holds a tracker
|
|
103
|
+
credential.
|
|
97
104
|
- **`outerlayer runner start`** lists, claims, renews and releases work
|
|
98
105
|
items the same way `work claim`/`renew`/`release` do, on the schedule its
|
|
99
106
|
config sets — it sends nothing about the job it runs beyond that; the
|
|
@@ -115,6 +122,15 @@ content:
|
|
|
115
122
|
command in a new container, and sends one `POST /v1/emitted-results` for
|
|
116
123
|
each: the check's name, pass or fail, and for a fail the exit status and the
|
|
117
124
|
last line of its output, scrubbed.
|
|
125
|
+
A `where: host` check that declares a `judge` runs after a successful
|
|
126
|
+
build instead of a command. The runner reads the item's recorded criteria
|
|
127
|
+
with `GET /v1/work-items/{id}`, fetches the build's commits and the brief
|
|
128
|
+
with the host's own git credentials, and copies out the tests that cite the
|
|
129
|
+
criteria. It starts a Claude Code agent in the build's image with the host's
|
|
130
|
+
Claude credential. The judge sees only a read-only folder of the criteria,
|
|
131
|
+
citations and diff, and it has no shell. The runner uploads the judge's
|
|
132
|
+
`report.html` as an artifact with its own key, and sends one
|
|
133
|
+
`POST /v1/emitted-results` with pass or fail and a one-line reason.
|
|
118
134
|
Before each check's command runs, the runner writes a read-only folder for it
|
|
119
135
|
to read: the work item, from `GET /v1/work-items/{id}` with the runner's own
|
|
120
136
|
key; the branch's diff, from `git fetch` of the build's commits with the
|
|
@@ -144,10 +160,9 @@ content:
|
|
|
144
160
|
to it.
|
|
145
161
|
- **`outerlayer runner init`** makes no network call when the config file
|
|
146
162
|
already holds a runner key. With no key there and a saved login, it
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
`GET /v1/runner/host-key`. `runner init --vm` on a Mac also runs `limactl`,
|
|
163
|
+
asks the gateway which factories the login can use (`GET /v1/me/factories`)
|
|
164
|
+
and prints the factory's API keys page. You create the key there and paste
|
|
165
|
+
it. It checks the pasted key, unsigned, with `GET /v1/runner/host-key`. `runner init --vm` on a Mac also runs `limactl`,
|
|
151
166
|
and Lima downloads a Linux VM image. Inside the VM, `apt` downloads Node and
|
|
152
167
|
`npm` downloads this CLI. Your runner key goes to the VM on the standard
|
|
153
168
|
input of a `limactl shell` command and is never a file or an argument on the
|
|
@@ -391,7 +406,7 @@ before it gives up.
|
|
|
391
406
|
| `outerlayer work claim --item <n>\|--issue <n> --kind implement\|amend [--repo] [--host] [--seconds]` | Records a lease for this host (default: its own hostname), so two hosts never build the same item at once. The lease belongs to the runner key that claimed it: a live lease held by a different key is refused, even under the same host name, and claiming again with the same key extends it. The first claim creates the host key (`host-key.pem` beside the config file) and binds the runner key to it; from then on every request made with that key is signed. Lease length defaults to 900 seconds, the server's own cap. |
|
|
392
407
|
| `outerlayer work renew --item <n>\|--issue <n> [--repo] [--host] [--seconds]` | Extends this host's own live lease. Refused if the lease has expired, or if a different runner key holds it (403 `claim_not_held`). |
|
|
393
408
|
| `outerlayer work release --item <n>\|--issue <n> [--repo] [--host] [--session-id] [--outcome]` | Marks the lease this API key holds released, optionally recording how the attempt ended. Releasing an already-released lease is a no-op that returns the recorded release time and outcome. Run inside a session with no `--host`, it releases that session's own lease instead (`--session-id` names the session when it cannot be detected), so the item's review opens without ending the session. |
|
|
394
|
-
| `outerlayer runner init [--vm\|--no-vm] [--
|
|
409
|
+
| `outerlayer runner init [--vm\|--no-vm] [--factory <org>/<factory>] [--app-id <id>] [--config <path>]` | Writes a `runner` block with defaults, keeping every key the config already had. With no `apiKey` in the config and a saved login, it prints the API keys page of the factory `--factory` or `--app-id` names (the only factory the login can use, when neither is given), asks you to paste a runner key made with the Runner preset, and checks it before anything else changes. With no terminal it stops and says what to put in the config. It names `builtin:vm` on a Linux machine where the user can use `/dev/kvm` and Docker Engine can build images once the guest kernel and helper are published (not yet), `builtin:container` on that machine until then, `builtin:container` on any other machine with Docker Engine, and `builtin:process` on one without, and writes no hook script. Refuses rather than overwriting an existing block. On macOS it asks whether to create a Linux VM with Lima, installs Docker Engine and the runner in it, and starts both at login; `--vm` answers yes and `--no-vm` answers no, and a run with no terminal answers no. The runner key and the host key then live only in the VM: the Mac's config loses `apiKey` and `runner` and gains a `runnerVm` note, which `outerlayer doctor` reads. |
|
|
395
410
|
| `outerlayer runner check [--config <path>]` | Validates the config, the hooks and the key, prints the settings the runner would use, and exits non-zero on a problem. Takes no work and writes no pid file. |
|
|
396
411
|
| `outerlayer runner start [--config <path>]` | Runs the loop: claim work, run it, sync, clean up, report, release with an outcome. Repeat. Reads the `runner` block from the config file (default `~/.outerlayer/config.json`). Refuses to start on a bad config, an unrunnable hook, or a refused key. |
|
|
397
412
|
| `outerlayer runner image --repository <owner/name> [--remote <url>] [--config <path>] [--json]` | Builds the image a repository's builds run in. Fetches the head of the default branch into the runner's cache, builds its `.devcontainer/devcontainer.json` with the devcontainer CLI, ignores every setting that reaches the host or widens the container's privileges, and adds this CLI and a pinned Claude Code. Reuses the image until the recipe or the tools change, keeps the newest three, and writes `recipe.json` beside the image record. Refuses a Compose recipe (`recipe_needs_docker`) and a repository with only named configurations (`recipe_ambiguous`). |
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createRequire } from 'node:module';
|
|
3
|
+
export { keepHandWritten, runAgentSetup } from './chunk-RAZTWYZN.js';
|
|
4
|
+
import './chunk-47TTLEDX.js';
|
|
5
|
+
import './chunk-YVZJ6GKF.js';
|
|
6
|
+
import './chunk-F4XSVQJ4.js';
|
|
7
|
+
import './chunk-ANPNT6PM.js';
|
|
8
|
+
import './chunk-W5VPCONO.js';
|
|
9
|
+
import './chunk-LXAY4A2G.js';
|
|
10
|
+
import './chunk-T4Y6SCG3.js';
|
|
11
|
+
import './chunk-ZRL6HKBY.js';
|
|
12
|
+
import './chunk-52NC2FIU.js';
|
|
13
|
+
import './chunk-MNTSH4CL.js';
|
|
14
|
+
import './chunk-X5N6KC6V.js';
|
|
15
|
+
import './chunk-N3CUDFCW.js';
|
|
16
|
+
import './chunk-EABW6AJQ.js';
|
|
17
|
+
import './chunk-RA3O54FC.js';
|
|
18
|
+
import './chunk-M2ZWWTWZ.js';
|
|
19
|
+
import './chunk-N2PXGQRL.js';
|
|
20
|
+
import './chunk-BQXFBI7T.js';
|
|
21
|
+
import './chunk-XCCLFVXM.js';
|
|
22
|
+
import './chunk-ZJSNLVCE.js';
|
|
23
|
+
import './chunk-BJ3KTMDH.js';
|
|
24
|
+
import './chunk-CRB3POP4.js';
|
|
25
|
+
import './chunk-VNVZDWO3.js';
|
|
26
|
+
import './chunk-Z5GEFMRW.js';
|
|
27
|
+
|
|
28
|
+
createRequire(import.meta.url);
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createRequire } from 'node:module';
|
|
3
|
+
import { sanitizeTerminal, readEffectiveArtifactSpoolState } from './chunk-MQJSXHV7.js';
|
|
4
|
+
import './chunk-N3CUDFCW.js';
|
|
5
|
+
import { cliInvocation } from './chunk-CRB3POP4.js';
|
|
6
|
+
import { homeFromEnv } from './chunk-VNVZDWO3.js';
|
|
7
|
+
import './chunk-Z5GEFMRW.js';
|
|
8
|
+
|
|
9
|
+
createRequire(import.meta.url);
|
|
10
|
+
|
|
11
|
+
// src/artifact-link-cmd.ts
|
|
12
|
+
function lookupArtifactLink(artifactId, home = homeFromEnv()) {
|
|
13
|
+
const shown = sanitizeTerminal(artifactId);
|
|
14
|
+
const entry = readEffectiveArtifactSpoolState(home).state.get(artifactId);
|
|
15
|
+
if (entry === void 0) return { ok: false, reason: `no artifact ${shown} is queued or uploaded on this machine` };
|
|
16
|
+
if (entry.state !== "uploaded") {
|
|
17
|
+
return { ok: false, reason: `artifact ${shown} is ${entry.state}, not uploaded yet \u2014 run \`${cliInvocation()} sync\` first` };
|
|
18
|
+
}
|
|
19
|
+
if (entry.url === void 0) {
|
|
20
|
+
return { ok: false, reason: `artifact ${shown} uploaded, but the gateway returned no link for it` };
|
|
21
|
+
}
|
|
22
|
+
return { ok: true, url: entry.url };
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export { lookupArtifactLink };
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
-
export { buildRepositoryImage } from './chunk-
|
|
3
|
+
export { buildRepositoryImage } from './chunk-3CWUOFV6.js';
|
|
4
4
|
export { RecipeError } from './chunk-QOZKPLVJ.js';
|
|
5
|
-
import './chunk-N5FOE5PS.js';
|
|
6
5
|
import './chunk-CX22S5BA.js';
|
|
7
|
-
import './chunk-
|
|
8
|
-
import './chunk-
|
|
6
|
+
import './chunk-ECODQ7II.js';
|
|
7
|
+
import './chunk-JBJTC3UU.js';
|
|
8
|
+
import './chunk-N2PXGQRL.js';
|
|
9
|
+
import './chunk-BQXFBI7T.js';
|
|
9
10
|
import './chunk-Z5GEFMRW.js';
|
|
10
11
|
|
|
11
12
|
createRequire(import.meta.url);
|
package/dist/build-info.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"id":"2026-10-
|
|
1
|
+
{"id":"2026-10-13T00:18:48.455Z+4c5e4a3","root":"/home/runner/_work/outerlayer/outerlayer","pkg":"outerlayer"}
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
-
export { MIN_BUILDX_VERSION, builderName, builderSpec, buildxState, ensureBuilder, ensureFailureCount, isOutOfMemory, proxyEnvironment, trackImageBuild } from './chunk-
|
|
3
|
+
export { MIN_BUILDX_VERSION, builderName, builderSpec, buildxState, ensureBuilder, ensureFailureCount, isOutOfMemory, proxyEnvironment, trackImageBuild } from './chunk-S26M3YBJ.js';
|
|
4
4
|
import './chunk-7RQ73DLO.js';
|
|
5
|
-
import './chunk-4Q7OMKAT.js';
|
|
6
5
|
import './chunk-CX22S5BA.js';
|
|
7
|
-
import './chunk-
|
|
8
|
-
import './chunk-
|
|
9
|
-
import './chunk-
|
|
10
|
-
import './chunk-
|
|
6
|
+
import './chunk-BMYGAGBJ.js';
|
|
7
|
+
import './chunk-N3CUDFCW.js';
|
|
8
|
+
import './chunk-N2PXGQRL.js';
|
|
9
|
+
import './chunk-BQXFBI7T.js';
|
|
11
10
|
import './chunk-Z5GEFMRW.js';
|
|
12
11
|
|
|
13
12
|
createRequire(import.meta.url);
|
|
@@ -1,72 +1,75 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
-
import { probeCredentials } from './chunk-
|
|
4
|
-
import './chunk-R4ZQQ7U2.js';
|
|
5
|
-
import './chunk-O765JR4W.js';
|
|
6
|
-
import './chunk-UGP76IZ5.js';
|
|
3
|
+
import { probeCredentials } from './chunk-QQM2UJ6T.js';
|
|
7
4
|
import './chunk-3JVYMD4G.js';
|
|
8
|
-
import './chunk-YETTWTAY.js';
|
|
9
|
-
import './chunk-RMWLBUCJ.js';
|
|
10
5
|
import './chunk-I2UOAV7X.js';
|
|
11
|
-
import './chunk-
|
|
12
|
-
import './chunk-
|
|
13
|
-
import './chunk-
|
|
14
|
-
import './chunk-
|
|
15
|
-
import './chunk-
|
|
16
|
-
import
|
|
6
|
+
import './chunk-YETTWTAY.js';
|
|
7
|
+
import './chunk-3OFZM4X6.js';
|
|
8
|
+
import './chunk-SADUQSO4.js';
|
|
9
|
+
import './chunk-KDVIU23F.js';
|
|
10
|
+
import './chunk-MTP2QEVO.js';
|
|
11
|
+
import './chunk-S5PCA3SN.js';
|
|
12
|
+
import './chunk-UYOYTKE2.js';
|
|
13
|
+
import './chunk-XNGMQ27R.js';
|
|
14
|
+
import { placeholderQueues, placeholderProblem, permissionModeProblems, permissionModeProblem, needsClaudeCredential, claudeCredentialCheck, claimPermissionProblem, formerSkillQueues, formerSkillProblem } from './chunk-FUB7LRUE.js';
|
|
15
|
+
import './chunk-AMFWYESY.js';
|
|
17
16
|
import './chunk-YYYRBYWG.js';
|
|
18
|
-
import './chunk-
|
|
17
|
+
import './chunk-GOBOJMOJ.js';
|
|
18
|
+
import './chunk-JF42URPU.js';
|
|
19
|
+
import './chunk-ESVW4MJY.js';
|
|
19
20
|
import './chunk-TBT347UY.js';
|
|
20
|
-
import './chunk-
|
|
21
|
-
import './chunk-
|
|
22
|
-
import './chunk-
|
|
23
|
-
import './chunk-
|
|
24
|
-
import './chunk-
|
|
25
|
-
import './chunk-
|
|
26
|
-
import './chunk-
|
|
27
|
-
import './chunk-
|
|
21
|
+
import './chunk-NL4XPC7W.js';
|
|
22
|
+
import './chunk-Y5MXET4M.js';
|
|
23
|
+
import './chunk-L2USZT6T.js';
|
|
24
|
+
import './chunk-S26M3YBJ.js';
|
|
25
|
+
import './chunk-GGOMT6KF.js';
|
|
26
|
+
import './chunk-X5H2WYMB.js';
|
|
27
|
+
import './chunk-6CHIYEZZ.js';
|
|
28
|
+
import './chunk-SWCTGCSC.js';
|
|
29
|
+
import './chunk-WGAUY5LE.js';
|
|
28
30
|
import { parseRunnerEnv } from './chunk-6MZSX4M7.js';
|
|
29
|
-
import './chunk-
|
|
30
|
-
import './chunk-
|
|
31
|
+
import './chunk-KK4VBOH6.js';
|
|
32
|
+
import './chunk-WBT5X3NH.js';
|
|
31
33
|
import './chunk-IP7BIBXJ.js';
|
|
32
|
-
import
|
|
34
|
+
import './chunk-S76AYB4M.js';
|
|
35
|
+
import './chunk-MQJSXHV7.js';
|
|
36
|
+
import { loadRunnerConfig, RunnerConfigError, checkHooks } from './chunk-XGP3VYOG.js';
|
|
33
37
|
import './chunk-UXYLWVTQ.js';
|
|
34
|
-
import './chunk-R7PF5OOU.js';
|
|
35
|
-
import './chunk-QOZKPLVJ.js';
|
|
36
|
-
import './chunk-N5FOE5PS.js';
|
|
37
|
-
import './chunk-OGFGZQA3.js';
|
|
38
|
-
import './chunk-4NPZVMJU.js';
|
|
39
38
|
import './chunk-7RQ73DLO.js';
|
|
40
|
-
import './chunk-
|
|
39
|
+
import './chunk-3CWUOFV6.js';
|
|
40
|
+
import './chunk-QOZKPLVJ.js';
|
|
41
41
|
import './chunk-CX22S5BA.js';
|
|
42
|
+
import './chunk-ECODQ7II.js';
|
|
43
|
+
import './chunk-JBJTC3UU.js';
|
|
44
|
+
import './chunk-OGFGZQA3.js';
|
|
42
45
|
import './chunk-F7CU5ABH.js';
|
|
43
46
|
import './chunk-BKO6JEZI.js';
|
|
44
|
-
import './chunk-
|
|
45
|
-
import './chunk-
|
|
46
|
-
import './chunk-
|
|
47
|
-
import './chunk-
|
|
48
|
-
import './chunk-
|
|
49
|
-
import './chunk-YRYMNBGQ.js';
|
|
50
|
-
import './chunk-GQD22KKN.js';
|
|
47
|
+
import './chunk-BMYGAGBJ.js';
|
|
48
|
+
import './chunk-NACDBXUG.js';
|
|
49
|
+
import './chunk-GOSFARMS.js';
|
|
50
|
+
import './chunk-ANPNT6PM.js';
|
|
51
|
+
import './chunk-T2Q7ISPE.js';
|
|
51
52
|
import './chunk-WZBHBH3J.js';
|
|
52
53
|
import './chunk-5QRP3MVS.js';
|
|
53
|
-
import './chunk-
|
|
54
|
-
import './chunk-
|
|
55
|
-
import './chunk-
|
|
56
|
-
import './chunk-
|
|
57
|
-
import './chunk-
|
|
58
|
-
import './chunk-
|
|
59
|
-
import './chunk-
|
|
60
|
-
import './chunk-
|
|
61
|
-
import './chunk-PLMTLGYH.js';
|
|
62
|
-
import './chunk-J5M7BSJQ.js';
|
|
54
|
+
import './chunk-W5VPCONO.js';
|
|
55
|
+
import './chunk-LXAY4A2G.js';
|
|
56
|
+
import './chunk-T4Y6SCG3.js';
|
|
57
|
+
import './chunk-ZRL6HKBY.js';
|
|
58
|
+
import './chunk-52NC2FIU.js';
|
|
59
|
+
import './chunk-MNTSH4CL.js';
|
|
60
|
+
import './chunk-X5N6KC6V.js';
|
|
61
|
+
import './chunk-N3CUDFCW.js';
|
|
63
62
|
import './chunk-EABW6AJQ.js';
|
|
64
63
|
import './chunk-RA3O54FC.js';
|
|
65
|
-
import './chunk-
|
|
66
|
-
import './chunk-
|
|
67
|
-
import './chunk-
|
|
64
|
+
import './chunk-M2ZWWTWZ.js';
|
|
65
|
+
import './chunk-N2PXGQRL.js';
|
|
66
|
+
import './chunk-BQXFBI7T.js';
|
|
67
|
+
import './chunk-ULSIJGLS.js';
|
|
68
|
+
import './chunk-G2YNJIGF.js';
|
|
68
69
|
import './chunk-XCCLFVXM.js';
|
|
70
|
+
import './chunk-ZJSNLVCE.js';
|
|
69
71
|
import './chunk-BJ3KTMDH.js';
|
|
72
|
+
import './chunk-CRB3POP4.js';
|
|
70
73
|
import './chunk-VNVZDWO3.js';
|
|
71
74
|
import './chunk-Z5GEFMRW.js';
|
|
72
75
|
import { readFileSync } from 'fs';
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
3
|
import { RecipeError, locateRecipe, readRecipe, assertBuildable, writeSanitizedRecipe, classifyProperties, SANITIZED_NAME } from './chunk-QOZKPLVJ.js';
|
|
4
|
-
import { startTimeOf, claimPidFile, RunnerAlreadyRunningError, releasePidFile } from './chunk-N5FOE5PS.js';
|
|
5
4
|
import { CLAUDE_CODE_VERSION, NODE_IMAGE, DEFAULT_BASE_IMAGE, TINI_VERSION, GH_VERSION, GH_SHA256, TINI_SHA256 } from './chunk-CX22S5BA.js';
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
5
|
+
import { claimPidFile, RunnerAlreadyRunningError, releasePidFile } from './chunk-ECODQ7II.js';
|
|
6
|
+
import { startTimeOf } from './chunk-JBJTC3UU.js';
|
|
7
|
+
import { RUNNER_DIR_MODE, repoCacheDir, imagesDir, attemptStamp, runnerDir, rootfsPathFor, RUNNER_FILE_MODE } from './chunk-N2PXGQRL.js';
|
|
8
|
+
import { withGitConfig, tokenHeader } from './chunk-BQXFBI7T.js';
|
|
8
9
|
import { mkdirSync, rmSync, existsSync, mkdtempSync, cpSync, readFileSync, writeFileSync, readdirSync, lstatSync, readlinkSync } from 'fs';
|
|
9
10
|
import { tmpdir } from 'os';
|
|
10
11
|
import { dirname, join } from 'path';
|
|
@@ -36,6 +37,10 @@ function git(cwd, args, timeoutMs, extend = (env) => env) {
|
|
|
36
37
|
);
|
|
37
38
|
});
|
|
38
39
|
}
|
|
40
|
+
function gitFailureLine(err) {
|
|
41
|
+
const lines = (err instanceof Error ? err.message : String(err)).replace(/^git [\w-]+ failed: /, "").split("\n").map((line) => line.trim()).filter((line) => line !== "");
|
|
42
|
+
return lines.find((line) => !/^warning:/i.test(line)) ?? lines[0] ?? "";
|
|
43
|
+
}
|
|
39
44
|
function defaultBranchOf(lsRemote) {
|
|
40
45
|
const match = lsRemote.match(/^ref: refs\/heads\/(\S+)\s+HEAD$/m);
|
|
41
46
|
return match ? match[1] : null;
|
|
@@ -90,7 +95,7 @@ async function readBranchHead(input) {
|
|
|
90
95
|
try {
|
|
91
96
|
out = await git(input.dir, ["ls-remote", "--heads", input.remote, `refs/heads/${input.branch}`], HEAD_TIMEOUT_MS, credential);
|
|
92
97
|
} catch (err) {
|
|
93
|
-
return { kind: "unreadable", reason: (err
|
|
98
|
+
return { kind: "unreadable", reason: gitFailureLine(err) };
|
|
94
99
|
}
|
|
95
100
|
const sha = out.match(/^([0-9a-f]{40}|[0-9a-f]{64})\trefs\/heads\//m)?.[1];
|
|
96
101
|
return sha === void 0 ? { kind: "absent" } : { kind: "found", sha };
|
|
@@ -102,9 +107,10 @@ async function fetchCommit(input) {
|
|
|
102
107
|
await git(input.dir, ["init", "--quiet"]);
|
|
103
108
|
await git(input.dir, ["fetch", "--quiet", "--depth", "1", "--no-tags", input.remote, input.commit], CLONE_TIMEOUT_MS, credential);
|
|
104
109
|
await git(input.dir, ["checkout", "--quiet", "--detach", "--force", "FETCH_HEAD"]);
|
|
110
|
+
if (input.clean === true) await git(input.dir, ["clean", "-ffdx", "--quiet"]);
|
|
105
111
|
return { ok: true };
|
|
106
112
|
} catch (err) {
|
|
107
|
-
const detail = (err
|
|
113
|
+
const detail = gitFailureLine(err);
|
|
108
114
|
return { ok: false, reason: `the fetch of ${input.commit.slice(0, 8)} from ${input.remote} failed: ${detail}` };
|
|
109
115
|
}
|
|
110
116
|
}
|
|
@@ -122,7 +128,7 @@ async function diffBetween(input) {
|
|
|
122
128
|
);
|
|
123
129
|
return { ok: true };
|
|
124
130
|
} catch (err) {
|
|
125
|
-
const detail = (err
|
|
131
|
+
const detail = gitFailureLine(err);
|
|
126
132
|
return { ok: false, reason: `the diff of ${input.head.slice(0, 8)} from ${input.base.slice(0, 8)} could not be read from ${input.remote}: ${detail}` };
|
|
127
133
|
}
|
|
128
134
|
}
|
|
@@ -189,9 +195,9 @@ function toolsDockerfile(parts) {
|
|
|
189
195
|
" && chmod 1777 /out/build",
|
|
190
196
|
...parts.guestHelper === true ? [
|
|
191
197
|
"COPY guest/outerlayer-guest /out/opt/outerlayer/bin/outerlayer-guest",
|
|
192
|
-
// The guest mounts the build's tmpfs, the kernel's file systems and the run directory over these.
|
|
198
|
+
// The guest mounts the build's tmpfs, the kernel's file systems and the run directory over these. The judge's tmpfs is mounted over its directory when the judge runs.
|
|
193
199
|
"RUN chmod 0755 /out/opt/outerlayer/bin/outerlayer-guest \\",
|
|
194
|
-
" && mkdir -p /out/outerlayer/job /out/run /out/proc /out/sys /out/dev"
|
|
200
|
+
" && mkdir -p /out/outerlayer/job /out/outerlayer/judge /out/run /out/proc /out/sys /out/dev"
|
|
195
201
|
] : [],
|
|
196
202
|
`RUN set -eu \\`,
|
|
197
203
|
` && case "$TARGETARCH" in \\`,
|
|
@@ -295,6 +301,11 @@ function splitRepository(repository) {
|
|
|
295
301
|
}
|
|
296
302
|
return { full, owner: parts[0], name: parts[1] };
|
|
297
303
|
}
|
|
304
|
+
async function fetchPinnedCommit(opts) {
|
|
305
|
+
const fetched = await fetchCommit({ remote: opts.remote, dir: opts.dir, commit: opts.commit, token: opts.token, clean: true });
|
|
306
|
+
if (!fetched.ok) throw new RecipeError("repository_unreadable", `cannot read ${opts.repository}: ${fetched.reason}`);
|
|
307
|
+
return { dir: opts.dir, defaultBranch: opts.ref, commit: opts.commit };
|
|
308
|
+
}
|
|
298
309
|
function metadataOf(image) {
|
|
299
310
|
try {
|
|
300
311
|
const parsed = JSON.parse(image.labels["devcontainer.metadata"] ?? "[]");
|
|
@@ -345,12 +356,8 @@ async function buildRepositoryImage(opts, ports) {
|
|
|
345
356
|
throw err;
|
|
346
357
|
}
|
|
347
358
|
try {
|
|
348
|
-
const
|
|
349
|
-
|
|
350
|
-
dir: cacheDir,
|
|
351
|
-
token: opts.readToken,
|
|
352
|
-
repository
|
|
353
|
-
});
|
|
359
|
+
const remote = opts.remote ?? `https://github.com/${owner}/${name}.git`;
|
|
360
|
+
const checkout = opts.pinned === void 0 ? await fetchDefaultBranch({ remote, dir: cacheDir, token: opts.readToken, repository }) : await fetchPinnedCommit({ remote, dir: cacheDir, token: opts.readToken, repository, ...opts.pinned });
|
|
354
361
|
const location = locateRecipe(checkout.dir);
|
|
355
362
|
const recipe = readRecipe(checkout.dir, location);
|
|
356
363
|
assertBuildable(checkout.dir, location, recipe);
|