mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-09-10 08:07:03 +00:00
fix tarring the entire cache back to s3 + UX nits
This commit is contained in:
@@ -147,8 +147,9 @@ async fn copy_cache_to_bucket_as_tar(bucket: &str) {
|
||||
}
|
||||
|
||||
match Command::new("rclone")
|
||||
.current_dir(ROOT_CACHE_DIR)
|
||||
.arg("copyto")
|
||||
.arg(ROOT_CACHE_DIR)
|
||||
.arg(TAR_CACHE_FILENAME)
|
||||
.arg(format!(":s3,env_auth=true:{bucket}/{TAR_CACHE_FILENAME}"))
|
||||
.arg("--size-only")
|
||||
.arg("--fast-list")
|
||||
|
||||
@@ -409,8 +409,8 @@
|
||||
timeoutModel && clearTimeout(timeoutModel)
|
||||
timeoutModel = setTimeout(() => {
|
||||
code = getCode()
|
||||
dispatch('change')
|
||||
}, 500)
|
||||
dispatch('change')
|
||||
})
|
||||
|
||||
editor.onDidFocusEditorText(() => {
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
import Button from './common/button/Button.svelte'
|
||||
import HighlightCode from './HighlightCode.svelte'
|
||||
import DrawerContent from './common/drawer/DrawerContent.svelte'
|
||||
import { Drawer } from './common'
|
||||
import { Badge, Drawer } from './common'
|
||||
|
||||
export let lang: 'python3' | 'deno' | 'go' | 'bash'
|
||||
export let editor: Editor
|
||||
@@ -213,17 +213,14 @@
|
||||
<ResourceEditor bind:this={resourceEditor} on:refresh={resourcePicker.openDrawer} />
|
||||
<VariableEditor bind:this={variableEditor} on:create={variablePicker.openDrawer} />
|
||||
|
||||
<div class="flex flex-row justify-between items-center overflow-hidden w-full">
|
||||
<div class="flex flex-row justify-between items-center overflow-hidden w-full px-1">
|
||||
<div class="flex flex-row divide-x items-center">
|
||||
<div class="mx-2">
|
||||
<span
|
||||
title={validCode
|
||||
? 'last signature parsing was sucessful'
|
||||
: 'last signature parsing was NOT succesful'}
|
||||
class="relative inline-flex rounded-full h-2 w-2 {validCode
|
||||
? 'bg-green-500/80'
|
||||
: 'bg-red-500'}"
|
||||
/>
|
||||
{#if validCode}
|
||||
<Badge color="green">Inputs</Badge>
|
||||
{:else}
|
||||
<Badge color="red">Inputs</Badge>
|
||||
{/if}
|
||||
</div>
|
||||
<div>
|
||||
<Button
|
||||
@@ -293,9 +290,9 @@
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="py-1">
|
||||
<Button
|
||||
btnClasses="ml-1 !font-medium"
|
||||
btnClasses="!font-medium"
|
||||
size="xs"
|
||||
spacingSize="md"
|
||||
color="light"
|
||||
@@ -305,7 +302,7 @@
|
||||
{#if !iconOnly}
|
||||
Reload assistants
|
||||
{/if}
|
||||
<span class="ml-1">
|
||||
<span class="ml-1 -my-1">
|
||||
{#if lang == 'deno'}
|
||||
(<span class={websocketAlive.deno ? 'green' : 'text-red-700'}>Deno</span>)
|
||||
{:else if lang == 'go'}
|
||||
|
||||
@@ -1,197 +0,0 @@
|
||||
<script lang="ts">
|
||||
import { scriptPathToHref } from '$lib/utils'
|
||||
|
||||
import { slide } from 'svelte/transition'
|
||||
|
||||
import InputTransformsViewer from './InputTransformsViewer.svelte'
|
||||
import IconedPath from './IconedPath.svelte'
|
||||
import type { FlowModule } from '$lib/gen'
|
||||
import HighlightCode from './HighlightCode.svelte'
|
||||
import { faBug } from '@fortawesome/free-solid-svg-icons'
|
||||
import Icon from 'svelte-awesome'
|
||||
|
||||
export let modules: FlowModule[]
|
||||
export let failureModule: FlowModule | undefined
|
||||
|
||||
let open: { [id: number]: boolean } = {}
|
||||
</script>
|
||||
|
||||
<p class="font-black text-lg my-6 w-full">
|
||||
<span>{modules?.length} Step{modules?.length > 1 ? 's' : ''} </span>
|
||||
<span class="mt-4" />
|
||||
</p>
|
||||
<ul class="-mb-8 w-full">
|
||||
{#each modules ?? [] as mod, i}
|
||||
<li class="w-full">
|
||||
<div class="relative pb-8 w-full">
|
||||
{#if i < (modules ?? []).length - 1 || failureModule}
|
||||
<span class="absolute top-4 left-4 -ml-px h-full w-0.5 bg-gray-200" aria-hidden="true" />
|
||||
{/if}
|
||||
<div class="relative flex space-x-3">
|
||||
<div>
|
||||
<span
|
||||
class="h-8 w-8 rounded-full bg-blue-600 flex items-center justify-center ring-8 ring-white text-white"
|
||||
>
|
||||
{i + 1}
|
||||
</span>
|
||||
</div>
|
||||
<div class="min-w-0 flex-1 pt-1.5 flex justify-between space-x-4 w-full">
|
||||
<div class="w-full">
|
||||
<span class="text-black">{mod?.summary ?? ''}</span>
|
||||
<p class="text-sm text-gray-500">
|
||||
{#if mod?.value?.type == 'script'}
|
||||
<a
|
||||
target="_blank"
|
||||
href={scriptPathToHref(mod?.value?.path ?? '')}
|
||||
class="font-medium text-gray-900"
|
||||
>
|
||||
<IconedPath path={mod?.value?.path ?? ''} />
|
||||
</a>
|
||||
{#if mod?.value?.path?.startsWith('hub/')}
|
||||
<div>
|
||||
<button
|
||||
on:click={async () => {
|
||||
open[i] = !open[i]
|
||||
}}
|
||||
class="mb-2 underline text-black"
|
||||
>
|
||||
View code and inputs {open[i] ? '(-)' : '(+)'}</button
|
||||
>
|
||||
{#if open[i]}
|
||||
<div class="border border-black p-2 bg-gray-50 divide-y">
|
||||
<InputTransformsViewer
|
||||
inputTransforms={mod?.value?.input_transforms ??
|
||||
mod?.input_transforms ??
|
||||
{}}
|
||||
/>
|
||||
<div class="w-full h-full mt-6">
|
||||
<iframe
|
||||
style="height: 400px;"
|
||||
class="w-full h-full text-sm"
|
||||
title="embedded script from hub"
|
||||
frameborder="0"
|
||||
src="https://hub.windmill.dev/embed/script/{mod?.value?.path?.substring(
|
||||
4
|
||||
)}"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
{:else if mod?.value?.type == 'rawscript'}
|
||||
<button on:click={() => (open[i] = !open[i])} class="mb-2 underline text-black">
|
||||
Raw {mod?.value?.language} script {open[i] ? '(-)' : '(+)'}</button
|
||||
>
|
||||
|
||||
{#if open[i]}
|
||||
<div transition:slide class="border border-black p-2 bg-gray-50 w-full">
|
||||
<InputTransformsViewer
|
||||
inputTransforms={mod?.value?.input_transforms ??
|
||||
mod?.input_transforms ??
|
||||
{}}
|
||||
/>
|
||||
<HighlightCode
|
||||
language={mod?.value?.language ?? 'deno'}
|
||||
code={mod?.value?.content}
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
{:else if mod?.value?.type == 'forloopflow'}
|
||||
For loop over all the elements of the list returned as a result of step {i}:
|
||||
<svelte:self modules={mod.value.modules} />
|
||||
{/if}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
{/each}
|
||||
{#if failureModule}
|
||||
<li class="w-full">
|
||||
<div class="relative pb-8 w-full">
|
||||
<div class="relative flex space-x-3">
|
||||
<div>
|
||||
<span
|
||||
class="h-8 w-8 rounded-full bg-red-600 flex items-center justify-center ring-8 ring-white text-white"
|
||||
>
|
||||
<Icon data={faBug} />
|
||||
</span>
|
||||
</div>
|
||||
<div class="min-w-0 flex-1 pt-1.5 flex justify-between space-x-4 w-full">
|
||||
<div class="w-full">
|
||||
<span class="text-black">{failureModule?.summary ?? ''}</span>
|
||||
<p class="text-sm text-gray-500">
|
||||
{#if failureModule?.value?.type == 'script'}
|
||||
<a
|
||||
target="_blank"
|
||||
href={scriptPathToHref(failureModule?.value?.path ?? '')}
|
||||
class="font-medium text-gray-900"
|
||||
>
|
||||
<IconedPath path={failureModule?.value?.path ?? ''} />
|
||||
</a>
|
||||
{#if failureModule?.value?.path?.startsWith('hub/')}
|
||||
<div>
|
||||
<button
|
||||
on:click={async () => {
|
||||
open[modules.length] = !open[modules.length]
|
||||
}}
|
||||
class="mb-2 underline text-black"
|
||||
>
|
||||
View code and inputs {open[modules.length] ? '(-)' : '(+)'}</button
|
||||
>
|
||||
{#if open[modules.length]}
|
||||
<div class="border border-black p-2 bg-gray-50 divide-y">
|
||||
<InputTransformsViewer
|
||||
inputTransforms={failureModule?.value?.input_transforms ??
|
||||
failureModule?.input_transforms ??
|
||||
{}}
|
||||
/>
|
||||
<div class="w-full h-full mt-6">
|
||||
<iframe
|
||||
style="height: 400px;"
|
||||
class="w-full h-full text-sm"
|
||||
title="embedded script from hub"
|
||||
frameborder="0"
|
||||
src="https://hub.windmill.dev/embed/script/{failureModule?.value?.path?.substring(
|
||||
4
|
||||
)}"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
{:else if failureModule?.value?.type == 'rawscript'}
|
||||
<button
|
||||
on:click={() => (open[modules.length] = !open[modules.length])}
|
||||
class="mb-2 underline text-black"
|
||||
>
|
||||
Error handler: Raw {failureModule?.value?.language} script {open[modules.length]
|
||||
? '(-)'
|
||||
: '(+)'}</button
|
||||
>
|
||||
|
||||
{#if open[modules.length]}
|
||||
<div transition:slide class="border border-black p-2 bg-gray-50 w-full">
|
||||
<InputTransformsViewer
|
||||
inputTransforms={failureModule?.value?.input_transforms ??
|
||||
failureModule?.input_transforms ??
|
||||
{}}
|
||||
/>
|
||||
<HighlightCode
|
||||
language={failureModule?.value?.language ?? 'deno'}
|
||||
code={failureModule?.value?.content}
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
{/if}
|
||||
</ul>
|
||||
@@ -2,6 +2,7 @@
|
||||
import type { Schema } from '$lib/common'
|
||||
import type { InputTransform } from '$lib/gen'
|
||||
import { allTrue } from '$lib/utils'
|
||||
import { slide } from 'svelte/transition'
|
||||
import ArgInput from './ArgInput.svelte'
|
||||
import InputTransformForm from './InputTransformForm.svelte'
|
||||
|
||||
@@ -15,6 +16,7 @@
|
||||
export let extraLib: string = 'missing extraLib'
|
||||
export let importPath: string | undefined = undefined
|
||||
export let autofocus = false
|
||||
export let animateNew = false
|
||||
|
||||
let clazz: string = ''
|
||||
export { clazz as class }
|
||||
@@ -41,35 +43,37 @@
|
||||
<div class="w-full {clazz}">
|
||||
{#if Object.keys(schema?.properties ?? {}).length > 0}
|
||||
{#each Object.keys(schema?.properties ?? {}) as argName, i (argName)}
|
||||
{#if inputTransform}
|
||||
<InputTransformForm
|
||||
bind:arg={args[argName]}
|
||||
bind:schema
|
||||
bind:argName
|
||||
bind:inputCheck={inputCheck[argName]}
|
||||
bind:extraLib
|
||||
bind:importPath
|
||||
/>
|
||||
{:else}
|
||||
<ArgInput
|
||||
autofocus={i == 0 && autofocus}
|
||||
label={argName}
|
||||
bind:description={schema.properties[argName].description}
|
||||
bind:value={args[argName]}
|
||||
type={schema.properties[argName].type}
|
||||
required={schema.required.includes(argName)}
|
||||
bind:pattern={schema.properties[argName].pattern}
|
||||
bind:valid={inputCheck[argName]}
|
||||
defaultValue={schema.properties[argName].default}
|
||||
bind:enum_={schema.properties[argName].enum}
|
||||
bind:format={schema.properties[argName].format}
|
||||
contentEncoding={schema.properties[argName].contentEncoding}
|
||||
properties={schema.properties[argName].properties}
|
||||
bind:itemsType={schema.properties[argName].items}
|
||||
disabled={disabledArgs.includes(argName)}
|
||||
{editableSchema}
|
||||
/>
|
||||
{/if}
|
||||
<div transition:slide|local>
|
||||
{#if inputTransform}
|
||||
<InputTransformForm
|
||||
bind:arg={args[argName]}
|
||||
bind:schema
|
||||
bind:argName
|
||||
bind:inputCheck={inputCheck[argName]}
|
||||
bind:extraLib
|
||||
bind:importPath
|
||||
/>
|
||||
{:else}
|
||||
<ArgInput
|
||||
autofocus={i == 0 && autofocus}
|
||||
label={argName}
|
||||
bind:description={schema.properties[argName].description}
|
||||
bind:value={args[argName]}
|
||||
type={schema.properties[argName].type}
|
||||
required={schema.required.includes(argName)}
|
||||
bind:pattern={schema.properties[argName].pattern}
|
||||
bind:valid={inputCheck[argName]}
|
||||
defaultValue={schema.properties[argName].default}
|
||||
bind:enum_={schema.properties[argName].enum}
|
||||
bind:format={schema.properties[argName].format}
|
||||
contentEncoding={schema.properties[argName].contentEncoding}
|
||||
properties={schema.properties[argName].properties}
|
||||
bind:itemsType={schema.properties[argName].items}
|
||||
disabled={disabledArgs.includes(argName)}
|
||||
{editableSchema}
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
{/each}
|
||||
{:else}
|
||||
<p class="italic text-sm">No inputs</p>
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
import UnsavedConfirmationModal from './common/confirmationModal/UnsavedConfirmationModal.svelte'
|
||||
import { dirtyStore } from './common/confirmationModal/dirtyStore'
|
||||
import { Button } from './common'
|
||||
import { faChevronDown, faChevronUp, faPen } from '@fortawesome/free-solid-svg-icons'
|
||||
import { faChevronDown, faChevronUp, faPen, faSave } from '@fortawesome/free-solid-svg-icons'
|
||||
import Breadcrumb from './common/breadcrumb/Breadcrumb.svelte'
|
||||
import Toggle from './Toggle.svelte'
|
||||
|
||||
@@ -86,11 +86,13 @@
|
||||
<UnsavedConfirmationModal />
|
||||
<div class="flex flex-col h-screen">
|
||||
<!-- Nav between steps-->
|
||||
<div class="flex flex-col w-full px-4 py-2 border-b shadow-sm">
|
||||
<div class="justify-between flex flex-row w-full items-center overflow-x-auto scrollbar-hidden">
|
||||
<div class="flex flex-row">
|
||||
<div class="flex flex-col w-full px-2 py-1 border-b shadow-sm">
|
||||
<div
|
||||
class="justify-between flex flex-row w-full items-center overflow-x-auto scrollbar-hidden px-2"
|
||||
>
|
||||
<div class="flex flex-row py-1">
|
||||
<Breadcrumb
|
||||
items={['Metadata', 'Code', 'UI Customisation']}
|
||||
items={['Metadata', 'Code', 'Advanced']}
|
||||
selectedIndex={step}
|
||||
on:select={(e) => changeStep(e.detail.index + 1)}
|
||||
disabled={pathError != ''}
|
||||
@@ -130,13 +132,6 @@
|
||||
</Button>
|
||||
</div>
|
||||
<div class="flex flex-row gap-x-2">
|
||||
<Button
|
||||
size="sm"
|
||||
variant={step == 1 ? 'border' : 'contained'}
|
||||
disabled={step === 1 && pathError !== ''}
|
||||
btnClasses={step == 1 && initialPath == '' ? 'hidden sm:invisible' : ''}
|
||||
on:click={editScript}>Save (commit)</Button
|
||||
>
|
||||
<Button
|
||||
variant="border"
|
||||
size="sm"
|
||||
@@ -145,18 +140,22 @@
|
||||
>
|
||||
Back
|
||||
</Button>
|
||||
{#if step < 3}
|
||||
<Button
|
||||
size="sm"
|
||||
btnClasses={step == 3 ? 'hidden sm:invisible' : ''}
|
||||
disabled={step === 1 && pathError !== ''}
|
||||
on:click={() => changeStep(step + 1)}
|
||||
>
|
||||
Next
|
||||
</Button>
|
||||
{:else}
|
||||
<Button size="sm" on:click={editScript}>Save</Button>
|
||||
{/if}
|
||||
<Button
|
||||
size="sm"
|
||||
variant={step == 1 ? 'contained' : 'border'}
|
||||
btnClasses={step == 3 ? 'invisible' : ''}
|
||||
disabled={step === 1 && pathError !== ''}
|
||||
on:click={() => changeStep(step + 1)}
|
||||
>
|
||||
Next
|
||||
</Button>
|
||||
<Button
|
||||
size="sm"
|
||||
variant={step == 1 ? 'border' : 'contained'}
|
||||
disabled={step === 1 && pathError !== ''}
|
||||
btnClasses={step == 1 && initialPath == '' ? 'invisible' : ''}
|
||||
on:click={editScript}>Save</Button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -146,6 +146,7 @@
|
||||
bind:code
|
||||
bind:websocketAlive
|
||||
bind:this={editor}
|
||||
on:change={() => inferSchema()}
|
||||
cmdEnterAction={async () => {
|
||||
await inferSchema()
|
||||
runTest()
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
</script>
|
||||
|
||||
<div class="w-full">
|
||||
<h1 class="my-4">UI customisation</h1>
|
||||
<h1 class="my-4">Advanced</h1>
|
||||
|
||||
<Tabs selected="ui">
|
||||
<Tab value="ui">UI</Tab>
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
variant === 'border' ? 'border' : '',
|
||||
ButtonType.FontSizeClasses[size],
|
||||
ButtonType.SpacingClasses[spacingSize],
|
||||
'focus:ring-4 font-semibold',
|
||||
'focus:ring-2 font-semibold',
|
||||
'rounded-md',
|
||||
'justify-center items-center text-center whitespace-nowrap inline-flex',
|
||||
btnClasses,
|
||||
|
||||
@@ -176,9 +176,15 @@
|
||||
automaticLayout={true}
|
||||
cmdEnterAction={async () => {
|
||||
selected = 'test'
|
||||
if (flowModule.value.type === 'rawscript') {
|
||||
flowModule.value.content = editor.getCode()
|
||||
}
|
||||
await reload(flowModule)
|
||||
modulePreview?.runTestWithStepArgs()
|
||||
}}
|
||||
on:change={async (event) => {
|
||||
await reload(flowModule)
|
||||
}}
|
||||
formatAction={() => reload(flowModule)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -5,10 +5,10 @@
|
||||
import CenteredModal from '$lib/components/CenteredModal.svelte'
|
||||
import { sendUserToast } from '$lib/utils'
|
||||
import FlowMetadata from '$lib/components/FlowMetadata.svelte'
|
||||
import FlowModulesViewer from '$lib/components/FlowModulesViewer.svelte'
|
||||
import JobArgs from '$lib/components/JobArgs.svelte'
|
||||
import { onDestroy, onMount } from 'svelte'
|
||||
import Tooltip from '$lib/components/Tooltip.svelte'
|
||||
import FlowGraph from '$lib/components/graph/FlowGraph.svelte'
|
||||
|
||||
let job: Job | undefined = undefined
|
||||
let currentApprovers: { resume_id: number; approver: string }[] = []
|
||||
@@ -21,6 +21,7 @@
|
||||
.includes(new Number($page.params.resume).valueOf())
|
||||
|
||||
let timeout: NodeJS.Timer | undefined = undefined
|
||||
let error: string | undefined = undefined
|
||||
|
||||
getJob()
|
||||
|
||||
@@ -28,14 +29,16 @@
|
||||
timeout = setInterval(getJob, 1000)
|
||||
window.onunhandledrejection = (event: PromiseRejectionEvent) => {
|
||||
event.preventDefault()
|
||||
|
||||
timeout && clearInterval(timeout)
|
||||
if (event.reason?.message) {
|
||||
const { message, body, status } = event.reason
|
||||
|
||||
if (body) {
|
||||
sendUserToast(`${body}`, true)
|
||||
error = body.toString()
|
||||
} else {
|
||||
sendUserToast(`${message}`, true)
|
||||
error = message.toString()
|
||||
}
|
||||
} else {
|
||||
console.log('Caught unhandled promise rejection without message', event)
|
||||
@@ -48,19 +51,15 @@
|
||||
})
|
||||
|
||||
async function getJob() {
|
||||
try {
|
||||
const suspendedJobFlow = await JobService.getSuspendedJobFlow({
|
||||
workspace: $page.params.workspace,
|
||||
id: $page.params.job,
|
||||
resumeId: new Number($page.params.resume).valueOf(),
|
||||
signature: $page.params.hmac,
|
||||
approver
|
||||
})
|
||||
job = suspendedJobFlow.job
|
||||
currentApprovers = suspendedJobFlow.approvers
|
||||
} catch (e) {
|
||||
sendUserToast(e.message, true)
|
||||
}
|
||||
const suspendedJobFlow = await JobService.getSuspendedJobFlow({
|
||||
workspace: $page.params.workspace,
|
||||
id: $page.params.job,
|
||||
resumeId: new Number($page.params.resume).valueOf(),
|
||||
signature: $page.params.hmac,
|
||||
approver
|
||||
})
|
||||
job = suspendedJobFlow.job
|
||||
currentApprovers = suspendedJobFlow.approvers
|
||||
}
|
||||
|
||||
async function resume() {
|
||||
@@ -92,6 +91,9 @@
|
||||
|
||||
<div class="min-h-screen antialiased text-gray-900">
|
||||
<CenteredModal title="Approve resuming of flow?">
|
||||
{#if error}
|
||||
<h1 class="text-red-400">{error}</h1>
|
||||
{/if}
|
||||
<div class="flex flex-row justify-between flex-wrap sm:flex-nowrap gap-x-4">
|
||||
<div class="w-full">
|
||||
<h2 class="mt-4">Current approvers</h2>
|
||||
@@ -167,10 +169,13 @@
|
||||
</div>
|
||||
{#if job && job.raw_flow}
|
||||
<h2 class="mt-10">Flow details</h2>
|
||||
<FlowModulesViewer
|
||||
modules={job.raw_flow?.modules}
|
||||
failureModule={job.raw_flow?.failure_module}
|
||||
/>
|
||||
<div class="border border-gray-700">
|
||||
<FlowGraph
|
||||
modules={job.raw_flow?.modules}
|
||||
failureModule={job.raw_flow?.failure_module}
|
||||
notSelectable
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
</CenteredModal>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user