diff --git a/frontend/src/lib/components/git_sync/GitSyncContext.svelte.ts b/frontend/src/lib/components/git_sync/GitSyncContext.svelte.ts index e2b3f07e0d..c69245b0e5 100644 --- a/frontend/src/lib/components/git_sync/GitSyncContext.svelte.ts +++ b/frontend/src/lib/components/git_sync/GitSyncContext.svelte.ts @@ -1,5 +1,5 @@ import { getContext, setContext } from 'svelte' -import { enterpriseLicense, userWorkspaces } from '$lib/stores' +import { enterpriseLicense } from '$lib/stores' import { get } from 'svelte/store' import { sendUserToast } from '$lib/toast' import { JobService, WorkspaceService, ResourceService } from '$lib/gen' @@ -45,7 +45,7 @@ export type GitSyncSettings = { export type ModalState = { push: { idx: number; repo: GitSyncRepository; open: boolean } | null pull: { idx: number; repo: GitSyncRepository; open: boolean; settingsOnly?: boolean } | null - success: { open: boolean; savedWithoutInit?: boolean } | null + success: { open: boolean; savedWithoutInit?: boolean; autoPullOn?: boolean } | null } export type ValidationState = { @@ -282,8 +282,8 @@ export function createGitSyncContext(workspace: string) { closeModal('pull') } - function showSuccessModal(savedWithoutInit?: boolean) { - activeModals.success = { open: true, savedWithoutInit } + function showSuccessModal(savedWithoutInit?: boolean, autoPullOn?: boolean) { + activeModals.success = { open: true, savedWithoutInit, autoPullOn } } function closeSuccessModal() { @@ -528,7 +528,7 @@ export function createGitSyncContext(workspace: string) { repoToSave.detectionState = undefined repoToSave.extractedSettings = undefined // Show success modal for new connections - showSuccessModal(savedWithoutInit) + showSuccessModal(savedWithoutInit, repoToSave.auto_pull?.enabled === true) } } @@ -664,14 +664,6 @@ export function createGitSyncContext(workspace: string) { } } - // Mirrors the card's fork detection: wm-fork- id prefix, or a parent - // workspace id (dev workspaces are prefix-less). - function isForkOrDevWorkspace(): boolean { - if (workspace.startsWith('wm-fork-')) return true - const ws = get(userWorkspaces)?.find((w) => w.id === workspace) - return !!ws?.parent_workspace_id - } - function addSyncRepository() { if (!get(enterpriseLicense) && repositories && repositories.length >= 1) { sendUserToast('Multiple repositories requires Enterprise Edition', true) @@ -691,19 +683,10 @@ export function createGitSyncContext(workspace: string) { exclude_types_override: [], legacyImported: false, isUnsavedConnection: true, - collapsed: false, - // New connections default to pulling changes from Git (webhook with a - // polling fallback), forks included. Existing repos load without - // auto_pull and stay off. Auto-pull is EE-only (the backend rejects an - // enabled setting on CE) and parent-managed on fork/dev workspaces - // (the backend rejects it there too), so only default it on when - // licensed and not a fork. - ...(get(enterpriseLicense) && !isForkOrDevWorkspace() - ? { - auto_pull: { enabled: true, mode: 'auto', sync_forks: true }, - fork_open_prs: true - } - : {}) + collapsed: false + // Pull-from-Git defaults are applied by the repository card once the + // selected resource resolves: only app-backed repos (instant webhook + // delivery) default to auto-pull on; polling is opt-in for token repos. }) gitSyncTestJobs.push({ jobId: '', diff --git a/frontend/src/lib/components/git_sync/GitSyncModalManager.svelte b/frontend/src/lib/components/git_sync/GitSyncModalManager.svelte index 15e23f7e1e..05925d6e26 100644 --- a/frontend/src/lib/components/git_sync/GitSyncModalManager.svelte +++ b/frontend/src/lib/components/git_sync/GitSyncModalManager.svelte @@ -104,5 +104,6 @@ {/if} diff --git a/frontend/src/lib/components/git_sync/GitSyncRepositoryCard.svelte b/frontend/src/lib/components/git_sync/GitSyncRepositoryCard.svelte index a01d3b7c81..35e27b8402 100644 --- a/frontend/src/lib/components/git_sync/GitSyncRepositoryCard.svelte +++ b/frontend/src/lib/components/git_sync/GitSyncRepositoryCard.svelte @@ -22,7 +22,6 @@ import GitSyncModeDisplay from './GitSyncModeDisplay.svelte' import Toggle from '$lib/components/Toggle.svelte' import EEOnly from '$lib/components/EEOnly.svelte' - import Select from '$lib/components/select/Select.svelte' import { ResourceService, VariableService } from '$lib/gen' let { @@ -69,15 +68,6 @@ } } - // Delivery mode shown in the selector. The backend also has a webhook-only - // mode; it's surfaced as "auto" (webhook with polling fallback) here. - function deliveryMode(): 'auto' | 'polling' { - return repo?.auto_pull?.mode === 'polling' ? 'polling' : 'auto' - } - function setDeliveryMode(mode: 'auto' | 'polling') { - if (repo?.auto_pull) repo.auto_pull = { ...repo.auto_pull, mode } - } - // Parent-level fork auto-sync (phase 5). Configured on the parent workspace's // repo and applied to all of its forks, so hide it when the current workspace // is itself a fork. @@ -141,7 +131,7 @@ const abortController = new AbortController() async function loadResourceInfo() { - if (repo?.git_repo_resource_path && !repo.isUnsavedConnection && $workspaceStore) { + if (repo?.git_repo_resource_path && $workspaceStore) { loadingResourceInfo = true resourceInfo = null // Clear stale app state up front so a resource change or a failed @@ -157,6 +147,25 @@ // Extract git URL from resource value const value = resource.value as Record isGithubApp = value?.is_github_app === true + // A newly added connection defaults to pulling from Git only when + // the repository is app-backed (instant webhook delivery). Polling + // is opt-in for token repositories. Fork/dev workspaces never get + // the parent-only defaults (the backend rejects them), and both + // features are EE-only. + if ( + repo.isUnsavedConnection && + isGithubApp && + !isFork && + $enterpriseLicense && + repo.auto_pull === undefined + ) { + repo.auto_pull = { enabled: true, mode: 'auto', sync_forks: true } + repo.fork_open_prs = repo.fork_open_prs ?? true + } + // Webhook with polling fallback is the only delivery for app repos. + if (isGithubApp && repo.auto_pull?.mode === 'polling') { + repo.auto_pull = { ...repo.auto_pull, mode: 'auto' } + } let gitUrl = value?.url || value?.git_url if (gitUrl && typeof gitUrl === 'string') { @@ -591,12 +600,12 @@ target="_blank" class="text-blue-500 hover:underline font-mono">open-pr-on-commit - workflow in the repository (repositories connected through the + workflow in the repository. Recommended: connect the repository through the GitHub App can let Windmill open them automatically). + > and Windmill opens them automatically. {/if} {#if repoMode === 'sync' && isFork} @@ -636,12 +645,12 @@ target="_blank" class="text-blue-500 hover:underline font-mono">open-pr-on-fork-commit - workflow in the repository (repositories connected through the + workflow in the repository. Recommended: connect the repository through the GitHub App can let Windmill open them automatically). + > and Windmill opens them automatically. {/if} {/if} @@ -702,7 +711,7 @@ options={{ right: 'Automatically deploy changes from Git', rightTooltip: - 'Windmill deploys new commits from the tracked branch into this workspace. Repositories connected through the GitHub App sync instantly via webhooks; others are checked about every minute.' + 'Windmill deploys new commits from the tracked branch into this workspace. Repositories connected through the GitHub App sync instantly via webhooks with a polling fallback; token-based repositories are checked about every minute.' }} on:change={(e) => setAutoPullEnabled(e.detail)} > @@ -724,22 +733,30 @@ /> {/if} + {#if !isGithubApp && !loadingResourceInfo && !repo.auto_pull?.enabled} +
+ + Pull for this repository checks the tracked branch about every minute; + longer gaps make drift and merge conflicts more likely. For instant pull, + connect the repository through the + GitHub App + (which also lets Windmill manage pull requests), or push changes into + Windmill with the + sync GitHub workflow. + +
+ {/if} {#if repo.auto_pull?.enabled} {@const viaWebhook = repo.auto_pull?.webhook_id != null} - {#if isGithubApp} -
-
Delivery
-