mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-09-10 00:05:27 +00:00
feat(git-sync): app-aware pull defaults, always webhook delivery, token-repo guidance
- Pull-from-Git defaults on only for app-backed repos (applied when the selected resource resolves); polling is opt-in for token repositories, with a warning alert recommending the GitHub App (instant pull + in-app PRs) or the sync GitHub workflow - App repos always use webhook delivery with polling fallback: the delivery selector is gone and a stored polling mode is normalized back to auto - Post-save modal reflects the auto-pull state instead of telling the user to turn on a toggle that is already on - Non-app PR hints recommend the GitHub App explicitly Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PP5gBSPfo1YtkL1sWVAjJm
This commit is contained in:
co-authored by
Claude Fable 5
parent
fdce2d40d3
commit
5ee9ca9b23
@@ -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: '',
|
||||
|
||||
@@ -104,5 +104,6 @@
|
||||
<GitSyncSuccessModal
|
||||
bind:open={gitSyncContext.activeModals.success.open}
|
||||
savedWithoutInit={gitSyncContext.activeModals.success.savedWithoutInit}
|
||||
autoPullOn={gitSyncContext.activeModals.success.autoPullOn}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
@@ -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<string, any>
|
||||
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</a
|
||||
>
|
||||
workflow in the repository (repositories connected through the
|
||||
workflow in the repository. Recommended: connect the repository through the
|
||||
<a
|
||||
href="https://www.windmill.dev/docs/advanced/git_sync"
|
||||
target="_blank"
|
||||
class="text-blue-500 hover:underline">GitHub App</a
|
||||
> can let Windmill open them automatically).
|
||||
> and Windmill opens them automatically.
|
||||
</div>
|
||||
{/if}
|
||||
{#if repoMode === 'sync' && isFork}
|
||||
@@ -636,12 +645,12 @@
|
||||
target="_blank"
|
||||
class="text-blue-500 hover:underline font-mono">open-pr-on-fork-commit</a
|
||||
>
|
||||
workflow in the repository (repositories connected through the
|
||||
workflow in the repository. Recommended: connect the repository through the
|
||||
<a
|
||||
href="https://www.windmill.dev/docs/advanced/git_sync"
|
||||
target="_blank"
|
||||
class="text-blue-500 hover:underline">GitHub App</a
|
||||
> can let Windmill open them automatically).
|
||||
> and Windmill opens them automatically.
|
||||
</div>
|
||||
{/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 @@
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
{#if !isGithubApp && !loadingResourceInfo && !repo.auto_pull?.enabled}
|
||||
<div class="mt-2">
|
||||
<Alert type="warning" title="Instant pull recommended" size="xs">
|
||||
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
|
||||
<a
|
||||
href="https://www.windmill.dev/docs/advanced/git_sync"
|
||||
target="_blank"
|
||||
class="text-blue-500 hover:underline">GitHub App</a
|
||||
>
|
||||
(which also lets Windmill manage pull requests), or push changes into
|
||||
Windmill with the
|
||||
<a
|
||||
href="https://www.windmill.dev/docs/advanced/deploy_gh_gl"
|
||||
target="_blank"
|
||||
class="text-blue-500 hover:underline">sync GitHub workflow</a
|
||||
>.
|
||||
</Alert>
|
||||
</div>
|
||||
{/if}
|
||||
{#if repo.auto_pull?.enabled}
|
||||
{@const viaWebhook = repo.auto_pull?.webhook_id != null}
|
||||
{#if isGithubApp}
|
||||
<div class="mt-3 max-w-sm">
|
||||
<div class="text-2xs font-semibold text-secondary mb-1">Delivery</div>
|
||||
<Select
|
||||
items={[
|
||||
{ label: 'Webhook with polling fallback', value: 'auto' },
|
||||
{ label: 'Polling only (air-gapped)', value: 'polling' }
|
||||
]}
|
||||
bind:value={() => deliveryMode(), (v) => setDeliveryMode(v)}
|
||||
clearable={false}
|
||||
size="sm"
|
||||
/>
|
||||
</div>
|
||||
{:else}
|
||||
{#if !isGithubApp}
|
||||
<div class="text-2xs text-secondary mt-2">
|
||||
Instant webhook sync requires the
|
||||
<a
|
||||
|
||||
@@ -5,9 +5,10 @@
|
||||
interface Props {
|
||||
open: boolean
|
||||
savedWithoutInit?: boolean
|
||||
autoPullOn?: boolean
|
||||
}
|
||||
|
||||
let { open = $bindable(false), savedWithoutInit = false }: Props = $props()
|
||||
let { open = $bindable(false), savedWithoutInit = false, autoPullOn = false }: Props = $props()
|
||||
</script>
|
||||
|
||||
<Modal bind:open title="Git Sync Connection Saved" class="sm:max-w-4xl" cancelText="Close">
|
||||
@@ -37,15 +38,27 @@
|
||||
{/if}
|
||||
|
||||
<!-- Optional setup section -->
|
||||
<div class="bg-amber-50 border border-amber-200 rounded-lg p-4">
|
||||
<h4 class="font-medium text-amber-900 mb-2 flex items-center gap-2">
|
||||
<ArrowRight class="h-4 w-4" />
|
||||
Deploy changes from Git back to Windmill
|
||||
</h4>
|
||||
<p class="text-sm text-amber-800 mb-3">
|
||||
Turn on "Automatically deploy changes from Git" on the repository to have Windmill pull new
|
||||
commits into this workspace for you.
|
||||
</p>
|
||||
{#if autoPullOn}
|
||||
<div class="bg-green-50 border border-green-200 rounded-lg p-4">
|
||||
<h4 class="font-medium text-green-900 mb-2 flex items-center gap-2">
|
||||
<ArrowRight class="h-4 w-4" />
|
||||
Pull from Git is on
|
||||
</h4>
|
||||
<p class="text-sm text-green-800">
|
||||
New commits to the tracked branch deploy into this workspace automatically. You can
|
||||
adjust this anytime on the repository card.
|
||||
</p>
|
||||
</div>
|
||||
{:else}
|
||||
<div class="bg-amber-50 border border-amber-200 rounded-lg p-4">
|
||||
<h4 class="font-medium text-amber-900 mb-2 flex items-center gap-2">
|
||||
<ArrowRight class="h-4 w-4" />
|
||||
Deploy changes from Git back to Windmill
|
||||
</h4>
|
||||
<p class="text-sm text-amber-800 mb-3">
|
||||
Turn on "Automatically deploy changes from Git" on the repository to have Windmill pull
|
||||
new commits into this workspace for you.
|
||||
</p>
|
||||
<div class="flex flex-col gap-2">
|
||||
<p class="text-sm text-amber-700">
|
||||
Prefer to control deployment from your own pipeline (tests, custom gating, deploy on PR
|
||||
@@ -60,8 +73,9 @@
|
||||
<ExternalLink class="h-3 w-3" />
|
||||
Learn more about CI-based deployment
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</Modal>
|
||||
|
||||
Reference in New Issue
Block a user