Skip to content
This repository was archived by the owner on Sep 21, 2026. It is now read-only.

Commit 1e3b03a

Browse files
committed
Show warning when VCS integration is not authorized for auto-deployments
1 parent 6965800 commit 1e3b03a

4 files changed

Lines changed: 206 additions & 56 deletions

File tree

‎src/routes/(console)/project-[region]-[project]/functions/function-[function]/+page.svelte‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import CreateActionMenu from './(components)/createActionMenu.svelte';
3333
import { Menu } from '$lib/components/menu';
3434
import DownloadActionMenuItem from './(components)/downloadActionMenuItem.svelte';
35+
import { Link } from '$lib/elements';
3536
3637
export let data;
3738
@@ -93,6 +94,19 @@
9394
title="Some configuration changes are not live yet. Your function is redeploying — changes will be applied once the build is complete." />
9495
{/if}
9596
{/if}
97+
98+
{#if data.repository && !data.repository.authorized}
99+
<Alert.Inline status="warning">
100+
Integration with your repository is not authorized to perform auto-deployments.
101+
Please add the repository to the installation settings
102+
<Link
103+
variant="muted"
104+
external
105+
href={`https://github.com/settings/installations/${data.repository.providerInstallationId}`}>
106+
here
107+
</Link>.
108+
</Alert.Inline>
109+
{/if}
96110
<Layout.Stack gap="xxxl">
97111
{#if activeDeployment}
98112
<DeploymentCard

‎src/routes/(console)/project-[region]-[project]/functions/function-[function]/+page.ts‎

Lines changed: 116 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -13,56 +13,128 @@ export const load: PageLoad = async ({ params, depends, url, route, parent }) =>
1313
const offset = pageToOffset(page, limit);
1414
const query = getQuery(url);
1515

16-
const parsedQueries = queryParamToMap(query || '[]');
17-
queries.set(parsedQueries);
18-
let activeDeployment: Models.Deployment | null = null;
19-
if (data.function.deploymentId) {
20-
try {
21-
activeDeployment = await sdk
22-
.forProject(params.region, params.project)
23-
.functions.getDeployment({
24-
functionId: params.function,
25-
deploymentId: data.function.deploymentId
26-
});
27-
} catch (error) {
28-
// active deployment with the requested ID could not be found
29-
activeDeployment = null;
30-
}
31-
}
16+
const [deploymentList, activeDeployment, repository] = await Promise.all([
17+
loadDeploymentList({
18+
region: params.region,
19+
project: params.project,
20+
functionId: params.function,
21+
limit,
22+
offset,
23+
query
24+
}),
25+
data.function.deploymentId
26+
? loadActiveDeployment({
27+
region: params.region,
28+
project: params.project,
29+
functionId: params.function,
30+
deploymentId: data.function.deploymentId
31+
})
32+
: Promise.resolve(null),
33+
data.function.installationId && data.function.providerRepositoryId
34+
? loadRepository({
35+
region: params.region,
36+
project: params.project,
37+
installationId: data.function.installationId,
38+
providerRepositoryId: data.function.providerRepositoryId
39+
})
40+
: Promise.resolve(null)
41+
]);
3242

3343
return {
3444
offset,
3545
limit,
3646
query,
3747
installations: data.installations,
3848
activeDeployment,
39-
deploymentList: await sdk
40-
.forProject(params.region, params.project)
41-
.functions.listDeployments({
42-
functionId: params.function,
43-
queries: [
44-
Query.limit(limit),
45-
Query.offset(offset),
46-
Query.orderDesc(''),
47-
Query.select([
48-
'buildSize',
49-
'sourceSize',
50-
'totalSize',
51-
'buildDuration',
52-
'status',
53-
'type',
54-
'resourceId',
55-
'providerRepositoryUrl',
56-
'providerRepositoryOwner',
57-
'providerRepositoryName',
58-
'providerBranchUrl',
59-
'providerBranch',
60-
'providerCommitMessage',
61-
'providerCommitHash',
62-
'providerCommitUrl'
63-
]),
64-
...parsedQueries.values()
65-
]
66-
})
49+
repository,
50+
deploymentList
6751
};
6852
};
53+
54+
async function loadDeploymentList({
55+
region,
56+
project,
57+
functionId,
58+
limit,
59+
offset,
60+
query
61+
}: {
62+
region: string;
63+
project: string;
64+
functionId: string;
65+
limit: number;
66+
offset: number;
67+
query: string;
68+
}): Promise<Models.DeploymentList> {
69+
const parsedQueries = queryParamToMap(query || '[]');
70+
queries.set(parsedQueries);
71+
72+
return sdk.forProject(region, project).functions.listDeployments({
73+
functionId,
74+
queries: [
75+
Query.limit(limit),
76+
Query.offset(offset),
77+
Query.orderDesc(''),
78+
Query.select([
79+
'buildSize',
80+
'sourceSize',
81+
'totalSize',
82+
'buildDuration',
83+
'status',
84+
'type',
85+
'resourceId',
86+
'providerRepositoryUrl',
87+
'providerRepositoryOwner',
88+
'providerRepositoryName',
89+
'providerBranchUrl',
90+
'providerBranch',
91+
'providerCommitMessage',
92+
'providerCommitHash',
93+
'providerCommitUrl'
94+
]),
95+
...parsedQueries.values()
96+
]
97+
});
98+
}
99+
100+
async function loadActiveDeployment({
101+
region,
102+
project,
103+
functionId,
104+
deploymentId
105+
}: {
106+
region: string;
107+
project: string;
108+
functionId: string;
109+
deploymentId: string;
110+
}): Promise<Models.Deployment | null> {
111+
try {
112+
return await sdk.forProject(region, project).functions.getDeployment({
113+
functionId,
114+
deploymentId
115+
});
116+
} catch (error) {
117+
return null;
118+
}
119+
}
120+
121+
async function loadRepository({
122+
region,
123+
project,
124+
installationId,
125+
providerRepositoryId
126+
}: {
127+
region: string;
128+
project: string;
129+
installationId: string;
130+
providerRepositoryId: string;
131+
}): Promise<Models.ProviderRepository | null> {
132+
try {
133+
return await sdk.forProject(region, project).vcs.getRepository({
134+
installationId,
135+
providerRepositoryId
136+
});
137+
} catch (error) {
138+
return null;
139+
}
140+
}

‎src/routes/(console)/project-[region]-[project]/sites/site-[site]/+page.svelte‎

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<script lang="ts">
22
import { Container } from '$lib/layout';
3-
import { Card, Divider, Empty, Layout, Tooltip } from '@appwrite.io/pink-svelte';
3+
import { Alert, Card, Divider, Empty, Layout, Tooltip } from '@appwrite.io/pink-svelte';
44
import SiteCard from '../(components)/siteCard.svelte';
55
import DomainsOverview from './domainsOverview.svelte';
66
import DeploymentsOverview from './deploymentsOverview.svelte';
@@ -15,6 +15,7 @@
1515
import { base } from '$app/paths';
1616
import type { PageProps } from './$types';
1717
import { regionalProtocol } from '$routes/(console)/project-[region]-[project]/store';
18+
import { Link } from '$lib/elements';
1819
1920
let { data }: PageProps = $props();
2021
@@ -31,6 +32,19 @@
3132

3233
<Container>
3334
<Layout.Stack gap="xxxl">
35+
{#if data.repository && !data.repository.authorized}
36+
<Alert.Inline status="warning">
37+
Integration with your repository is not authorized to perform auto-deployments.
38+
Please add the repository to the installation settings
39+
<Link
40+
variant="muted"
41+
external
42+
href={`https://github.com/settings/installations/${data.repository.providerInstallationId}`}>
43+
here
44+
</Link>.
45+
</Alert.Inline>
46+
{/if}
47+
3448
{#if data?.deployment && data.deployment.status === 'ready'}
3549
<SiteCard deployment={data.deployment} proxyRuleList={data.proxyRuleList}>
3650
{#snippet footer()}

‎src/routes/(console)/project-[region]-[project]/sites/site-[site]/+page.ts‎

Lines changed: 61 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -58,25 +58,75 @@ export const load = async ({ params, depends, parent }) => {
5858
})
5959
]);
6060

61-
let deployment: Models.Deployment | null = null;
62-
if (deploymentList?.total && site.deploymentId) {
63-
try {
64-
deployment = await sdk
65-
.forProject(params.region, params.project)
66-
.sites.getDeployment({ siteId: params.site, deploymentId: site.deploymentId });
67-
} catch (error) {
68-
// active deployment with the requested ID could not be found
69-
deployment = null;
70-
}
71-
}
61+
const [deployment, repository] = await Promise.all([
62+
deploymentList?.total && site.deploymentId
63+
? loadDeployment({
64+
region: params.region,
65+
project: params.project,
66+
siteId: params.site,
67+
deploymentId: site.deploymentId
68+
})
69+
: Promise.resolve(null),
70+
site.installationId && site.providerRepositoryId
71+
? loadRepository({
72+
region: params.region,
73+
project: params.project,
74+
installationId: site.installationId,
75+
providerRepositoryId: site.providerRepositoryId
76+
})
77+
: Promise.resolve(null)
78+
]);
7279

7380
return {
7481
site,
7582
deploymentList,
7683
deployment,
84+
repository,
7785
proxyRuleList,
7886
prodReadyDeployments,
7987
hasProdReadyDeployments:
8088
prodReadyDeployments?.deployments?.filter((d) => d?.$id !== deployment?.$id).length > 0
8189
};
8290
};
91+
92+
async function loadDeployment({
93+
region,
94+
project,
95+
siteId,
96+
deploymentId
97+
}: {
98+
region: string;
99+
project: string;
100+
siteId: string;
101+
deploymentId: string;
102+
}): Promise<Models.Deployment | null> {
103+
try {
104+
return await sdk.forProject(region, project).sites.getDeployment({
105+
siteId,
106+
deploymentId
107+
});
108+
} catch (error) {
109+
return null;
110+
}
111+
}
112+
113+
async function loadRepository({
114+
region,
115+
project,
116+
installationId,
117+
providerRepositoryId
118+
}: {
119+
region: string;
120+
project: string;
121+
installationId: string;
122+
providerRepositoryId: string;
123+
}): Promise<Models.ProviderRepository | null> {
124+
try {
125+
return await sdk.forProject(region, project).vcs.getRepository({
126+
installationId,
127+
providerRepositoryId
128+
});
129+
} catch (error) {
130+
return null;
131+
}
132+
}

0 commit comments

Comments
 (0)