mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-08-21 08:02:26 +00:00
feat: GIt sync to multiple repo (#2996)
This commit is contained in:
committed by
GitHub
parent
13c5802670
commit
fda0e28db3
Generated
+1
@@ -9432,6 +9432,7 @@ dependencies = [
|
||||
"serde_json",
|
||||
"sqlx",
|
||||
"tracing",
|
||||
"uuid 1.6.1",
|
||||
"windmill-common",
|
||||
"windmill-queue",
|
||||
]
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
-- Add down migration script here
|
||||
UPDATE workspace_settings SET git_sync = git_sync->0;
|
||||
@@ -0,0 +1,2 @@
|
||||
-- Add up migration script here
|
||||
UPDATE workspace_settings SET git_sync = '[]'::jsonb || git_sync
|
||||
@@ -1,6 +1,6 @@
|
||||
openapi: 3.0.3
|
||||
info:
|
||||
version: 1.241.0
|
||||
version: 1.242.0
|
||||
title: Windmill API
|
||||
contact:
|
||||
name: Windmill Team
|
||||
@@ -1525,17 +1525,19 @@ paths:
|
||||
s3_resource_path:
|
||||
type: string
|
||||
git_sync:
|
||||
type: object
|
||||
properties: &ref_16
|
||||
script_path:
|
||||
type: string
|
||||
git_repo_resource_path:
|
||||
type: string
|
||||
use_individual_branch:
|
||||
type: boolean
|
||||
required: &ref_17
|
||||
- script_path
|
||||
- git_repo_resource_path
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties: &ref_16
|
||||
script_path:
|
||||
type: string
|
||||
git_repo_resource_path:
|
||||
type: string
|
||||
use_individual_branch:
|
||||
type: boolean
|
||||
required: &ref_17
|
||||
- script_path
|
||||
- git_repo_resource_path
|
||||
required:
|
||||
- code_completion_enabled
|
||||
/w/{workspace}/workspaces/get_deploy_to:
|
||||
@@ -1891,9 +1893,11 @@ paths:
|
||||
type: object
|
||||
properties:
|
||||
git_sync_settings:
|
||||
type: object
|
||||
properties: *ref_16
|
||||
required: *ref_17
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties: *ref_16
|
||||
required: *ref_17
|
||||
responses:
|
||||
'200':
|
||||
description: status
|
||||
@@ -10202,7 +10206,7 @@ paths:
|
||||
schema: {}
|
||||
/w/{workspace}/job_helpers/list_stored_files:
|
||||
get:
|
||||
summary: List the file keys available in the worspace files storage (S3)
|
||||
summary: List the file keys available in the workspace files storage (S3)
|
||||
operationId: listStoredFiles
|
||||
tags:
|
||||
- helpers
|
||||
|
||||
@@ -1193,7 +1193,9 @@ paths:
|
||||
large_file_storage:
|
||||
$ref: "#/components/schemas/LargeFileStorage"
|
||||
git_sync:
|
||||
$ref: "#/components/schemas/WorkspaceGitSync"
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/components/schemas/WorkspaceGitSync"
|
||||
required:
|
||||
- code_completion_enabled
|
||||
|
||||
@@ -1532,7 +1534,9 @@ paths:
|
||||
type: object
|
||||
properties:
|
||||
git_sync_settings:
|
||||
$ref: "#/components/schemas/WorkspaceGitSync"
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/components/schemas/WorkspaceGitSync"
|
||||
|
||||
responses:
|
||||
"200":
|
||||
@@ -6846,7 +6850,7 @@ paths:
|
||||
|
||||
/w/{workspace}/job_helpers/list_stored_files:
|
||||
get:
|
||||
summary: List the file keys available in the worspace files storage (S3)
|
||||
summary: List the file keys available in the workspace files storage (S3)
|
||||
operationId: listStoredFiles
|
||||
tags:
|
||||
- helpers
|
||||
|
||||
@@ -1044,7 +1044,7 @@ async fn edit_large_file_storage_config(
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct EditGitSyncConfig {
|
||||
git_sync_settings: Option<WorkspaceGitRepo>,
|
||||
git_sync_settings: Option<Vec<WorkspaceGitRepo>>,
|
||||
}
|
||||
|
||||
async fn edit_git_sync_config(
|
||||
@@ -1078,7 +1078,7 @@ async fn edit_git_sync_config(
|
||||
.await?;
|
||||
|
||||
if let Some(git_sync_settings) = new_config.git_sync_settings {
|
||||
let serialized_config = serde_json::to_value::<WorkspaceGitRepo>(git_sync_settings)
|
||||
let serialized_config = serde_json::to_value::<Vec<WorkspaceGitRepo>>(git_sync_settings)
|
||||
.map_err(|err| Error::InternalErr(err.to_string()))?;
|
||||
|
||||
sqlx::query!(
|
||||
|
||||
@@ -13,6 +13,7 @@ enterprise = ["windmill-queue/enterprise"]
|
||||
default = []
|
||||
|
||||
[dependencies]
|
||||
uuid.workspace = true
|
||||
serde.workspace = true
|
||||
sqlx.workspace = true
|
||||
serde_json.workspace = true
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use sqlx::{Pool, Postgres};
|
||||
use uuid::Uuid;
|
||||
use windmill_common::users::SUPERADMIN_SYNC_EMAIL;
|
||||
use windmill_common::workspaces::WorkspaceGitRepo;
|
||||
|
||||
@@ -45,7 +46,7 @@ impl DeployedObject {
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn handle_deployment_metadata<'c, R: rsmq_async::RsmqConnection + Send + 'c>(
|
||||
pub async fn handle_deployment_metadata<'c, R: rsmq_async::RsmqConnection + Send + Clone + 'c>(
|
||||
email: &str,
|
||||
created_by: &str,
|
||||
db: &DB,
|
||||
@@ -94,122 +95,119 @@ pub async fn handle_deployment_metadata<'c, R: rsmq_async::RsmqConnection + Send
|
||||
));
|
||||
}
|
||||
|
||||
let workspace_git_repo = workspace_git_repo_setting
|
||||
let workspace_git_repos = workspace_git_repo_setting
|
||||
.unwrap()
|
||||
.map(|conf| serde_json::from_value::<WorkspaceGitRepo>(conf).ok())
|
||||
.flatten();
|
||||
.map(|conf| serde_json::from_value::<Vec<WorkspaceGitRepo>>(conf).ok())
|
||||
.flatten()
|
||||
.unwrap_or_default();
|
||||
|
||||
let git_sync_job_uuid = if !skip_git_sync && workspace_git_repo.is_some() {
|
||||
let workspace_git_repo = workspace_git_repo.unwrap();
|
||||
let mut git_sync_job_uuids: Vec<Uuid> = vec![];
|
||||
if !skip_git_sync {
|
||||
for workspace_git_repo in workspace_git_repos {
|
||||
let mut args: HashMap<String, serde_json::Value> = HashMap::new();
|
||||
args.insert(
|
||||
"repo_url_resource_path".to_string(),
|
||||
json!(workspace_git_repo
|
||||
.git_repo_resource_path
|
||||
.strip_prefix("$res:")),
|
||||
);
|
||||
|
||||
let mut args: HashMap<String, serde_json::Value> = HashMap::new();
|
||||
args.insert(
|
||||
"repo_url_resource_path".to_string(),
|
||||
json!(workspace_git_repo
|
||||
.git_repo_resource_path
|
||||
.strip_prefix("$res:")),
|
||||
);
|
||||
if let Some(path) = obj_path {
|
||||
args.insert("path".to_string(), json!(path));
|
||||
}
|
||||
if let Some(parent_path) = obj_parent_path.clone() {
|
||||
args.insert("parent_path".to_string(), json!(parent_path));
|
||||
}
|
||||
|
||||
if let Some(path) = obj_path {
|
||||
args.insert("path".to_string(), json!(path));
|
||||
let message = match obj.clone() {
|
||||
DeployedObject::Script { path, .. } => {
|
||||
if deployment_message.as_ref().is_none()
|
||||
|| deployment_message.as_ref().is_some_and(|x| x.is_empty())
|
||||
{
|
||||
format!("Script '{}' deployed", path)
|
||||
} else {
|
||||
deployment_message.clone().unwrap()
|
||||
}
|
||||
}
|
||||
DeployedObject::Flow { path, .. } => {
|
||||
if deployment_message.as_ref().is_none()
|
||||
|| deployment_message.as_ref().is_some_and(|x| x.is_empty())
|
||||
{
|
||||
format!("Flow '{}' deployed", path)
|
||||
} else {
|
||||
deployment_message.clone().unwrap()
|
||||
}
|
||||
}
|
||||
DeployedObject::App { path, .. } => {
|
||||
if deployment_message.as_ref().is_none()
|
||||
|| deployment_message.as_ref().is_some_and(|x| x.is_empty())
|
||||
{
|
||||
format!("App '{}' deployed", path)
|
||||
} else {
|
||||
deployment_message.clone().unwrap()
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
args.insert("commit_msg".to_string(), json!(message));
|
||||
args.insert(
|
||||
"use_individual_branch".to_string(),
|
||||
json!(workspace_git_repo.use_individual_branch.unwrap_or(false)),
|
||||
);
|
||||
|
||||
let tx: PushIsolationLevel<'_, R> =
|
||||
PushIsolationLevel::IsolatedRoot(db.clone(), rsmq.clone());
|
||||
|
||||
let (job_uuid, new_tx) = windmill_queue::push(
|
||||
db,
|
||||
tx,
|
||||
&w_id,
|
||||
JobPayload::DeploymentCallback { path: workspace_git_repo.script_path.clone() },
|
||||
args,
|
||||
created_by,
|
||||
&email,
|
||||
SUPERADMIN_SYNC_EMAIL.to_string(),
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
false,
|
||||
false,
|
||||
None,
|
||||
true,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
)
|
||||
.await?;
|
||||
new_tx.commit().await?;
|
||||
|
||||
git_sync_job_uuids.push(job_uuid);
|
||||
}
|
||||
if let Some(parent_path) = obj_parent_path {
|
||||
args.insert("parent_path".to_string(), json!(parent_path));
|
||||
}
|
||||
|
||||
let message = match obj.clone() {
|
||||
DeployedObject::Script { path, .. } => {
|
||||
if deployment_message.as_ref().is_none()
|
||||
|| deployment_message.as_ref().is_some_and(|x| x.is_empty())
|
||||
{
|
||||
format!("Script '{}' deployed", path)
|
||||
} else {
|
||||
deployment_message.clone().unwrap()
|
||||
}
|
||||
}
|
||||
DeployedObject::Flow { path, .. } => {
|
||||
if deployment_message.as_ref().is_none()
|
||||
|| deployment_message.as_ref().is_some_and(|x| x.is_empty())
|
||||
{
|
||||
format!("Flow '{}' deployed", path)
|
||||
} else {
|
||||
deployment_message.clone().unwrap()
|
||||
}
|
||||
}
|
||||
DeployedObject::App { path, .. } => {
|
||||
if deployment_message.as_ref().is_none()
|
||||
|| deployment_message.as_ref().is_some_and(|x| x.is_empty())
|
||||
{
|
||||
format!("App '{}' deployed", path)
|
||||
} else {
|
||||
deployment_message.clone().unwrap()
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
args.insert("commit_msg".to_string(), json!(message));
|
||||
args.insert(
|
||||
"use_individual_branch".to_string(),
|
||||
json!(workspace_git_repo.use_individual_branch.unwrap_or(false)),
|
||||
);
|
||||
|
||||
let tx: PushIsolationLevel<'_, R> = PushIsolationLevel::IsolatedRoot(db.clone(), rsmq);
|
||||
|
||||
let (job_uuid, new_tx) = windmill_queue::push(
|
||||
db,
|
||||
tx,
|
||||
&w_id,
|
||||
JobPayload::DeploymentCallback { path: workspace_git_repo.script_path.clone() },
|
||||
args,
|
||||
created_by,
|
||||
&email,
|
||||
SUPERADMIN_SYNC_EMAIL.to_string(),
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
false,
|
||||
false,
|
||||
None,
|
||||
true,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
)
|
||||
.await?;
|
||||
new_tx.commit().await?;
|
||||
Some(job_uuid)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
}
|
||||
|
||||
// We're not persisting the default commit msg as it's pretty useless. We will persist the ones manually set by users
|
||||
let job_uuids = if git_sync_job_uuid.is_some() {
|
||||
vec![git_sync_job_uuid.unwrap()]
|
||||
} else {
|
||||
vec![]
|
||||
};
|
||||
if !skip_db_insert && (deployment_message.is_some() || job_uuids.len() > 0) {
|
||||
if !skip_db_insert && (deployment_message.is_some() || git_sync_job_uuids.len() > 0) {
|
||||
// if the git sync job hasn't been triggered, and there is not custom deployment message, there's not point adding an entry to the table
|
||||
match obj.clone() {
|
||||
DeployedObject::Script { path, hash, .. } => {
|
||||
sqlx::query!(
|
||||
"INSERT INTO deployment_metadata (workspace_id, path, script_hash, callback_job_ids, deployment_msg) VALUES ($1, $2, $3, $4, $5)",
|
||||
w_id, path, hash.0, &job_uuids, deployment_message,
|
||||
w_id, path, hash.0, &git_sync_job_uuids, deployment_message,
|
||||
)
|
||||
},
|
||||
DeployedObject::Flow { path, .. } => {
|
||||
sqlx::query!(
|
||||
"INSERT INTO deployment_metadata (workspace_id, path, callback_job_ids, deployment_msg) VALUES ($1, $2, $3, $4) ON CONFLICT (workspace_id, path) WHERE script_hash IS NULL AND app_version IS NULL DO UPDATE SET callback_job_ids = $3, deployment_msg = $4",
|
||||
w_id, path, &job_uuids, deployment_message,
|
||||
w_id, path, &git_sync_job_uuids, deployment_message,
|
||||
)
|
||||
}
|
||||
DeployedObject::App { path, version, .. } => {
|
||||
sqlx::query!(
|
||||
"INSERT INTO deployment_metadata (workspace_id, path, app_version, callback_job_ids, deployment_msg) VALUES ($1, $2, $3, $4, $5)",
|
||||
w_id, path, version, &job_uuids, deployment_message,
|
||||
w_id, path, version, &git_sync_job_uuids, deployment_message,
|
||||
)
|
||||
}
|
||||
}.execute(db)
|
||||
|
||||
@@ -60,13 +60,11 @@
|
||||
script_path: string
|
||||
git_repo_resource_path: string
|
||||
use_individual_branch: boolean
|
||||
}
|
||||
let gitSyncTestJob:
|
||||
| {
|
||||
jobId: string
|
||||
status: 'running' | 'success' | 'failure'
|
||||
}
|
||||
| undefined = undefined
|
||||
}[]
|
||||
let gitSyncTestJobs: {
|
||||
jobId: string | undefined
|
||||
status: 'running' | 'success' | 'failure' | undefined
|
||||
}[]
|
||||
let codeCompletionEnabled: boolean = false
|
||||
let tab =
|
||||
($page.url.searchParams.get('tab') as
|
||||
@@ -194,29 +192,29 @@
|
||||
}
|
||||
}
|
||||
|
||||
async function editWindmillGitSyncSettings(
|
||||
gitRepoResourcePath: string,
|
||||
useIndividualBranch: boolean
|
||||
): Promise<void> {
|
||||
if (!emptyString(gitRepoResourcePath)) {
|
||||
gitSyncSettings = {
|
||||
script_path: 'hub/7926/sync-script-to-git-repo-windmill',
|
||||
git_repo_resource_path: `$res:${gitRepoResourcePath.replace('$res:', '')}`,
|
||||
use_individual_branch: useIndividualBranch
|
||||
async function editWindmillGitSyncSettings(): Promise<void> {
|
||||
let alreadySeenResource: string[] = []
|
||||
let finalSettings = gitSyncSettings.map((elmt) => {
|
||||
alreadySeenResource.push(elmt.git_repo_resource_path)
|
||||
return {
|
||||
script_path: elmt.script_path,
|
||||
git_repo_resource_path: `$res:${elmt.git_repo_resource_path.replace('$res:', '')}`,
|
||||
use_individual_branch: elmt.use_individual_branch
|
||||
}
|
||||
})
|
||||
if (alreadySeenResource.some((res, index) => alreadySeenResource.indexOf(res) !== index)) {
|
||||
sendUserToast('Same Git resource used more than once', true)
|
||||
return
|
||||
}
|
||||
if (finalSettings.length > 0) {
|
||||
await WorkspaceService.editWorkspaceGitSyncConfig({
|
||||
workspace: $workspaceStore!,
|
||||
requestBody: {
|
||||
git_sync_settings: gitSyncSettings
|
||||
git_sync_settings: finalSettings
|
||||
}
|
||||
})
|
||||
sendUserToast('Workspace Git sync settings updated')
|
||||
} else {
|
||||
gitSyncSettings = {
|
||||
script_path: '',
|
||||
git_repo_resource_path: '',
|
||||
use_individual_branch: false
|
||||
}
|
||||
await WorkspaceService.editWorkspaceGitSyncConfig({
|
||||
workspace: $workspaceStore!,
|
||||
requestBody: {
|
||||
@@ -261,18 +259,27 @@
|
||||
settings.large_file_storage?.type === LargeFileStorage.type.S3STORAGE
|
||||
? settings.large_file_storage?.s3_resource_path?.replace('$res:', '')
|
||||
: undefined
|
||||
if (settings.git_sync !== undefined && settings.git_sync !== null) {
|
||||
gitSyncSettings = {
|
||||
git_repo_resource_path: settings.git_sync.git_repo_resource_path.replace('$res:', ''),
|
||||
script_path: settings.git_sync.script_path,
|
||||
use_individual_branch: settings.git_sync.use_individual_branch ?? false
|
||||
}
|
||||
if (
|
||||
settings.git_sync !== undefined &&
|
||||
settings.git_sync !== null &&
|
||||
settings.git_sync.length > 0
|
||||
) {
|
||||
gitSyncSettings = settings.git_sync.map((settings) => {
|
||||
return {
|
||||
git_repo_resource_path: settings.git_repo_resource_path.replace('$res:', ''),
|
||||
script_path: settings.script_path,
|
||||
use_individual_branch: settings.use_individual_branch ?? false
|
||||
}
|
||||
})
|
||||
gitSyncTestJobs = settings.git_sync.map((settings) => {
|
||||
return {
|
||||
jobId: undefined,
|
||||
status: undefined
|
||||
}
|
||||
})
|
||||
} else {
|
||||
gitSyncSettings = {
|
||||
git_repo_resource_path: '',
|
||||
script_path: '',
|
||||
use_individual_branch: false
|
||||
}
|
||||
gitSyncSettings = []
|
||||
gitSyncTestJobs = []
|
||||
}
|
||||
|
||||
// check openai_client_credentials_oauth
|
||||
@@ -322,18 +329,19 @@
|
||||
)
|
||||
}
|
||||
|
||||
async function runGitSyncTestJob() {
|
||||
if (emptyString(gitSyncSettings.script_path)) {
|
||||
async function runGitSyncTestJob(settingsIdx: number) {
|
||||
let gitSyncSettingsElmt = gitSyncSettings[settingsIdx]
|
||||
if (emptyString(gitSyncSettingsElmt.script_path)) {
|
||||
return
|
||||
}
|
||||
let jobId = await JobService.runScriptByPath({
|
||||
workspace: $workspaceStore!,
|
||||
path: 'hub/7925/git-repo-test-read-write-windmill',
|
||||
requestBody: {
|
||||
repo_url_resource_path: gitSyncSettings.git_repo_resource_path.replace('$res:', '')
|
||||
repo_url_resource_path: gitSyncSettingsElmt.git_repo_resource_path.replace('$res:', '')
|
||||
}
|
||||
})
|
||||
gitSyncTestJob = {
|
||||
gitSyncTestJobs[settingsIdx] = {
|
||||
jobId: jobId,
|
||||
status: 'running'
|
||||
}
|
||||
@@ -343,7 +351,7 @@
|
||||
workspace: $workspaceStore!,
|
||||
id: jobId
|
||||
})
|
||||
gitSyncTestJob!.status = testResult.success ? 'success' : 'failure'
|
||||
gitSyncTestJobs[settingsIdx].status = testResult.success ? 'success' : 'failure'
|
||||
},
|
||||
timeoutCode: async () => {
|
||||
try {
|
||||
@@ -776,57 +784,98 @@
|
||||
<br />
|
||||
Filtering out certain sensitive folders from the sync will be available soon.
|
||||
</Alert>
|
||||
<div class="flex mt-5 mb-1 gap-1">
|
||||
{#if gitSyncSettings}
|
||||
{#key gitSyncSettings}
|
||||
|
||||
{#each gitSyncSettings as gitSyncSettingsElmt, idx}
|
||||
<div class="flex mt-5 mb-1 gap-1 items-center text-xs">
|
||||
<h6>Repository #{idx + 1}</h6>
|
||||
<Button
|
||||
color="light"
|
||||
size="xs"
|
||||
startIcon={{ icon: XCircle }}
|
||||
iconOnly={true}
|
||||
on:click={() => {
|
||||
gitSyncSettings.splice(idx, 1)
|
||||
gitSyncSettings = [...gitSyncSettings]
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div class="flex mt-5 mb-1 gap-1">
|
||||
{#key gitSyncSettingsElmt}
|
||||
<ResourcePicker
|
||||
resourceType="git_repository"
|
||||
initialValue={gitSyncSettings?.git_repo_resource_path?.split('$res:')?.[1] || ''}
|
||||
initialValue={gitSyncSettingsElmt.git_repo_resource_path}
|
||||
on:change={(ev) => {
|
||||
editWindmillGitSyncSettings(ev.detail, gitSyncSettings?.use_individual_branch)
|
||||
gitSyncSettingsElmt.git_repo_resource_path = ev.detail
|
||||
}}
|
||||
/>
|
||||
<Button
|
||||
disabled={emptyString(gitSyncSettings?.script_path)}
|
||||
disabled={emptyString(gitSyncSettingsElmt.script_path)}
|
||||
btnClasses="w-32 text-center"
|
||||
color="dark"
|
||||
on:click={() => runGitSyncTestJob()}
|
||||
on:click={() => runGitSyncTestJob(idx)}
|
||||
size="xs">Test connection</Button
|
||||
>
|
||||
{/key}
|
||||
{/if}
|
||||
</div>
|
||||
<div class="flex mb-5 text-normal text-2xs gap-1">
|
||||
{#if gitSyncTestJob !== undefined}
|
||||
{#if gitSyncTestJob?.status === 'running'}
|
||||
<RotateCw size={14} />
|
||||
{:else if gitSyncTestJob?.status === 'success'}
|
||||
<CheckCircle2 size={14} class="text-green-600" />
|
||||
{:else}
|
||||
<XCircle size={14} class="text-red-700" />
|
||||
</div>
|
||||
<div class="flex mb-5 text-normal text-2xs gap-1">
|
||||
{#if gitSyncSettings.filter((settings) => settings.git_repo_resource_path === gitSyncSettingsElmt.git_repo_resource_path).length > 1}
|
||||
<span class="text-red-700">Using the same resource twice is not allowed.</span>
|
||||
{/if}
|
||||
Git sync resource checked via Windmill job
|
||||
<a target="_blank" href={`/run/${gitSyncTestJob?.jobId}?workspace=${$workspaceStore}`}>
|
||||
{gitSyncTestJob?.jobId}
|
||||
</a>WARNING: Only read permissions are verified.
|
||||
{/if}
|
||||
</div>
|
||||
{#if gitSyncTestJobs[idx].status !== undefined}
|
||||
{#if gitSyncTestJobs[idx].status === 'running'}
|
||||
<RotateCw size={14} />
|
||||
{:else if gitSyncTestJobs[idx].status === 'success'}
|
||||
<CheckCircle2 size={14} class="text-green-600" />
|
||||
{:else}
|
||||
<XCircle size={14} class="text-red-700" />
|
||||
{/if}
|
||||
Git sync resource checked via Windmill job
|
||||
<a
|
||||
target="_blank"
|
||||
href={`/run/${gitSyncTestJobs[idx].jobId}?workspace=${$workspaceStore}`}
|
||||
>
|
||||
{gitSyncTestJobs[idx].jobId}
|
||||
</a>WARNING: Only read permissions are verified.
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<div class="flex mt-5 mb-1 gap-1">
|
||||
{#if gitSyncSettings}
|
||||
<Toggle
|
||||
disabled={emptyString(gitSyncSettings?.git_repo_resource_path)}
|
||||
bind:checked={gitSyncSettings.use_individual_branch}
|
||||
on:change={(ev) => {
|
||||
editWindmillGitSyncSettings(gitSyncSettings.git_repo_resource_path, ev.detail)
|
||||
}}
|
||||
options={{
|
||||
right: 'Create one branch per deployed script/flow/app',
|
||||
rightTooltip:
|
||||
"If set, Windmill will create a unique branch per script/flow/app being pushed, prefixed with 'wm_deploy/'."
|
||||
}}
|
||||
/>
|
||||
{/if}
|
||||
<div class="flex mt-5 mb-1 gap-1">
|
||||
{#if gitSyncSettings}
|
||||
<Toggle
|
||||
disabled={emptyString(gitSyncSettingsElmt?.git_repo_resource_path)}
|
||||
bind:checked={gitSyncSettingsElmt.use_individual_branch}
|
||||
options={{
|
||||
right: 'Create one branch per deployed script/flow/app',
|
||||
rightTooltip:
|
||||
"If set, Windmill will create a unique branch per script/flow/app being pushed, prefixed with 'wm_deploy/'."
|
||||
}}
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
{/each}
|
||||
|
||||
<div class="flex mt-5 mb-5 gap-1">
|
||||
<Button
|
||||
color="none"
|
||||
variant="border"
|
||||
on:click={() => {
|
||||
gitSyncSettings = [
|
||||
...gitSyncSettings,
|
||||
{
|
||||
script_path: 'hub/7926/sync-script-to-git-repo-windmill',
|
||||
git_repo_resource_path: '',
|
||||
use_individual_branch: false
|
||||
}
|
||||
]
|
||||
gitSyncTestJobs = [
|
||||
...gitSyncTestJobs,
|
||||
{
|
||||
jobId: undefined,
|
||||
status: undefined
|
||||
}
|
||||
]
|
||||
}}>Add connection</Button
|
||||
>
|
||||
</div>
|
||||
|
||||
<div class="bg-surface-disabled p-4 rounded-md flex flex-col gap-1">
|
||||
@@ -865,6 +914,16 @@ git push</code
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex mt-5 mb-5 gap-1">
|
||||
<Button
|
||||
color="blue"
|
||||
disabled={gitSyncSettings.some((elmt) => emptyString(elmt.git_repo_resource_path))}
|
||||
on:click={() => {
|
||||
editWindmillGitSyncSettings()
|
||||
console.log('Saving git sync settings', gitSyncSettings)
|
||||
}}>Save Git sync settings</Button
|
||||
>
|
||||
</div>
|
||||
{/if}
|
||||
{:else}
|
||||
<div class="bg-red-100 border-l-4 border-red-600 text-orange-700 p-4 m-4" role="alert">
|
||||
|
||||
Reference in New Issue
Block a user