Files
windmill/frontend/src/lib/hub.ts
T
d2b9799ac4 test: git sync E2E tests + auto-manage git sync script version (#8253)
* test: add E2E git sync integration tests with Gitea

Add 7 end-to-end tests that verify the full git sync pipeline:
deploy objects in Windmill → DeploymentCallback job runs hub sync script →
correct files appear in a Gitea git repository.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: auto-manage git sync script version locked to Windmill release

- Add LATEST_GIT_SYNC_SCRIPT_PATH constant as single source of truth
- Backend auto-fills empty script_path with latest on save
- New repos use empty script_path (auto-managed by backend)
- Existing repos with pinned versions show warning with opt-in button
- cache_hub_scripts always caches the latest constant
- Rename hubPaths.json gitSync entries to deprecated_ prefix

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* chore: update ee-repo-ref.txt for git-sync-tests branch

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* chore: update ee-repo-ref.txt

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: remove upgrade_git_sync_script_paths from save path

Empty script_path is now resolved to latest at job dispatch time in EE,
not on save. Users opt in via the UI button.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: use Option<String> for git sync script_path

None means auto-managed (uses LATEST_GIT_SYNC_SCRIPT_PATH),
Some(path) means pinned to a specific script. Resolution happens
at job dispatch time via effective_script_path().

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: separate git sync tests into dedicated CI workflow

- Remove git_sync_test from default integration test suite
- Move gitea service to dedicated docker-compose.git-sync.yml
- Add run_git_sync.sh script
- New workflow triggers on changes to git sync crate, hub paths,
  ee-repo-ref, or the test files themselves

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* test: add Rust integration tests for git sync filtering logic

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: run git sync E2E tests via cargo run instead of docker image

Build from source and run Windmill directly, start Gitea as a
standalone container. Tests run against localhost — no pre-built
Docker image needed, works on PRs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: add relevance check before running git sync E2E tests

Only run the expensive build+test when actually relevant:
- Direct git sync file changes: always run
- ee-repo-ref.txt changed: check if EE diff touches windmill-git-sync/
- Unrelated changes to workspaces.rs or other files: skip

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: remove broad path triggers from git sync workflow

Remove workspaces.rs and wmill_integration_test_utils.py from path
triggers - they change too often for unrelated reasons. Keep only
git-sync-specific paths + ee-repo-ref.txt (filtered by check-relevance).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* test: rewrite git sync E2E tests with full coverage and fix test infra

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* chore: remove accidentally committed gen files

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* test: remove unit/integration tests for git sync filtering (covered by E2E)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: use correct build features and pass license key to test step in CI

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* chore: add workflow_dispatch trigger to git sync test workflow

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Update commit reference in ee-repo-ref.txt

* fix: update stats_oss stubs to match EE telemetry signature changes

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: disable -D warnings for git sync e2e build step

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: allow test connection button in auto-managed git sync mode

The test connection button was disabled and runTestJob() bailed out
when script_path was unset. The test job uses a separate hub script
(gitSyncTest), not the sync script, so the guard was wrong.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* chore: update ee-repo-ref to include auto-managed script_path fix

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: use full SHA in ee-repo-ref.txt

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: address PR review feedback

- Initialize current_count before loop in wait_for_sync_jobs
- Clean up temp directories in clone helpers with addCleanup
- Fail CI startup steps if Gitea/Windmill never become ready
- Assert exact job count in exclude_path test
- Remove docs/git-sync-tests-plan.md (stale planning doc)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* chore: remove orphaned git_sync.sql fixture

No longer referenced after Rust integration tests were removed.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: assert old file removal in rename test

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* chore: update ee-repo-ref to 612d96a66f9d0cfdae335ef3eb4881f3444ce7cd

This commit updates the EE repository reference after PR #442 was merged in windmill-ee-private.

Previous ee-repo-ref: a05004a7c82f3d1ee5f6863bb9f5a33827d30032

New ee-repo-ref: 612d96a66f9d0cfdae335ef3eb4881f3444ce7cd

Automated by sync-ee-ref workflow.

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com>
2026-03-12 12:48:38 +00:00

112 lines
2.9 KiB
TypeScript

import type { Schema } from './common'
import { AppService, FlowService, type Flow, type Script } from './gen'
import { encodeState } from './utils'
import hubPathsData from './hubPaths.json'
import {
replacePlaceholderForSignatureScriptTemplate,
SIGNATURE_TEMPLATE_FLOW_HUB_ID,
SIGNATURE_TEMPLATE_SCRIPT_HUB_PATH
} from './components/triggers/http/utils'
export const DEFAULT_HUB_BASE_URL = 'https://hub.windmill.dev'
export const PRIVATE_HUB_MIN_VERSION = 10_000_000
export function scriptToHubUrl(
content: string,
summary: string,
description: string,
kind: Script['kind'],
language: Script['language'],
schema: Schema | any,
lock: string | undefined,
hubBaseUrl: string
): URL {
const url = new URL(hubBaseUrl + '/scripts/add')
url.hash = encodeState({ content, summary, description, kind, language, schema, lock })
return url
}
export const HubScript = {
SIGNATURE_TEMPLATE: SIGNATURE_TEMPLATE_SCRIPT_HUB_PATH
} as const
export const HubFlow = {
SIGNATURE_TEMPLATE: SIGNATURE_TEMPLATE_FLOW_HUB_ID
} as const
export function replaceScriptPlaceholderWithItsValues(id: string, content: string) {
switch (id) {
case HubScript.SIGNATURE_TEMPLATE:
case HubFlow.SIGNATURE_TEMPLATE:
return replacePlaceholderForSignatureScriptTemplate(content)
default:
return content
}
}
export async function loadHubFlows() {
try {
const flows = (await FlowService.listHubFlows()).flows ?? []
const processed = flows.sort((a, b) => b.votes - a.votes)
return processed
} catch {
console.error('Hub is not available')
}
}
export async function loadHubApps() {
try {
const apps = (await AppService.listHubApps()).apps ?? []
const processed = apps.sort((a, b) => b.votes - a.votes)
return processed
} catch {
console.error('Hub is not available')
}
}
export function flowToHubUrl(flow: Flow, hubBaseUrl: string): URL {
const url = new URL(hubBaseUrl + '/flows/add')
const openFlow = {
value: flow.value,
summary: flow.summary,
description: flow.description,
schema: flow.schema
}
url.searchParams.append('flow', encodeState(openFlow))
return url
}
export function appToHubUrl(staticApp: any, hubBaseUrl: string): URL {
const url = new URL(hubBaseUrl + '/apps/add')
url.searchParams.append('app', encodeState(staticApp))
return url
}
export function rawAppToHubUrl(hubBaseUrl: string, summary?: string): URL {
const url = new URL(hubBaseUrl + '/raw_apps/add')
if (summary) {
url.searchParams.append('summary', summary)
}
return url
}
type HubPaths = {
gitSyncTest: string
gitInitRepo: string
slackErrorHandler: string
slackRecoveryHandler: string
slackSuccessHandler: string
slackReport: string
discordReport: string
smtpReport: string
teamsErrorHandler: string
teamsRecoveryHandler: string
teamsSuccessHandler: string
emailErrorHandler: string
cloneRepoToS3forGitRepoViewer: string
appReport: string
}
export const hubPaths = hubPathsData as HubPaths