-
Notifications
You must be signed in to change notification settings - Fork 237
Add build trigger filters #3058
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,119 @@ | ||
| <script lang="ts"> | ||
| import { invalidate } from '$app/navigation'; | ||
| import { page } from '$app/state'; | ||
| import { Submit, trackError, trackEvent } from '$lib/actions/analytics'; | ||
| import { CardGrid } from '$lib/components'; | ||
| import { Dependencies } from '$lib/constants'; | ||
| import { Button, Form, InputTags } from '$lib/elements/forms'; | ||
| import { symmetricDifference } from '$lib/helpers/array'; | ||
| import { addNotification } from '$lib/stores/notifications'; | ||
| import { sdk } from '$lib/stores/sdk'; | ||
| import { type Models, Runtime, type Scopes } from '@appwrite.io/console'; | ||
| import { Input, Layout } from '@appwrite.io/pink-svelte'; | ||
|
|
||
| export let func: Models.Function; | ||
|
|
||
| type FuncWithTriggers = Models.Function & { | ||
| providerBranches?: string[]; | ||
| providerPaths?: string[]; | ||
| }; | ||
|
|
||
| function normalizeTriggerPatterns(patterns: string[] = []) { | ||
| return [...new Set(patterns.map((pattern) => pattern.trim()).filter(Boolean))]; | ||
| } | ||
|
|
||
| let providerBranches: string[] = normalizeTriggerPatterns( | ||
| (func as FuncWithTriggers).providerBranches | ||
| ); | ||
| let providerPaths: string[] = normalizeTriggerPatterns( | ||
| (func as FuncWithTriggers).providerPaths | ||
| ); | ||
| let savedBranches = normalizeTriggerPatterns((func as FuncWithTriggers).providerBranches); | ||
| let savedPaths = normalizeTriggerPatterns((func as FuncWithTriggers).providerPaths); | ||
|
|
||
| async function update() { | ||
| providerBranches = normalizeTriggerPatterns(providerBranches); | ||
| providerPaths = normalizeTriggerPatterns(providerPaths); | ||
|
|
||
| try { | ||
| await sdk.forProject(page.params.region, page.params.project).functions.update({ | ||
| functionId: func.$id, | ||
| name: func.name, | ||
| runtime: func.runtime as Runtime, | ||
| execute: func.execute?.length ? (func.execute as string[]) : undefined, | ||
| events: func.events?.length ? (func.events as string[]) : undefined, | ||
| schedule: func.schedule ?? undefined, | ||
| timeout: func.timeout ?? undefined, | ||
| enabled: func.enabled ?? undefined, | ||
| logging: func.logging ?? undefined, | ||
| entrypoint: func.entrypoint ?? undefined, | ||
| commands: func.commands ?? undefined, | ||
| scopes: func.scopes?.length ? (func.scopes as Scopes[]) : undefined, | ||
| installationId: func.installationId ?? undefined, | ||
| providerRepositoryId: func.providerRepositoryId ?? undefined, | ||
| providerBranch: func.providerBranch ?? undefined, | ||
| providerSilentMode: func.providerSilentMode ?? undefined, | ||
| providerRootDirectory: func.providerRootDirectory ?? undefined, | ||
| buildSpecification: func.buildSpecification ?? undefined, | ||
| providerBranches, | ||
| providerPaths | ||
| }); | ||
| savedBranches = [...providerBranches]; | ||
| savedPaths = [...providerPaths]; | ||
| await invalidate(Dependencies.FUNCTION); | ||
| addNotification({ | ||
| type: 'success', | ||
| message: 'Build triggers have been updated successfully' | ||
| }); | ||
| trackEvent(Submit.FunctionUpdateConfiguration); | ||
| } catch (error) { | ||
| addNotification({ | ||
| type: 'error', | ||
| message: error.message | ||
| }); | ||
| trackError(error, Submit.FunctionUpdateConfiguration); | ||
| } | ||
| } | ||
|
|
||
| $: isDisabled = | ||
|
Comment on lines
+14
to
+78
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Both new |
||
| !symmetricDifference(providerBranches, savedBranches).length && | ||
| !symmetricDifference(providerPaths, savedPaths).length; | ||
| </script> | ||
|
|
||
| {#if func.providerRepositoryId} | ||
| <Form onSubmit={update}> | ||
| <CardGrid> | ||
| <svelte:fragment slot="title">Build triggers</svelte:fragment> | ||
| Control which branch pushes and file changes trigger automatic deployments. Use glob patterns | ||
| to include or exclude specific branches and paths. | ||
| <svelte:fragment slot="aside"> | ||
| <Layout.Stack gap="xl"> | ||
| <Layout.Stack gap="s"> | ||
| <InputTags | ||
| id="providerBranches" | ||
| label="Branch filters" | ||
| placeholder={providerBranches.length | ||
| ? '' | ||
| : 'e.g. main, feat/*, !hotfix/*'} | ||
| bind:tags={providerBranches} /> | ||
| <Input.Helper state="default" | ||
| >Leave empty to deploy on all branches. Prefix with <code>!</code> to exclude.</Input.Helper> | ||
| </Layout.Stack> | ||
| <Layout.Stack gap="s"> | ||
| <InputTags | ||
| id="providerPaths" | ||
| label="Path filters" | ||
| placeholder={providerPaths.length ? '' : 'e.g. src/**, !docs/**'} | ||
| bind:tags={providerPaths} /> | ||
| <Input.Helper state="default" | ||
| >Leave empty to deploy on all file changes. Prefix with <code>!</code> | ||
| to exclude.</Input.Helper> | ||
| </Layout.Stack> | ||
| </Layout.Stack> | ||
| </svelte:fragment> | ||
| <svelte:fragment slot="actions"> | ||
| <Button disabled={isDisabled} submit>Update</Button> | ||
| </svelte:fragment> | ||
| </CardGrid> | ||
| </Form> | ||
| {/if} | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,117 @@ | ||
| <script lang="ts"> | ||
| import { invalidate } from '$app/navigation'; | ||
| import { page } from '$app/state'; | ||
| import { Submit, trackError, trackEvent } from '$lib/actions/analytics'; | ||
| import { CardGrid } from '$lib/components'; | ||
| import { Dependencies } from '$lib/constants'; | ||
| import { Button, Form, InputTags } from '$lib/elements/forms'; | ||
| import { symmetricDifference } from '$lib/helpers/array'; | ||
| import { addNotification } from '$lib/stores/notifications'; | ||
| import { sdk } from '$lib/stores/sdk'; | ||
| import { Adapter, BuildRuntime, Framework, type Models } from '@appwrite.io/console'; | ||
| import { Input, Layout } from '@appwrite.io/pink-svelte'; | ||
|
|
||
| export let site: Models.Site; | ||
|
|
||
| type SiteWithTriggers = Models.Site & { providerBranches?: string[]; providerPaths?: string[] }; | ||
|
|
||
| function normalizeTriggerPatterns(patterns: string[] = []) { | ||
| return [...new Set(patterns.map((pattern) => pattern.trim()).filter(Boolean))]; | ||
| } | ||
|
|
||
| let providerBranches: string[] = normalizeTriggerPatterns( | ||
| (site as SiteWithTriggers).providerBranches | ||
| ); | ||
| let providerPaths: string[] = normalizeTriggerPatterns( | ||
| (site as SiteWithTriggers).providerPaths | ||
| ); | ||
| let savedBranches = normalizeTriggerPatterns((site as SiteWithTriggers).providerBranches); | ||
| let savedPaths = normalizeTriggerPatterns((site as SiteWithTriggers).providerPaths); | ||
|
|
||
| async function update() { | ||
| providerBranches = normalizeTriggerPatterns(providerBranches); | ||
| providerPaths = normalizeTriggerPatterns(providerPaths); | ||
|
|
||
| try { | ||
| await sdk.forProject(page.params.region, page.params.project).sites.update({ | ||
| siteId: site.$id, | ||
| name: site.name, | ||
| framework: site.framework as Framework, | ||
| enabled: site.enabled ?? undefined, | ||
| logging: site.logging ?? undefined, | ||
| timeout: site.timeout ?? undefined, | ||
| installCommand: site.installCommand ?? undefined, | ||
| buildCommand: site.buildCommand ?? undefined, | ||
| startCommand: site.startCommand ?? undefined, | ||
| outputDirectory: site.outputDirectory ?? undefined, | ||
| buildRuntime: (site.buildRuntime as BuildRuntime) ?? undefined, | ||
| adapter: (site.adapter as Adapter) ?? undefined, | ||
| fallbackFile: site.fallbackFile ?? undefined, | ||
| installationId: site.installationId ?? undefined, | ||
| providerRepositoryId: site.providerRepositoryId ?? undefined, | ||
| providerBranch: site.providerBranch ?? undefined, | ||
| providerSilentMode: site.providerSilentMode ?? undefined, | ||
| providerRootDirectory: site.providerRootDirectory ?? undefined, | ||
| buildSpecification: site.buildSpecification ?? undefined, | ||
| providerBranches, | ||
| providerPaths | ||
| }); | ||
| savedBranches = [...providerBranches]; | ||
| savedPaths = [...providerPaths]; | ||
| await invalidate(Dependencies.SITE); | ||
| addNotification({ | ||
| type: 'success', | ||
| message: 'Build triggers have been updated successfully' | ||
| }); | ||
| trackEvent(Submit.SiteUpdateConfiguration); | ||
| } catch (error) { | ||
| addNotification({ | ||
| type: 'error', | ||
| message: error.message | ||
| }); | ||
| trackError(error, Submit.SiteUpdateConfiguration); | ||
| } | ||
| } | ||
|
|
||
| $: isDisabled = | ||
| !symmetricDifference(providerBranches, savedBranches).length && | ||
| !symmetricDifference(providerPaths, savedPaths).length; | ||
| </script> | ||
|
|
||
| {#if site.providerRepositoryId} | ||
| <Form onSubmit={update}> | ||
| <CardGrid> | ||
| <svelte:fragment slot="title">Build triggers</svelte:fragment> | ||
| Control which branch pushes and file changes trigger automatic deployments. Use glob patterns | ||
| to include or exclude specific branches and paths. | ||
| <svelte:fragment slot="aside"> | ||
| <Layout.Stack gap="xl"> | ||
| <Layout.Stack gap="s"> | ||
| <InputTags | ||
| id="providerBranches" | ||
| label="Branch filters" | ||
| placeholder={providerBranches.length | ||
| ? '' | ||
| : 'e.g. main, feat/*, !hotfix/*'} | ||
| bind:tags={providerBranches} /> | ||
| <Input.Helper state="default" | ||
| >Leave empty to deploy on all branches. Prefix with <code>!</code> to exclude.</Input.Helper> | ||
| </Layout.Stack> | ||
| <Layout.Stack gap="s"> | ||
| <InputTags | ||
| id="providerPaths" | ||
| label="Path filters" | ||
| placeholder={providerPaths.length ? '' : 'e.g. src/**, !docs/**'} | ||
| bind:tags={providerPaths} /> | ||
| <Input.Helper state="default" | ||
| >Leave empty to deploy on all file changes. Prefix with <code>!</code> | ||
| to exclude.</Input.Helper> | ||
| </Layout.Stack> | ||
| </Layout.Stack> | ||
| </svelte:fragment> | ||
| <svelte:fragment slot="actions"> | ||
| <Button disabled={isDisabled} submit>Update</Button> | ||
| </svelte:fragment> | ||
| </CardGrid> | ||
| </Form> | ||
| {/if} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
providerBranchesandproviderPathsare not present onModels.Function(norModels.Sitein the sites component), so theas FuncWithTriggerscast silently resolves toundefinedat runtime.normalizeTriggerPatternsthen defaults to[], meaning the form always opens empty even when the server already has branch/path filters stored. A user who saves without noticing will silently clear all existing trigger config. If the SDK response does carry these fields at runtime (without them being reflected in TypeScript types), the type augmentation workaround should be accompanied by a comment explaining that, and the PR should ensure the SDK pin is bumped to a version that properly types these fields.