Skip to content

Commit 6789fe2

Browse files
authored
fixing glide deployment to also check remote destination to confirm if deployment already exists or if it really needs updated (#39)
1 parent 0398daa commit 6789fe2

File tree

8 files changed

+160
-66
lines changed

8 files changed

+160
-66
lines changed

README_INTERNAL.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ Add the line "HELLO WORLD" to the end of `README.md`
4141
Then run this command to publish to your local Verdaccio instance:
4242

4343
```bash
44-
./publish_local.sh
44+
./scripts/publish_local.sh
4545
```
4646

4747
## Install Your Updated NPM Package Locally

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "polyapi",
3-
"version": "0.24.18",
3+
"version": "0.24.19",
44
"description": "Poly is a CLI tool to help create and manage your Poly definitions.",
55
"license": "MIT",
66
"repository": {

src/api.ts

Lines changed: 61 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -123,21 +123,39 @@ export const createOrUpdateServerFunction = async (
123123
).data;
124124
};
125125

126+
export const getServerFunctionById = async (id: string) => {
127+
return (
128+
await axios.get<any, AxiosResponse<FunctionDetailsDto>>(
129+
`${getApiBaseURL()}/functions/server/${id}`,
130+
{
131+
headers: {
132+
'Content-Type': 'application/json',
133+
...getApiHeaders(),
134+
},
135+
},
136+
)
137+
).data;
138+
};
139+
126140
export const getServerFunctionByName = async (
127141
context: string,
128142
name: string,
143+
detail = false
129144
) => {
130-
return (
131-
await axios.get<any, AxiosResponse<FunctionBasicDto[]>>(
132-
`${getApiBaseURL()}/functions/server`,
145+
const basic = (
146+
await axios.get<any, AxiosResponse<{ results: FunctionBasicDto[] }>>(
147+
`${getApiBaseURL()}/functions/server?search=${encodeURIComponent(`${context}${context && name ? '.' : ''}${name}`)}`,
133148
{
134149
headers: {
135150
'Content-Type': 'application/json',
136151
...getApiHeaders(),
152+
'x-poly-api-version': '2',
137153
},
138154
},
139155
)
140-
).data.find((fn) => fn.name === name && fn.context === context);
156+
).data.results.find((fn) => fn.name === name && fn.context === context);
157+
if (!detail || !basic) return basic;
158+
return getServerFunctionById(basic.id);
141159
};
142160

143161
export const deleteServerFunction = async (id: string) => {
@@ -178,21 +196,39 @@ export const createOrUpdateClientFunction = async (
178196
).data;
179197
};
180198

199+
export const getClientFunctionById = async (id: string) => {
200+
return (
201+
await axios.get<any, AxiosResponse<FunctionDetailsDto>>(
202+
`${getApiBaseURL()}/functions/client/${id}`,
203+
{
204+
headers: {
205+
'Content-Type': 'application/json',
206+
...getApiHeaders(),
207+
},
208+
},
209+
)
210+
).data;
211+
};
212+
181213
export const getClientFunctionByName = async (
182214
context: string,
183215
name: string,
216+
detail = false,
184217
) => {
185-
return (
186-
await axios.get<any, AxiosResponse<FunctionBasicDto[]>>(
187-
`${getApiBaseURL()}/functions/client`,
218+
const basic = (
219+
await axios.get<any, AxiosResponse<{ results: FunctionBasicDto[] }>>(
220+
`${getApiBaseURL()}/functions/client?search=${encodeURIComponent(`${context}${context && name ? '.' : ''}${name}`)}`,
188221
{
189222
headers: {
190223
'Content-Type': 'application/json',
191224
...getApiHeaders(),
225+
'x-poly-api-version': '2',
192226
},
193227
},
194228
)
195-
).data.find((fn) => fn.name === name && fn.context === context);
229+
).data.results.find((fn) => fn.name === name && fn.context === context);
230+
if (!detail || !basic) return basic;
231+
return getClientFunctionById(basic.id);
196232
};
197233

198234
export const deleteClientFunction = async (id: string) => {
@@ -482,8 +518,22 @@ export const createOrUpdateWebhook = async (
482518
).data;
483519
};
484520

485-
export const getWebhookByName = async (context: string, name: string) => {
521+
export const getWebhookById = async (id: string) => {
486522
return (
523+
await axios.get<any, AxiosResponse<WebhookHandleDto>>(
524+
`${getApiBaseURL()}/webhooks/${id}`,
525+
{
526+
headers: {
527+
'Content-Type': 'application/json',
528+
...getApiHeaders(),
529+
},
530+
},
531+
)
532+
).data;
533+
};
534+
535+
export const getWebhookByName = async (context: string, name: string, detail = false) => {
536+
const basic = (
487537
await axios.get<any, AxiosResponse<WebhookHandleBasicDto[]>>(
488538
`${getApiBaseURL()}/webhooks`,
489539
{
@@ -496,6 +546,8 @@ export const getWebhookByName = async (context: string, name: string) => {
496546
).data.find(
497547
(webhook) => webhook.name === name && webhook.context === context,
498548
);
549+
if (!detail || !basic) return basic;
550+
return getWebhookById(basic.id);
499551
};
500552

501553
export const deleteWebhook = async (webhookId: string) => {

src/commands/sync.ts

Lines changed: 66 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import {
1111
getCacheDeploymentsRevision,
1212
removeDeployableRecords,
1313
prepareDeployableDirectory,
14+
getDeployableFileRevision,
15+
getRandomString,
1416
} from '../deployables';
1517
import {
1618
createOrUpdateClientFunction,
@@ -19,14 +21,18 @@ import {
1921
deleteClientFunction,
2022
deleteServerFunction,
2123
deleteWebhook,
24+
getClientFunctionById,
2225
getClientFunctionByName,
26+
getServerFunctionById,
2327
getServerFunctionByName,
28+
getWebhookById,
2429
getWebhookByName,
2530
} from '../api';
31+
import { FunctionDetailsDto, WebhookHandleDto } from '../types';
2632

2733
const DEPLOY_ORDER: DeployableTypes[] = [
28-
'server-function',
2934
'client-function',
35+
'server-function',
3036
'webhook',
3137
];
3238

@@ -105,6 +111,32 @@ const syncDeployableAndGetId = async (deployable, code) => {
105111
throw new Error(`Unsupported deployable type: '${deployable.type}'`);
106112
};
107113

114+
const getDeployableFromServer = async <T = FunctionDetailsDto | WebhookHandleDto>(
115+
deployable: SyncDeployment,
116+
): Promise<T | null | undefined> => {
117+
try {
118+
switch(deployable.type) {
119+
case 'server-function': {
120+
return deployable.id
121+
? getServerFunctionById(deployable.id) as T
122+
: getServerFunctionByName(deployable.context, deployable.name, true) as T;
123+
}
124+
case 'client-function': {
125+
return deployable.id
126+
? getClientFunctionById(deployable.id) as T
127+
: getClientFunctionByName(deployable.context, deployable.name, true) as T;
128+
}
129+
case 'webhook': {
130+
return deployable.id
131+
? getWebhookById(deployable.id) as T
132+
: getWebhookByName(deployable.context, deployable.name, true) as T;
133+
}
134+
}
135+
} catch (err) {
136+
return null;
137+
}
138+
}
139+
108140
const syncDeployable = async (
109141
deployable: SyncDeployment,
110142
): Promise<Deployment> => {
@@ -149,33 +181,51 @@ export const syncDeployables = async (
149181
const previousDeployment = deployable.deployments.find(
150182
(i) => i.instance === instance,
151183
);
184+
// Any deployable may be deployed to multiple instances/environments at the same time
185+
// So we reduce the deployable record down to a single instance we want to deploy to
186+
const syncDeployment: SyncDeployment = {
187+
...deployable,
188+
...previousDeployment, // flatten to grab name & context
189+
type: deployable.type, // but make sure we use the latest type
190+
description: deployable.description ?? deployable.types?.description,
191+
instance,
192+
};
193+
const deployed = await getDeployableFromServer(syncDeployment);
152194
const gitRevisionChanged = gitRevision !== deployable.gitRevision;
153-
const fileRevisionChanged =
154-
previousDeployment?.fileRevision !== deployable.fileRevision;
195+
const serverFileRevision = !deployed
196+
? ''
197+
: type === 'webhook'
198+
// TODO: Actually calculate real revision on webhook
199+
? getRandomString(8)
200+
: ((deployed as FunctionDetailsDto).hash || getDeployableFileRevision((deployed as FunctionDetailsDto).code));
201+
const fileRevisionChanged = serverFileRevision !== deployable.fileRevision;
202+
// TODO: If deployed variabnt exists AND was deployed after timestamp on previousDeployment then sync it back to the repo
155203
let action = gitRevisionChanged
156204
? 'REMOVED'
157-
: !previousDeployment?.id
205+
: !previousDeployment?.id && !deployed
158206
? 'ADDED'
159207
: fileRevisionChanged
160208
? 'UPDATED'
161-
: 'OK';
209+
: 'SKIPPED';
162210

163-
if (!dryRun && (gitRevisionChanged || fileRevisionChanged)) {
211+
if (!dryRun && action !== 'SKIPPED') {
164212
// if user is changing type, ex. server -> client function or vice versa
165213
// then try to cleanup the old type first
166214
if (previousDeployment && deployable.type !== previousDeployment.type) {
167215
await removeDeployable(previousDeployment);
168216
}
169-
// Any deployable may be deployed to multiple instances/environments at the same time
170-
// So we reduce the deployable record down to a single instance we want to deploy to
171-
const syncDeployment: SyncDeployment = {
172-
...deployable,
173-
...previousDeployment, // flatten to grab name & context
174-
type: deployable.type, // but make sure we use the latest type
175-
description: deployable.description ?? deployable.types?.description,
176-
instance,
177-
};
178-
if (gitRevision === deployable.gitRevision) {
217+
if (gitRevisionChanged) {
218+
// This deployable no longer exists so let's remove it
219+
const found = await removeDeployable(syncDeployment);
220+
if (!found) action = 'NOT FOUND';
221+
const removeIndex = allDeployables.findIndex(
222+
(d) =>
223+
d.name === deployable.name &&
224+
d.context === deployable.context &&
225+
d.file === deployable.file,
226+
);
227+
toRemove.push(...allDeployables.splice(removeIndex, 1));
228+
} else {
179229
const deployment = await syncDeployable(syncDeployment);
180230
if (previousDeployment) {
181231
previousDeployment.id = deployment.id;
@@ -187,17 +237,6 @@ export const syncDeployables = async (
187237
} else {
188238
deployable.deployments.unshift(deployment);
189239
}
190-
} else {
191-
// This deployable no longer exists so let's remove it
192-
const found = await removeDeployable(syncDeployment);
193-
if (!found) action = 'NOT FOUND';
194-
const removeIndex = allDeployables.findIndex(
195-
(d) =>
196-
d.name === deployable.name &&
197-
d.context === deployable.context &&
198-
d.file === deployable.file,
199-
);
200-
toRemove.push(...allDeployables.splice(removeIndex, 1));
201240
}
202241
}
203242

src/deployables.ts

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,6 @@ const writeJsonFile = async <T = any>(
150150
path: string,
151151
contents: T,
152152
): Promise<unknown> => {
153-
await open(path, 'w');
154153
return writeFile(path, JSON.stringify(contents, undefined, 2), {
155154
encoding: 'utf8',
156155
flag: 'w',
@@ -268,8 +267,14 @@ export const getDeployableFileRevision = (fileContents: string): string =>
268267
fileContents.replace(/^(\/\/.*\n)+/, ''),
269268
)
270269
.digest('hex')
271-
// Trimming to 7 characters to align with git revision format and to keep this nice and short!
272-
.substring(0, 7);
270+
// Trimming to 8 characters to align with git revision format and to keep this nice and short!
271+
.substring(0, 8);
272+
273+
export const getRandomString = (length = 8) => {
274+
return Array.from({ length }, () =>
275+
Math.floor(Math.random() * 16).toString(16),
276+
).join('');
277+
}
273278

274279
export const getGitRevision = (branchOrTag = 'HEAD'): string => {
275280
try {
@@ -281,9 +286,7 @@ export const getGitRevision = (branchOrTag = 'HEAD'): string => {
281286
return result;
282287
} catch (err) {
283288
console.warn('Failed to get git revision. Falling back to random hash.');
284-
return Array.from({ length: 8 }, () =>
285-
Math.floor(Math.random() * 16).toString(16),
286-
).join('');
289+
return getRandomString(8);
287290
}
288291
};
289292

src/types/functions.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,15 @@ export interface FunctionDetailsDto extends FunctionBasicDto {
5959
* If there are some missing poly schemas in `returnTypeSchema`, they will be listed here.
6060
*/
6161
unresolvedReturnTypePolySchemaRefs?: SchemaRef[];
62+
code: string;
63+
language: string;
64+
logsEnabled?: boolean;
65+
serverSideAsync?: boolean;
66+
minScale?: number | null;
67+
maxScale?: number | null;
68+
requirements?: string | null;
69+
generateContexts?: string[] | null;
70+
hash: string;
6271
}
6372

6473
export interface EntrySource {

0 commit comments

Comments
 (0)