@wascartech/devbot 2.1.1 → 2.3.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/README.md +17 -12
- package/dist/admin/settings-routes.js +2 -1
- package/dist/admin/settings-routes.js.map +1 -1
- package/dist/ci-lint-guard.js +88 -0
- package/dist/ci-lint-guard.js.map +1 -0
- package/dist/conflict-fix.js +69 -10
- package/dist/conflict-fix.js.map +1 -1
- package/dist/devcontainer.js +14 -2
- package/dist/devcontainer.js.map +1 -1
- package/dist/git.js +142 -45
- package/dist/git.js.map +1 -1
- package/dist/global-settings-store.js +11 -4
- package/dist/global-settings-store.js.map +1 -1
- package/dist/help.js +1 -1
- package/dist/help.js.map +1 -1
- package/dist/opencode.js +22 -4
- package/dist/opencode.js.map +1 -1
- package/dist/platform/gitealike/base.js +26 -0
- package/dist/platform/gitealike/base.js.map +1 -1
- package/dist/platform/github/index.js +26 -0
- package/dist/platform/github/index.js.map +1 -1
- package/dist/platform/gitlab/api.js +7 -1
- package/dist/platform/gitlab/api.js.map +1 -1
- package/dist/platform/gitlab/index.js +38 -4
- package/dist/platform/gitlab/index.js.map +1 -1
- package/dist/platform/gitlab/read.js +33 -2
- package/dist/platform/gitlab/read.js.map +1 -1
- package/dist/platform/gitlab/schemas-read.js +7 -0
- package/dist/platform/gitlab/schemas-read.js.map +1 -1
- package/dist/platform/gitlab/schemas.js +14 -0
- package/dist/platform/gitlab/schemas.js.map +1 -1
- package/dist/platform/port.js +3 -3
- package/dist/platform/port.js.map +1 -1
- package/dist/platform/types.js.map +1 -1
- package/dist/prompt.js.map +1 -1
- package/dist/run-files.js +9 -8
- package/dist/run-files.js.map +1 -1
- package/dist/runner.js +166 -27
- package/dist/runner.js.map +1 -1
- package/dist/settings-store.js +28 -4
- package/dist/settings-store.js.map +1 -1
- package/dist/types/global-settings.js +6 -0
- package/dist/types/global-settings.js.map +1 -1
- package/dist/types/project-settings.js +1 -0
- package/dist/types/project-settings.js.map +1 -1
- package/dist/webhook.js +86 -29
- package/dist/webhook.js.map +1 -1
- package/dist/work-item-branch-store.js +14 -5
- package/dist/work-item-branch-store.js.map +1 -1
- package/migrations/0032_confidential_work_items.sql +11 -0
- package/migrations/0033_work_item_branch_adopted.sql +6 -0
- package/package.json +4 -1
- package/public/assets/{DashboardSidebarCollapse-rIuzCmVm.js → DashboardSidebarCollapse-CWmehYha.js} +1 -1
- package/public/assets/{DashboardToolbar-DFCUqZ4Z.js → DashboardToolbar-DHcR2yAt.js} +1 -1
- package/public/assets/{ErrorLogModal.vue_vue_type_script_setup_true_lang-BCyNIf1E.js → ErrorLogModal.vue_vue_type_script_setup_true_lang-B0yvkhY5.js} +1 -1
- package/public/assets/{ErrorLogsPage-DyYK2Rop.js → ErrorLogsPage-ClPltTSr.js} +1 -1
- package/public/assets/{LogSlideover.vue_vue_type_script_setup_true_lang-33xie7TE.js → LogSlideover.vue_vue_type_script_setup_true_lang-F1i8DRzf.js} +1 -1
- package/public/assets/{OverviewPage-CFfa0uwg.js → OverviewPage-DWz8IJ46.js} +1 -1
- package/public/assets/{PageGrid-CBROIU87.js → PageGrid-DelloK5f.js} +1 -1
- package/public/assets/{PeriodRangePicker.vue_vue_type_script_setup_true_lang-DiFUNem7.js → PeriodRangePicker.vue_vue_type_script_setup_true_lang-YOwfelec.js} +1 -1
- package/public/assets/ProjectDetailPage-QEdo9Ytu.js +1 -0
- package/public/assets/{ProjectsPage-CFx8-elJ.js → ProjectsPage-BJzRIlvb.js} +1 -1
- package/public/assets/{RunDetailSlideover.vue_vue_type_script_setup_true_lang-DopYYmCT.js → RunDetailSlideover.vue_vue_type_script_setup_true_lang-BLDs3UaU.js} +1 -1
- package/public/assets/{RunsPage-CRnnXU4P.js → RunsPage-BYlDZjwk.js} +1 -1
- package/public/assets/{Select-Bvx32Diz.js → Select-DGVDts9_.js} +1 -1
- package/public/assets/{SelectMenu-BjMxc4VB.js → SelectMenu-B6n06FSV.js} +1 -1
- package/public/assets/{SettingsPage-Bb6LM3wO.js → SettingsPage-BpLc2GAe.js} +21 -21
- package/public/assets/{TimeCell.vue_vue_type_script_setup_true_lang-DW_UB0Fu.js → TimeCell.vue_vue_type_script_setup_true_lang-BNWTJF4u.js} +1 -1
- package/public/assets/{UsagePage-BLMDEsv-.js → UsagePage-CSt7StoP.js} +1 -1
- package/public/assets/{VolumesPage-CxcLc3L2.js → VolumesPage-Cxav6H5n.js} +1 -1
- package/public/assets/WebhookConfigPanel.vue_vue_type_script_setup_true_lang-DQNacZEe.js +1 -0
- package/public/assets/{WorkItemCell.vue_vue_type_script_setup_true_lang-BQn6vTjd.js → WorkItemCell.vue_vue_type_script_setup_true_lang-DAJMkNI8.js} +1 -1
- package/public/assets/{index-C5RBBrPj.js → index-Cs2OnrL7.js} +2 -2
- package/public/assets/{index-BMbMibyb.js → index-RZx6yIXX.js} +1 -1
- package/public/assets/{usage-format-jsb31_O8.js → usage-format-RcSEOPCq.js} +1 -1
- package/public/assets/{useManagedProjects-8rtjRqVJ.js → useManagedProjects-DnOY5lQq.js} +1 -1
- package/public/assets/{useRouteTab-DfwrcMic.js → useRouteTab-B-Vrl8p9.js} +1 -1
- package/public/index.html +1 -1
- package/public/assets/ProjectDetailPage-CreyvUit.js +0 -1
- package/public/assets/WebhookConfigPanel.vue_vue_type_script_setup_true_lang-B2V2GF6b.js +0 -1
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@ DevBot is **forge-agnostic**: a platform abstraction layer supports **GitLab**,
|
|
|
9
9
|
1. The forge sends a webhook when the bot account is `@mentioned` in a work item (comment on the work item, or work item creation with a mention in the description).
|
|
10
10
|
2. The mention is parsed: `@devbot /build <prompt>` triggers **build mode**; anything else triggers plan mode (the default).
|
|
11
11
|
3. DevBot starts a Podman container with a per-work-item named volume (`devbot-wi-<id>`), bind-mounting the OpenCode config read-only.
|
|
12
|
-
4. The container clones the repo (first run) or fetches (subsequent runs). On first run it clones with a fallback chain: `wi-<number>` (prior WIP branch if it exists remotely) → the `/base` target branch if given, else the first existing branch from the global base-branches list tried **top-to-bottom** (default `dev,master` → tries `dev` then `master`, set in the WebUI). A `/branch <name>` mention overrides that work-branch name (stored per work item, first naming only
|
|
12
|
+
4. The container clones the repo (first run) or fetches (subsequent runs). On first run it clones with a fallback chain: `wi-<number>` (prior WIP branch if it exists remotely) → the `/base` target branch if given, else the first existing branch from the global base-branches list tried **top-to-bottom** (default `dev,master` → tries `dev` then `master`, set in the WebUI). A `/branch <name>` mention overrides that work-branch name (stored per work item, first naming only). A name that does not exist is created; an existing **unprotected** branch is adopted with its history preserved (fast-forward only); a protected or unverifiable branch is rejected. For a newly created branch, build mode force-checks-out the work branch off whatever HEAD landed on; plan mode stays on the successful clone's branch. An adopted branch is cloned directly and never force-reset. If neither the work branch nor any configured branch exists remotely (e.g. a brand-new repo with no branches), the run aborts with an actionable `⚠️ No base branch found` note — no bare-clone fall-through. On subsequent runs it fetches and checks out the work branch (build mode pulls --rebase; plan mode tolerates a missing branch). With `GIT_SUBMODULES_ENABLED` (default `true`), clone and each fetch also run `git submodule update --init --recursive` (best-effort; see [Git submodules](#git-submodules)).
|
|
13
13
|
5. OpenCode runs with `--continue` (one session per work item, resumed across mentions) and `--format json`. The agent is `plan` or `build` per the mode.
|
|
14
14
|
6. **Build mode only**: the container commits and pushes to the branch. Plan mode makes no git changes.
|
|
15
15
|
7. DevBot parses the JSON output and extracts assistant `text` parts only. In build mode it also extracts the agent's ` ```mr ` content block (title + description) from the reply, stripping it from the comment text.
|
|
@@ -32,7 +32,7 @@ The full command reference — every token, its parsing rules, combinations, and
|
|
|
32
32
|
|---|---|
|
|
33
33
|
| `/build` | build mode (existing) |
|
|
34
34
|
| `/base <branch>` | set the base/target branch for this work item's first run. Overrides the global base-branch walk entirely (hard per-work-item override) and retargets the MR (build mode). First-run only: on subsequent runs it's stripped and a `⚠️ /base '<branch>' ignored — work item already initialized.` note is posted. Rejects the whole mention if the branch is missing on the remote or the name has unsafe characters. Persists per work item (first-write-wins); cleared by `/reset` and work-item close. May appear anywhere, like `/build`; duplicate `/base` in one mention → last wins. |
|
|
35
|
-
| `/branch <name>` | name this work item's work branch for every run (default `wi-<number>`). Honored on the **first naming only**: the name is stored per work item (first-write-wins) and reused on later runs, including after `/reset` and work-item close.
|
|
35
|
+
| `/branch <name>` | name this work item's work branch for every run (default `wi-<number>`). Honored on the **first naming only**: the name is stored per work item (first-write-wins) and reused on later runs, including after `/reset` and work-item close. Three outcomes: an absent branch is created on the first run; an existing unprotected branch is **adopted** (checked out with its remote commits intact, committed on, pushed — fast-forward only, never force-pushed or rebased); a protected branch is rejected. Protection that cannot be read (forge error, driver/field unavailable) also rejects the whole mention, fail-closed. An unsafe name is rejected before lookup. On an adopted branch `/force-push` and `/fix-conflicts` are refused, and a moved remote refuses the push with a manual-rebase note. A later, different `/branch` on an already-named work item is ignored with a `⚠️` note. May appear anywhere, like `/build`; duplicate `/branch` in one mention → last wins. |
|
|
36
36
|
| `/agent <name> <segment>` | route `<segment>` to subagent `<name>` (case-insensitive, `.md` suffix optional). May appear multiple times in one mention, on any lines. `<segment>` is the rest of the line after the `/agent <name>` token. |
|
|
37
37
|
| `/force-push` | standalone push-only command (no agent run) **or** a build modifier. Alone, it dispatches a push task that force-pushes the work item's existing local `wi-<iid>` branch with `--force-with-lease` — no opencode run, no clone, no commit; it fails with an actionable note if the workspace or branch doesn't exist. Combined with `/build`, it keeps the original meaning: run the agent, then force-push its result. Stripped from the prompt wherever it appears, like `/build`. |
|
|
38
38
|
| `/push` | standalone push-only command (no agent run) **or** a build modifier. Alone, it publishes the work item's existing local branch with a plain fast-forward push (no force); if nothing changed it posts `ℹ️ Nothing to push`. Combined with `/build`, it forces the run's host-side push even when the global/project auto-push setting is off. Stripped from the prompt wherever it appears. |
|
|
@@ -400,10 +400,11 @@ Infrastructure and identity variables only — provider, model, plugin, base-bra
|
|
|
400
400
|
- **Run timeout**: runaway agents are killed after `PLAN_TIMEOUT_MS` (plan mode) or `BUILD_TIMEOUT_MS` (build mode). The podman container is `rm -f`'d on timeout, not just the client process. A run that goes completely silent for `RUN_STALL_TIMEOUT_MS` is killed earlier with a distinct "stalled" note (env-only; `0` disables) — this bounds a wedged opencode process or a model looping on a sandbox-blocked tool call.
|
|
401
401
|
- **In-flight stop**: `/stop` (work-item scope) or the WebUI row **Stop** button (task scope) sets a durable `cancel_requested` flag on the queued/running row and `rm -f`s the work item's phase containers. The runner checks the flag at each phase boundary (post-attachment, post-clone/sync, post-run, pre-push, pre-MR) and unwinds as a clean stop: no `⚠️` error reply, no error-log row, and no push/MR. Authorization is the same as any mention (Developer+ AND author/assignee); a stop works even when the bot is unconfigured. The flag is durable so a crash mid-stop does not replay the task on restart (`purgeCancelled` runs before replay). The per-work-item volume is untouched — use `/reset` to discard it.
|
|
402
402
|
- **No silent rebase loss**: if `git pull --rebase` fails on a diverged branch, the run aborts with a note rather than discarding local commits.
|
|
403
|
-
- **Force push is opt-in and
|
|
404
|
-
- **Branch naming is fail-closed**: `/branch <name>` names the work branch on the first naming only
|
|
405
|
-
- **
|
|
406
|
-
- **
|
|
403
|
+
- **Force push is opt-in, leased, and never on an adopted branch**: `/force-push` overwrites a DevBot-created remote branch using `--force-with-lease` (never plain `--force`). The lease refuses the push if the remote moved since the run's fetch, so a concurrent/upstream change is not clobbered. It only ever touches the work item branch — the MR target branch is untouched. With `/build` the host-side HEAD guard and fallback-commit rescue still apply. Standalone (no `/build`), `/force-push` runs no agent: it just fetches and force-pushes the existing local branch (a repair action after a normal push was refused); if the workspace or the local branch doesn't exist it posts an actionable note and pushes nothing. On an **adopted** branch force-push is rejected before dispatch.
|
|
404
|
+
- **Branch naming is fail-closed, and existing unprotected branches are adoptable**: `/branch <name>` names the work branch on the first naming only. An absent name is created; an existing **unprotected** branch is adopted with its remote history preserved (fast-forward only); a protected branch, an unsafe name, a forge lookup failure, or a driver/field that cannot report protection rejects the mention and runs nothing. The chosen name and its adopted/created state are stored per work item and reused on every later run (including after `/reset` and close); the branch is never auto-renamed.
|
|
405
|
+
- **Adopted branches are fast-forward only**: the first run clones the branch directly (never `checkout -B`), later runs fetch and fast-forward, and the push is a plain fast-forward. If the remote moved so a fast-forward is impossible, the push is refused with a note naming the branch and asking for a manual rebase — no force, no rewrite. `/force-push` and conflict resolution (standalone `/fix-conflicts` and the auto-fix path) are refused on an adopted branch because both rewrite shared history.
|
|
406
|
+
- **Rewrite-aware publish**: the post-build host-side push detects a rewritten branch history (e.g. after a rebase or a conflict auto-fix) and, when the remote still equals the run's **starting** tip, publishes with a SHA-pinned `--force-with-lease` instead of failing with git's raw fast-forward hint. If the remote moved during the run, the push is refused with a clean "re-run" note — it never clobbers commits it did not produce. This rewrite path is unreachable for adopted branches, which only ever fast-forward. The fallback-commit rescue also refuses to commit a working tree that still contains conflict markers.
|
|
407
|
+
- **Conflict auto-fix is opt-in and fails closed**: when enabled, DevBot checks the branch against its MR target and delegates resolution to a direct build run (rebase-first, merge fallback; the resolver never pushes). It only opens/updates the MR after a clean re-check; an unresolved conflict leaves the branch pushed but opens no MR and posts the conflicting paths. With the switch off there is no check and no behavior change. On an adopted branch the resolver is skipped (it would rewrite shared history) with a note asking for a manual rebase.
|
|
407
408
|
- **Per-run auth**: the provider `auth.json`, the per-run `opencode.json` (carrying the scoped MCP bearer token), and pasted `mcp-auth.json` are written at mode 0600 into the per-work-item **xdg volume** (`devbot-wi-<id>-xdg`, mounted at `/home/devbot/.xdg`) — outside the cloned repository, so the agent's `git add -A` can never commit them. No keys are baked into the image.
|
|
408
409
|
|
|
409
410
|
## Known ceilings (documented, not built)
|
|
@@ -447,7 +448,8 @@ npm run test:path-sandbox # path policy + guard plugin parity self-check
|
|
|
447
448
|
npm run test:shell-sandbox # managed config + bwrap shell wrapper self-check
|
|
448
449
|
npm run test:podman-volume # real-Podman volume + readFileFromVolume deny/symlink self-check
|
|
449
450
|
npm run test:podman-run # real-Podman runPodmanCapture + logs self-check
|
|
450
|
-
npm run test:nested-podman # nested rootless Podman smoke (
|
|
451
|
+
npm run test:nested-podman # nested rootless Podman smoke (manual; needs a rootless host + builder image)
|
|
452
|
+
npm run test:nested-podman-wiring # hermetic fail-versus-skip wiring self-check
|
|
451
453
|
npm run test:devcontainer # nested-podman flag/driver builder self-check
|
|
452
454
|
npm run test:devcontainer-wiring # store volume lifecycle self-check
|
|
453
455
|
npm run test:platform-webhooks # platform webhook parse + signature self-check
|
|
@@ -487,14 +489,17 @@ by runtime requirement:
|
|
|
487
489
|
| --- | --- | --- |
|
|
488
490
|
| `hermetic` (default for the `test` job) | everything except the tooling suites | slim `node:22-slim` |
|
|
489
491
|
| `integration` | `test:podman-*`, `test:ui-e2e`, `test:shell-sandbox` | privileged runner (`test:integration`) |
|
|
490
|
-
| `nested` | `test:nested-podman` |
|
|
492
|
+
| `nested` | `test:nested-podman` | manual (`test:nested-podman`; needs a rootless host) |
|
|
491
493
|
| `all` | every suite (default with no env var) | local `npm test` |
|
|
492
494
|
|
|
493
495
|
The integration suites self-skip when Podman/Chromium/bubblewrap is absent, but
|
|
494
|
-
the CI integration
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
496
|
+
the CI integration job sets `DEVBOT_REQUIRE_PODMAN=1`, which turns a failed
|
|
497
|
+
Podman probe (or a non-working nested run) into a hard failure with the captured
|
|
498
|
+
reason rather than a silent skip — so missing coverage cannot hide. On a dev
|
|
499
|
+
host without the tooling the suites skip gracefully.
|
|
500
|
+
|
|
501
|
+
`test:nested-podman` is a manual, non-blocking CI job because the suite needs a
|
|
502
|
+
rootless-capable host. Current CI reality: with no rootless-capable runner, the nested sandbox has no CI coverage at all — the manual job is a probe, and the hermetic wiring check tests the wiring, not the sandbox.
|
|
498
503
|
|
|
499
504
|
For a manual interactive pass, `node --experimental-sqlite --import tsx
|
|
500
505
|
scripts/e2e-serve.ts` seeds a temp DB and serves the built app with the same
|
|
@@ -52,6 +52,7 @@ function globalDefaults() {
|
|
|
52
52
|
autoMr: g.autoMr ? "true" : "false",
|
|
53
53
|
autoResolveConflicts: g.autoResolveConflicts ? "true" : "false",
|
|
54
54
|
ciFailAutoReport: g.ciFailAutoReport ? "true" : "false",
|
|
55
|
+
allowConfidentialWorkItems: g.allowConfidentialWorkItems ? "true" : "false",
|
|
55
56
|
lspServers: g.lspServers.join(","),
|
|
56
57
|
lspDisabled: "",
|
|
57
58
|
};
|
|
@@ -69,7 +70,7 @@ export function mountSettingsRoutes(app) {
|
|
|
69
70
|
return res.status(404).json({ error: "not managed" });
|
|
70
71
|
}
|
|
71
72
|
const settings = getProjectSettings(projectId) ?? {
|
|
72
|
-
planModel: "", buildModel: "", planVariant: "", buildVariant: "", plugins: "", baseBranches: "", lspServers: "", lspDisabled: "", builderImage: "", buildWorkflow: "", mrDescription: "", minRole: "", requireAuthorOrAssignee: "", autoPush: "", autoMr: "", autoResolveConflicts: "", ciFailAutoReport: "", assignee: "",
|
|
73
|
+
planModel: "", buildModel: "", planVariant: "", buildVariant: "", plugins: "", baseBranches: "", lspServers: "", lspDisabled: "", builderImage: "", buildWorkflow: "", mrDescription: "", minRole: "", requireAuthorOrAssignee: "", autoPush: "", autoMr: "", autoResolveConflicts: "", ciFailAutoReport: "", allowConfidentialWorkItems: "", assignee: "",
|
|
73
74
|
};
|
|
74
75
|
logReq(req, "debug", "get settings", { projectId });
|
|
75
76
|
return res.json({ settings, defaults: globalDefaults() });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"settings-routes.js","sourceRoot":"","sources":["../../src/admin/settings-routes.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"settings-routes.js","sourceRoot":"","sources":["../../src/admin/settings-routes.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
// Guard publishing when the branch diff touches the project's CI entry file
|
|
2
|
+
// (work item #116). A CI configuration GitLab cannot parse still produces a
|
|
3
|
+
// pipeline — a red one with no jobs to open — so the forge linter must answer
|
|
4
|
+
// *before* the branch is pushed. The lint is advisory infrastructure: an outage
|
|
5
|
+
// or an unsupported forge degrades to an explicit report line, never a block.
|
|
6
|
+
import { getPlatform } from "./platform/index.js";
|
|
7
|
+
import { PlatformHttpError, UnsupportedError } from "./platform/types.js";
|
|
8
|
+
import { inspectWorkingTreeFile } from "./git.js";
|
|
9
|
+
import { log } from "./logger.js";
|
|
10
|
+
const SKIPPED = { status: "skipped", errors: [], warnings: [] };
|
|
11
|
+
export function formatCiLintReport(result) {
|
|
12
|
+
if (result.status === "skipped")
|
|
13
|
+
return null;
|
|
14
|
+
if (result.status === "unavailable") {
|
|
15
|
+
return `ci/lint unavailable: ${result.detail ?? "unknown error"}`;
|
|
16
|
+
}
|
|
17
|
+
const counts = `${result.errors.length} errors, ${result.warnings.length} warnings`;
|
|
18
|
+
if (result.status === "valid")
|
|
19
|
+
return `ci/lint: valid (${counts})`;
|
|
20
|
+
const lines = [`ci/lint: invalid (${counts})`];
|
|
21
|
+
if (result.errors.length > 0) {
|
|
22
|
+
lines.push("", "Errors:", ...result.errors.map((e) => `- ${e}`));
|
|
23
|
+
}
|
|
24
|
+
if (result.warnings.length > 0) {
|
|
25
|
+
lines.push("", "Warnings:", ...result.warnings.map((w) => `- ${w}`));
|
|
26
|
+
}
|
|
27
|
+
return lines.join("\n");
|
|
28
|
+
}
|
|
29
|
+
function describeError(e) {
|
|
30
|
+
if (e instanceof UnsupportedError)
|
|
31
|
+
return e.message;
|
|
32
|
+
if (e instanceof PlatformHttpError) {
|
|
33
|
+
return e.body ? `${e.status} ${e.body}` : String(e.status);
|
|
34
|
+
}
|
|
35
|
+
const message = e instanceof Error ? e.message : String(e);
|
|
36
|
+
return message.length > 300 ? `${message.slice(0, 300)}…` : message;
|
|
37
|
+
}
|
|
38
|
+
// Pure decision step: inspection + linter injected so the invalid path is
|
|
39
|
+
// testable without podman or a forge.
|
|
40
|
+
export async function evaluateCiLint(args) {
|
|
41
|
+
const { entryFile, inspection, ref } = args;
|
|
42
|
+
if (!entryFile || !ref || !inspection.touched || inspection.content === null)
|
|
43
|
+
return SKIPPED;
|
|
44
|
+
try {
|
|
45
|
+
const result = await args.lint(inspection.content, ref);
|
|
46
|
+
return {
|
|
47
|
+
status: result.valid ? "valid" : "invalid",
|
|
48
|
+
errors: result.errors,
|
|
49
|
+
warnings: result.warnings,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
catch (e) {
|
|
53
|
+
log.warn("ci/lint unavailable", { err: e });
|
|
54
|
+
return { status: "unavailable", errors: [], warnings: [], detail: describeError(e) };
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
// Orchestrate the guard: discover the forge entry file, inspect the working
|
|
58
|
+
// tree, ask the forge, and post the outcome line to the work item. Returns the
|
|
59
|
+
// verdict so the caller can refuse to publish on `invalid`.
|
|
60
|
+
export async function runCiLintGuard(ctx) {
|
|
61
|
+
if (!ctx.baseBranch)
|
|
62
|
+
return SKIPPED;
|
|
63
|
+
const entryFile = getPlatform().ci.lintEntryFile();
|
|
64
|
+
if (!entryFile)
|
|
65
|
+
return SKIPPED;
|
|
66
|
+
let inspection;
|
|
67
|
+
try {
|
|
68
|
+
inspection = await inspectWorkingTreeFile({ workItemId: ctx.workItemId, baseBranch: ctx.baseBranch, entryFile }, ctx.envVars, ctx.builderImage);
|
|
69
|
+
}
|
|
70
|
+
catch (e) {
|
|
71
|
+
log.warn("ci/lint inspection failed", { workItemId: ctx.workItemId, err: e });
|
|
72
|
+
return { status: "unavailable", errors: [], warnings: [], detail: describeError(e) };
|
|
73
|
+
}
|
|
74
|
+
const result = await evaluateCiLint({
|
|
75
|
+
entryFile,
|
|
76
|
+
inspection,
|
|
77
|
+
ref: ctx.baseBranch,
|
|
78
|
+
lint: (content, ref) => getPlatform().ci.lint(ctx.projectId, { content, ref }),
|
|
79
|
+
});
|
|
80
|
+
const report = formatCiLintReport(result);
|
|
81
|
+
if (report) {
|
|
82
|
+
await getPlatform().workItems
|
|
83
|
+
.postComment(ctx.projectId, ctx.workItemNumber, report)
|
|
84
|
+
.catch((e) => log.warn("ci/lint report note failed", { projectId: ctx.projectId, err: e }));
|
|
85
|
+
}
|
|
86
|
+
return result;
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=ci-lint-guard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ci-lint-guard.js","sourceRoot":"","sources":["../src/ci-lint-guard.ts"],"names":[],"mappings":"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"}
|
package/dist/conflict-fix.js
CHANGED
|
@@ -1,4 +1,37 @@
|
|
|
1
1
|
import { shq } from "./redact.js";
|
|
2
|
+
// Force every host-side fetch to keep its transferred objects in a pack instead
|
|
3
|
+
// of unpacking a small transfer into loose objects. `git fetch` unpacks
|
|
4
|
+
// transfers below `fetch.unpackLimit` (default 100) into `.git/objects/<ab>/`.
|
|
5
|
+
// After the UID split (#81) the workspace can hold object directories owned by
|
|
6
|
+
// the `agent` UID (1001) or nested-Podman subuids, which the host-side
|
|
7
|
+
// push/sync container (devbot) can read but not write. git then aborts with
|
|
8
|
+
// "insufficient permission for adding an object to repository database
|
|
9
|
+
// .git/objects". A pack is written only into `objects/pack`, created by the
|
|
10
|
+
// clone as a group-writable devbot directory, so the fetch never needs to
|
|
11
|
+
// write into a foreign-owned fanout directory.
|
|
12
|
+
// unpackLimit=0 is NOT the neutral value (some versions treat it as "always
|
|
13
|
+
// unpack"); 1 means "never unpack a non-empty transfer".
|
|
14
|
+
export const SAFE_FETCH_FLAGS = "-c fetch.unpackLimit=1 -c transfer.unpackLimit=1";
|
|
15
|
+
// Printed immediately after a successful fetch. Its presence (or absence) in
|
|
16
|
+
// stdout tells the caller which stage failed when an object-database write
|
|
17
|
+
// error appears: a failed fetch means the local workspace object database,
|
|
18
|
+
// while a fetch that succeeded means the remote's object database rejected
|
|
19
|
+
// the push.
|
|
20
|
+
export const FETCH_OK_MARKER = "FETCH_OK";
|
|
21
|
+
// Compose a safe `fetch origin` chain step. The extraHeader is the token-bearing
|
|
22
|
+
// `git -c http.extraHeader=…` prefix; `-c` options must precede the
|
|
23
|
+
// subcommand, so the flags are appended to the header.
|
|
24
|
+
export function safeFetchOrigin(extraHeader) {
|
|
25
|
+
return `${extraHeader} ${SAFE_FETCH_FLAGS} fetch origin && echo ${FETCH_OK_MARKER}`;
|
|
26
|
+
}
|
|
27
|
+
// True when a git failure is an object-database write error. git uses this same
|
|
28
|
+
// message for a permission error (EACCES/EROFS) and for a full disk (ENOSPC),
|
|
29
|
+
// and prints it on both the local fetch path and the receiving side of a push.
|
|
30
|
+
export function isObjectDatabaseWriteFailure(text) {
|
|
31
|
+
return (/insufficient permission for adding an object to repository database/i.test(text) ||
|
|
32
|
+
/unpack-objects abnormal exit/i.test(text) ||
|
|
33
|
+
/unpack-objects failed/i.test(text));
|
|
34
|
+
}
|
|
2
35
|
// Pure conflict-fix helpers (work item #56): the git shell-script builders,
|
|
3
36
|
// their result parsers, the resolver prompt/result parser, and the note
|
|
4
37
|
// formatters. Deliberately dependency-light (no config/podman) so the contract
|
|
@@ -20,7 +53,7 @@ export function conflictCheckScript(target, branch, extraHeader) {
|
|
|
20
53
|
"cd /workspace",
|
|
21
54
|
"git rebase --abort 2>/dev/null || true",
|
|
22
55
|
"git merge --abort 2>/dev/null || true",
|
|
23
|
-
`${extraHeader} fetch origin`,
|
|
56
|
+
`${extraHeader} ${SAFE_FETCH_FLAGS} fetch origin`,
|
|
24
57
|
`echo "TIP:$(git rev-parse origin/${shq(branch)} 2>/dev/null || true)"`,
|
|
25
58
|
`git rev-parse --verify --quiet origin/${shq(target)} >/dev/null || { echo "CHECK_FAILED:missing-target"; exit 8; }`,
|
|
26
59
|
`git merge-tree --write-tree --name-only origin/${shq(target)} ${shq(branch)}`,
|
|
@@ -66,26 +99,36 @@ export function parseConflictCheckResult(code, stdout) {
|
|
|
66
99
|
// (we only rewrote our own earlier commits).
|
|
67
100
|
// else (remote moved) → REMOTE_MOVED, exit 9 (fail closed, no clobber).
|
|
68
101
|
// `force` (/force-push) short-circuits to an unconditional leased push.
|
|
69
|
-
|
|
102
|
+
// An ADOPTED branch is fast-forward only: even `force` is ignored and a
|
|
103
|
+
// non-ancestor remote emits ADOPTED_DIVERGED (exit 12), never a lease push.
|
|
104
|
+
export function publishScript(workItemNumber, branch, extraHeader, preRunTip, force = false, adopted = false) {
|
|
70
105
|
const b = shq(branch);
|
|
71
106
|
const lease = `--force-with-lease=refs/heads/${branch}:${preRunTip}`;
|
|
72
107
|
const markerCheck = `if git diff --cached -U0 | grep -qE '^\\+.*(<<<<<<<|=======|>>>>>>>)'; then echo "CONFLICT_MARKERS"; exit 10; fi`;
|
|
73
|
-
const decide =
|
|
74
|
-
?
|
|
75
|
-
: [
|
|
108
|
+
const decide = adopted
|
|
109
|
+
? [
|
|
76
110
|
`if ! git rev-parse --verify --quiet origin/${b} >/dev/null; then`,
|
|
77
111
|
` ${extraHeader} push origin ${b} && echo PUSHED;`,
|
|
78
112
|
`elif git merge-base --is-ancestor origin/${b} HEAD; then`,
|
|
79
113
|
` if test -n "$(git log --format=%H origin/${b}..HEAD)"; then ${extraHeader} push origin ${b} && echo PUSHED; else echo NO_COMMITS; fi;`,
|
|
80
|
-
`
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
114
|
+
`else echo "ADOPTED_DIVERGED:${branch}"; exit 12; fi`,
|
|
115
|
+
].join("\n")
|
|
116
|
+
: force
|
|
117
|
+
? `if ! git rev-parse --verify --quiet origin/${b} >/dev/null; then ${extraHeader} push origin ${b} && echo PUSHED; else ${extraHeader} push origin ${b} --force-with-lease && echo FORCE_PUSHED; fi`
|
|
118
|
+
: [
|
|
119
|
+
`if ! git rev-parse --verify --quiet origin/${b} >/dev/null; then`,
|
|
120
|
+
` ${extraHeader} push origin ${b} && echo PUSHED;`,
|
|
121
|
+
`elif git merge-base --is-ancestor origin/${b} HEAD; then`,
|
|
122
|
+
` if test -n "$(git log --format=%H origin/${b}..HEAD)"; then ${extraHeader} push origin ${b} && echo PUSHED; else echo NO_COMMITS; fi;`,
|
|
123
|
+
`elif test "$(git rev-parse origin/${b})" = ${shq(preRunTip)}; then`,
|
|
124
|
+
` ${extraHeader} push origin ${b} ${lease} && echo FORCE_PUSHED;`,
|
|
125
|
+
`else echo REMOTE_MOVED; exit 9; fi`,
|
|
126
|
+
].join("\n");
|
|
84
127
|
return [
|
|
85
128
|
"cd /workspace",
|
|
86
129
|
`test "$(git rev-parse --abbrev-ref HEAD)" = ${b} || { echo "WRONG_HEAD:$(git rev-parse --abbrev-ref HEAD)"; exit 7; }`,
|
|
87
130
|
`if test -n "$(git status --porcelain)"; then git add -A && { ${markerCheck}; } && git commit -m "chore: fallback commit for uncommitted agent work (#${workItemNumber})" --no-verify && echo FALLBACK_COMMITTED; fi`,
|
|
88
|
-
|
|
131
|
+
safeFetchOrigin(extraHeader),
|
|
89
132
|
decide,
|
|
90
133
|
].join(" && ");
|
|
91
134
|
}
|
|
@@ -97,6 +140,7 @@ export function parsePublishResult(stdout) {
|
|
|
97
140
|
fallbackCommitted: stdout.includes("FALLBACK_COMMITTED"),
|
|
98
141
|
remoteMoved: stdout.includes("REMOTE_MOVED"),
|
|
99
142
|
rewritten: stdout.includes("REWRITTEN"),
|
|
143
|
+
adoptedDiverged: stdout.includes("ADOPTED_DIVERGED"),
|
|
100
144
|
};
|
|
101
145
|
}
|
|
102
146
|
// ---- Resolver --------------------------------------------------------------
|
|
@@ -154,6 +198,21 @@ export function formatUnresolvedNote(target, files) {
|
|
|
154
198
|
`The branch was pushed without the merge request. Resolve the conflicts manually and re-run \`/mr\`, ` +
|
|
155
199
|
`or disable conflict auto-fix in the project settings.`);
|
|
156
200
|
}
|
|
201
|
+
// Adopted branches share history with other users: DevBot may only fast-forward
|
|
202
|
+
// them. A non-ancestor remote means someone else moved the branch; the user
|
|
203
|
+
// must rebase locally and push the result.
|
|
204
|
+
export function formatAdoptedPushRefusedNote(branch) {
|
|
205
|
+
return (`⚠️ Push refused — remote branch \`${branch}\` moved and an adopted branch is ` +
|
|
206
|
+
`fast-forward only. Rebase manually, then push. Nothing was forced.`);
|
|
207
|
+
}
|
|
208
|
+
export function formatAdoptedForceRefusedNote(branch) {
|
|
209
|
+
return (`⚠️ /force-push is not available on adopted branch \`${branch}\` — its history ` +
|
|
210
|
+
`is shared and can only be fast-forwarded. Rebase manually, then push.`);
|
|
211
|
+
}
|
|
212
|
+
export function formatAdoptedConflictRefusedNote(branch) {
|
|
213
|
+
return (`⚠️ Conflict resolution is not available on adopted branch \`${branch}\` — it ` +
|
|
214
|
+
`rebases the branch and rewrites shared history. Rebase it manually and push the result.`);
|
|
215
|
+
}
|
|
157
216
|
// Fix-only note for the standalone /fix-conflicts task: no publish happened, so
|
|
158
217
|
// the branch is untouched when resolution fails. Never mentions an MR step.
|
|
159
218
|
export function formatFixOnlyUnresolvedNote(target, files) {
|
package/dist/conflict-fix.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conflict-fix.js","sourceRoot":"","sources":["../src/conflict-fix.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAElC,4EAA4E;AAC5E,0EAA0E;AAC1E,iFAAiF;AACjF,8EAA8E;AAC9E,uEAAuE;AAEvE,+EAA+E;AAE/E,mDAAmD;AACnD,gFAAgF;AAChF,8EAA8E;AAC9E,kDAAkD;AAClD,2EAA2E;AAC3E,mEAAmE;AACnE,iFAAiF;AACjF,yCAAyC;AACzC,iFAAiF;AACjF,qEAAqE;AACrE,MAAM,UAAU,mBAAmB,CAAC,MAAc,EAAE,MAAc,EAAE,WAAmB;IACrF,OAAO;QACL,eAAe;QACf,wCAAwC;QACxC,uCAAuC;QACvC,GAAG,WAAW,eAAe;
|
|
1
|
+
{"version":3,"file":"conflict-fix.js","sourceRoot":"","sources":["../src/conflict-fix.ts"],"names":[],"mappings":"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"}
|
package/dist/devcontainer.js
CHANGED
|
@@ -31,6 +31,17 @@ export function hasFuseDevice(path = "/dev/fuse") {
|
|
|
31
31
|
// container artifacts cannot leak into the git diff. graphroot/runroot are
|
|
32
32
|
// separate subdirs so a runroot cleanup can never touch the image store.
|
|
33
33
|
export const PODMAN_STORE_DIR = "/home/devbot/.local/share/containers";
|
|
34
|
+
// The builder image creates `devbot` as its first regular user, uid/gid 1000
|
|
35
|
+
// (docker/Dockerfile.builder). Pin the container-side keep-id mapping to that
|
|
36
|
+
// id instead of inheriting the host account's uid number: a system account
|
|
37
|
+
// (uid < 1000) or a uid in 1002..65536 lands inside the subordinate range the
|
|
38
|
+
// inner runtime asks the kernel to map, and newuidmap rejects the whole map
|
|
39
|
+
// (podman exits 125). Pinning also keeps the credential owner at container id
|
|
40
|
+
// 1000, outside the inner subordinate ranges, so the agent-sandbox DAC
|
|
41
|
+
// boundary holds regardless of the host uid.
|
|
42
|
+
export const DEVBOT_CONTAINER_UID = 1000;
|
|
43
|
+
export const DEVBOT_CONTAINER_GID = 1000;
|
|
44
|
+
export const NESTED_PODMAN_USERNS = `--userns=keep-id:uid=${DEVBOT_CONTAINER_UID},gid=${DEVBOT_CONTAINER_GID}`;
|
|
34
45
|
// Resolve the effective storage driver. "auto" probes for /dev/fuse at startup:
|
|
35
46
|
// fuse-overlayfs when present (layered, disk-efficient), else vfs (portable but
|
|
36
47
|
// full-copy). An explicit choice is honored as-is.
|
|
@@ -55,8 +66,9 @@ export function sandboxBaseArgs() {
|
|
|
55
66
|
export function nestedPodmanArgs(driver) {
|
|
56
67
|
const args = [
|
|
57
68
|
// Predictable host↔container uid mapping; the inner subuid range (1001:64535
|
|
58
|
-
// in the image) is derived from this mapping.
|
|
59
|
-
|
|
69
|
+
// in the image) is derived from this mapping. Pinned to the image's devbot
|
|
70
|
+
// user so the host account's uid number cannot shift it.
|
|
71
|
+
NESTED_PODMAN_USERNS,
|
|
60
72
|
// No systemd inside the builder; the inner runtime uses cgroupfs and shares
|
|
61
73
|
// the outer cgroup namespace.
|
|
62
74
|
"--cgroupns=host",
|
package/dist/devcontainer.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"devcontainer.js","sourceRoot":"","sources":["../src/devcontainer.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,4EAA4E;AAC5E,kEAAkE;AAClE,EAAE;AACF,8EAA8E;AAC9E,yEAAyE;AACzE,sEAAsE;AACtE,gFAAgF;AAChF,0EAA0E;AAC1E,2BAA2B;AAE3B,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAKhD,gFAAgF;AAChF,2EAA2E;AAC3E,iDAAiD;AACjD,MAAM,UAAU,mBAAmB,CAAC,OAAgB,EAAE,IAAsB;IAC1E,OAAO,OAAO,IAAI,IAAI,KAAK,OAAO,CAAC;AACrC,CAAC;AAED,6EAA6E;AAC7E,iFAAiF;AACjF,MAAM,UAAU,aAAa,CAAC,IAAI,GAAG,WAAW;IAC9C,IAAI,CAAC;QACH,UAAU,CAAC,IAAI,EAAE,SAAS,CAAC,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;QAClD,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,0EAA0E;AAC1E,gFAAgF;AAChF,2EAA2E;AAC3E,yEAAyE;AACzE,MAAM,CAAC,MAAM,gBAAgB,GAAG,sCAAsC,CAAC;AAEvE,gFAAgF;AAChF,gFAAgF;AAChF,mDAAmD;AACnD,MAAM,UAAU,oBAAoB,CAAC,UAA4B,EAAE,OAAgB;IACjF,IAAI,UAAU,KAAK,MAAM;QAAE,OAAO,OAAO,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,KAAK,CAAC;IACrE,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,8EAA8E;AAC9E,0EAA0E;AAC1E,kFAAkF;AAClF,4EAA4E;AAC5E,oEAAoE;AACpE,sEAAsE;AACtE,MAAM,UAAU,eAAe;IAC7B,OAAO,CAAC,WAAW,EAAE,QAAQ,EAAE,WAAW,EAAE,QAAQ,CAAC,CAAC;AACxD,CAAC;AAED,wEAAwE;AACxE,gFAAgF;AAChF,uEAAuE;AACvE,kBAAkB;AAClB,MAAM,UAAU,gBAAgB,CAAC,MAAqB;IACpD,MAAM,IAAI,GAAG;QACX,6EAA6E;QAC7E,
|
|
1
|
+
{"version":3,"file":"devcontainer.js","sourceRoot":"","sources":["../src/devcontainer.ts"],"names":[],"mappings":"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"}
|