An account that can only read an origin repository proposes through its own fork there, and a protected repository is always proposed to that way #72
No reviewers
Labels
No labels
agent-work
agent-working
ultracode
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
trevato-apps/forge!72
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "tdobbertin-espo/forge:feat/propose-via-fork"
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?
Stacked on #71 (which is stacked on #70). This branch has those two commits first. Only the top commit is new. Land #70 and #71 first.
To carry a branch into an origin repository, the forge pushed the branch there. So the account needed push rights on that repository. An account that could only read it could not propose at all.
Now such an account proposes through its own fork at the origin (
src/origins/fork-route.ts). The fork is found or made. Found: in the picker's cache, by its two possible names, then byGET /repos/{o}/{r}/forks(bounded) for a fork the account owns under any name. Made:POST /forks, as<owner>-<name>when the name is taken. The branch is pushed into the fork, with a lease on where it stands there. The pull opens on the origin with head<account>:<branch>. The origin'spermissions.pushdecides the way when the pull opens, and a direct push that the origin refuses falls back to the fork.A repository that the operator protects (
FORGE_ORIGIN_DENY_PUSH, from #71) is always proposed to through a fork, whatever the credential can do. A branch pushed into a repository runs its workflows with that repository's Actions secrets; a pull from a fork runs them without the secrets (Forgejoservices/actions/secret.go). So push-through, a carried branch and a branch made on its mirror are refused there (origin_protected). The fork step of contribute uses the same fork (ensureFork), and a fork that reaches its origin through a fork says Propose via your fork. A push to the fork waits on the guard, as every other write does.The
owner:branchhead is Forgejo's own form (routers/api/v1/repo/pull.go,parseCompareInfoandGetForkedRepo). The note in the Forgejo provider that called it unverified is updated. This very pull is opened that way: headtdobbertin-espo:feat/propose-via-fork, from an account with read access only on this repository (this instance runs Forgejo 15.0.6).What is unchanged: an account with push rights on a repository that is not protected proposes as before, by a branch in the repository. Nothing new is stored, and there is no migration.
Tests
bun 1.3.13, a scrubbed environment (no agent variables):
test/propose-via-fork.test.ts: 10 pass, 0 fail, with a real forge serving git behind the fake API: a reader proposes through its fork with head<owner>:<branch>; the fork is reused, found under a name of its own, or made under a second name; an account that can push still pushes directly; a push the origin refuses falls back to the fork; a protected repository always takes the fork, even for an account that could push; a push into the fork waits on the guard.bun test --timeout 60000call: 544 pass, 0 fail across 41 files.bun scripts/gate.tsandtsc --noEmit: clean.the 41 files
propose-via-fork, origin-guard, origin-token-scopes, following, following-card, forks, fork-flow, fork-pull-approval, repo-fork-bar, crew-proposal, origins, origins-oauth, origins-operator, origins-reconnect, origins-security-auth, origins-security-provider, origins-security-push, origins-sync, origins-sync-settled, web-origins, web-origin-link, mcp-origins, mcp-origin-apps, push-through, trusted-hosts, trusted-hosts-ui, steps-lists, no-polling, refresh-meta, mirror-outbound, mirror-out, carried, migrate, migrate-after, tui-migrate, apps-feedback-mirror, and the five cross files reserved-names, studio, shards, check-list, hollow (each
test/<name>.test.ts).🤖 Generated with Claude Code
To carry a branch into an origin repository, the account needed push rights there. An account that could only read the repository could not propose at all. Now such an account proposes through its own fork at the origin (src/origins/fork-route.ts). The fork is found (in the picker's cache, by its two possible names, then by GET /repos/{o}/{r}/forks, bounded, for a fork the account owns under any name) or made (POST /forks, as `<owner>-<name>` when the name is taken). The branch is pushed into the fork, with a lease on where it stands there. The pull opens on the origin with head `<account>:<branch>`. The origin's `permissions.push` decides the way when the pull opens, and a direct push that the origin refuses falls back to the fork. A repository that the operator protects (FORGE_ORIGIN_DENY_PUSH) is always proposed to through a fork, whatever the credential can do: a branch pushed into a repository runs its workflows with that repository's Actions secrets, and a pull from a fork runs them without the secrets (Forgejo services/actions/secret.go:43). So push-through, a carried branch and a branch made on its mirror are refused there (`origin_protected`). The fork step of contribute uses the same fork (`ensureFork`), and a fork that reaches its origin through a fork says "Propose via your fork". A push to the fork waits on the guard, as every other write does. The `owner:branch` head is Forgejo's own form (routers/api/v1/repo/ pull.go, parseCompareInfo and GetForkedRepo). It was checked on Forgejo 15.0.9: an account with read access only opened pulls on a private repository through its fork, and the repository got no new branch. The note in the Forgejo provider that called this form unverified is updated. An account with push rights on a repository that is not protected proposes as before. test/propose-via-fork.test.ts (a real forge serving git behind the fake API). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>View command line instructions
Manual merge helper
Use this merge commit message when completing the merge manually.
Checkout
From your project repository, check out a new branch and test the changes.Merge
Merge the changes and update on Forgejo.Warning: The "Autodetect manual merge" setting is not enabled for this repository, you will have to mark this pull request as manually merged afterwards.