feat(forgejo): run trigger sessions in per-artifact clones #35
No reviewers
Labels
No labels
Agent
Ignore
Agent
In Progress
Agent
Planned
Agent
Planning
Agent
Ready
Agent
Triage
Compat
Breaking
Kind
Bug
Kind
Documentation
Kind
Enhancement
Kind
Feature
Kind
Security
Kind
Testing
Priority
Critical
Priority
High
Priority
Low
Priority
Medium
Reviewed
Confirmed
Reviewed
Duplicate
Reviewed
Invalid
Reviewed
Won't Fix
Status
Abandoned
Status
Blocked
Status
Need More Info
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
lucas/omp-deck!35
Loading…
Reference in a new issue
No description provided.
Delete branch "33-forgejo-run-trigger-sessions-in-isolated-per-artifact-clones"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
A new Forgejo trigger session now runs in its own
git clone --localof the workspace, at<data dir>/checkouts/<owner>/<repo>/<issue|pr>-<n>. The clone is detached at the PR head or the remote's default branch and has no local branches. The session stores links to its workspace and checkout insession_triggers, so it is still listed and counted under its workspace and keeps that workspace's permission rules. The dispatcher queue is FIFO per artifact, so different issues and PRs run in parallel.An artifact keeps a single conversation: a trigger on an archived mapped session unarchives and continues it instead of replacing it. Archiving a session deletes its clone, deleting a session removes it, and resuming a session whose clone is missing re-creates it.
Decisions
forgejo_held/forgejo_activityframes,forgejo_inject,ForgejoBanners, and the hold logic are gone. Legacy mapped sessions that have no links and run in the workspace dir are still reused, but no longer held.DeckPresenceis reduced toopenSessionIds(). It only decides whether a session the dispatcher brought live gets disposed after its turn.015-session-trigger-links.sql, because 013 and 014 were taken.reuseMappedexpects the session's linkedcheckoutPathas its cwd, falling back to the workspace path for legacy sessions.restoreCheckout). The new clone starts fresh at the PR head or default branch, not where the session left off. Resume fails if the linked workspace no longer exists.could not prepare a checkout: …. No session is created.ForgejoDispatcherDeps.createCheckoutis an optional test seam; it defaults to the real implementation.listSessions({ cwd })now filtersSessionManager.listAll()byworkspacePath ?? cwdinstead of callingSessionManager.list(cwd).findForgejoSessionArtifactwas removed, since only inject used it.fs.promisescalls;removeCheckoutis now async.Verification
bun run typecheck: protocol, server and web all pass.bun test: 1036 pass, 0 fail. New tests:checkout.test.tsruns against real git (PR ref, issue default branch, origin URL, no local branches, the same branch checked out in clone and workspace, leftover replacement, partial clone cleanup, refusal outside the root, re-creation of a missing clone, an existing clone left untouched, refusal of a mismatched path). Also link round-trips insession-triggers.test.ts, and dispatcher tests for the clone cwd and links, checkout failure, per-artifact FIFO, parallel artifacts of one repo, no hold for open workspace sessions, an open mapped session staying live, an archived mapped session being unarchived and continued, and an archived session that is gone staying archived and being replaced.refs/pull/<n>/head.Closes #33
@ -0,0 +53,4 @@// The caller only gets here when no session owns this artifact, so an// existing directory is a leftover of a crashed creation.fs.rmSync(dest, { recursive: true, force: true });fs.mkdirSync(path.dirname(dest), { recursive: true });This is an async function, why the two sync calls?
Fixed in
48a2b87:createCheckoutandremoveCheckoutnow usefs.promises.rm/mkdir, andremoveCheckoutis async and awaited at every call site.I don't think "link" is a great word for here. It is really generic and only carries meaning if you consistently mention both sides, e.g. "link A to B". Throughout the new code, the word "link" never manages to give me any meaningful info.
Re review 57: agreed, "links" said nothing on its own. Fixed in
7a137b3. The pair (owning workspace, checkout the session runs in) is now aSessionPlacement:SessionLinks→SessionPlacementgetSessionLinks→getSessionPlacementlistSessionWorkspaceLinks→listSessionWorkspacesCreateSessionOpts.links→placementThe comments were reworded to match ("owning workspace", "no checkout").
I kept the migration's filename
015-session-trigger-links.sqland only reworded its comment. The runner records applied migrations by filename, so renaming the file would re-run theADD COLUMNs on databases that already have them, and those would fail.