mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-08-23 08:00:45 +00:00
feat(git-sync): nested fork routing + fork-of-dev branch rooting
A fork of a dev workspace now roots its wm-fork/** branch on the dev's environment-label branch (the content it diverged from) and its PR merges back into that branch: the backend passes parent_dev_workspace_label with the deploy (parent row joined in both enqueue paths), the CLI gains --parent-dev-workspace-label and checks it before the wm-fork- prefix fallback when rooting a fork-of-a-fork branch, and the PR completion hook uses it as the PR base. Fork sync routing covers the whole live descendant chain of the webhook/poller workspace (recursive, depth-capped) instead of direct children only, and fork_open_prs is resolved at the root ancestor — only the root can hold auto-pull config, so grandchild forks sync through it. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PP5gBSPfo1YtkL1sWVAjJm
This commit is contained in:
@@ -2761,6 +2761,7 @@ export async function pull(
|
||||
onlyCreateBranch?: boolean;
|
||||
parentWorkspaceId?: string;
|
||||
devWorkspaceLabel?: string;
|
||||
parentDevWorkspaceLabel?: string;
|
||||
gitCommitterEmail?: string;
|
||||
gitCommitterName?: string;
|
||||
},
|
||||
@@ -2841,20 +2842,23 @@ export async function pull(
|
||||
: !!opts.useIndividualBranch;
|
||||
const groupByFolder = targetIsFork ? false : !!opts.groupByFolder;
|
||||
|
||||
// Fork-of-a-fork: only when the parent workspace is itself a fork, root
|
||||
// the new branch on the parent's fork branch (mirrors the hub script's
|
||||
// `parent_workspace_id?.startsWith(FORKED_…)` gate).
|
||||
if (opts.parentWorkspaceId && isForkWorkspace(opts.parentWorkspaceId)) {
|
||||
const parentBranch = computeGitSyncDeployBranch({
|
||||
workspaceId: opts.parentWorkspaceId,
|
||||
items: deployItems,
|
||||
useIndividualBranch,
|
||||
groupByFolder,
|
||||
clonedBranchName,
|
||||
});
|
||||
if (parentBranch && parentBranch !== clonedBranchName) {
|
||||
checkoutGitSyncDeployBranch(parentBranch);
|
||||
}
|
||||
// Fork-of-a-fork: when the parent workspace is itself a fork, root the new
|
||||
// branch on the parent's fork branch (the content this fork diverged from).
|
||||
// A dev-workspace parent has a prefix-less id the prefix check can't see, so
|
||||
// the backend passes its environment label; its branch is the label verbatim.
|
||||
const parentBranch = opts.parentDevWorkspaceLabel
|
||||
? opts.parentDevWorkspaceLabel
|
||||
: opts.parentWorkspaceId && isForkWorkspace(opts.parentWorkspaceId)
|
||||
? computeGitSyncDeployBranch({
|
||||
workspaceId: opts.parentWorkspaceId,
|
||||
items: deployItems,
|
||||
useIndividualBranch,
|
||||
groupByFolder,
|
||||
clonedBranchName,
|
||||
})
|
||||
: null;
|
||||
if (parentBranch && parentBranch !== clonedBranchName) {
|
||||
checkoutGitSyncDeployBranch(parentBranch);
|
||||
}
|
||||
|
||||
const deployBranch = computeGitSyncDeployBranch({
|
||||
@@ -3389,6 +3393,7 @@ export async function gitDeploy(
|
||||
onlyCreateBranch?: boolean;
|
||||
parentWorkspaceId?: string;
|
||||
devWorkspaceLabel?: string;
|
||||
parentDevWorkspaceLabel?: string;
|
||||
skipSecrets?: boolean;
|
||||
gitCommitterEmail?: string;
|
||||
gitCommitterName?: string;
|
||||
@@ -5238,6 +5243,10 @@ const command = new Command()
|
||||
"--dev-workspace-label <label:string>",
|
||||
"Environment label of a dev workspace (dev/staging); its deploys go to that branch",
|
||||
)
|
||||
.option(
|
||||
"--parent-dev-workspace-label <label:string>",
|
||||
"Environment label of the parent dev workspace; roots a fork-of-dev branch on it",
|
||||
)
|
||||
.option("--skip-secrets", "Skip syncing only secrets variables")
|
||||
.option(
|
||||
"--git-committer-email <email:string>",
|
||||
|
||||
Reference in New Issue
Block a user