Skip to content

Commit f029919

Browse files
Merge pull request #844 from appwrite/feat-functions-deployment-status
feat(cli): Updating function deployment status
2 parents 836e79c + 23523be commit f029919

File tree

2 files changed

+90
-28
lines changed

2 files changed

+90
-28
lines changed

templates/cli/lib/commands/push.js.twig

Lines changed: 84 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
const inquirer = require("inquirer");
22
const JSONbig = require("json-bigint")({ storeAsString: false });
33
const { Command } = require("commander");
4-
const { localConfig } = require("../config");
4+
const { localConfig, globalConfig } = require("../config");
55
const { Spinner, SPINNER_ARC, SPINNER_DOTS } = require('../spinner');
66
const { paginate } = require('../paginate');
77
const { questionsPushBuckets, questionsPushTeams, questionsPushFunctions, questionsGetEntrypoint, questionsPushCollections, questionsConfirmPushCollections } = require("../questions");
88
const { actionRunner, success, log, error, commandDescriptions } = require("../parser");
9-
const { functionsGet, functionsCreate, functionsUpdate, functionsCreateDeployment, functionsUpdateDeployment, functionsListVariables, functionsDeleteVariable, functionsCreateVariable } = require('./functions');
9+
const { functionsGet, functionsCreate, functionsUpdate, functionsCreateDeployment, functionsUpdateDeployment, functionsGetDeployment, functionsListVariables, functionsDeleteVariable, functionsCreateVariable } = require('./functions');
1010
const {
1111
databasesGet,
1212
databasesCreate,
@@ -40,13 +40,14 @@ const {
4040
} = require("./teams");
4141

4242
const STEP_SIZE = 100; // Resources
43-
const POOL_DEBOUNCE = 2000; // Milliseconds
43+
const POLL_DEBOUNCE = 2000; // Milliseconds
44+
const POLL_MAX_DEBOUNCE = 30; // Times
4445

45-
let poolMaxDebounces = 30;
46+
let pollMaxDebounces = 30;
4647

4748
const awaitPools = {
4849
wipeAttributes: async (databaseId, collectionId, iteration = 1) => {
49-
if (iteration > poolMaxDebounces) {
50+
if (iteration > pollMaxDebounces) {
5051
return false;
5152
}
5253

@@ -63,12 +64,12 @@ const awaitPools = {
6364

6465
let steps = Math.max(1, Math.ceil(total / STEP_SIZE));
6566
if (steps > 1 && iteration === 1) {
66-
poolMaxDebounces *= steps;
67+
pollMaxDebounces *= steps;
6768

68-
log('Found a large number of attributes, increasing timeout to ' + (poolMaxDebounces * POOL_DEBOUNCE / 1000 / 60) + ' minutes')
69+
log('Found a large number of attributes, increasing timeout to ' + (pollMaxDebounces * POLL_DEBOUNCE / 1000 / 60) + ' minutes')
6970
}
7071

71-
await new Promise(resolve => setTimeout(resolve, POOL_DEBOUNCE));
72+
await new Promise(resolve => setTimeout(resolve, POLL_DEBOUNCE));
7273

7374
return await awaitPools.wipeAttributes(
7475
databaseId,
@@ -77,7 +78,7 @@ const awaitPools = {
7778
);
7879
},
7980
wipeIndexes: async (databaseId, collectionId, iteration = 1) => {
80-
if (iteration > poolMaxDebounces) {
81+
if (iteration > pollMaxDebounces) {
8182
return false;
8283
}
8384

@@ -94,12 +95,12 @@ const awaitPools = {
9495

9596
let steps = Math.max(1, Math.ceil(total / STEP_SIZE));
9697
if (steps > 1 && iteration === 1) {
97-
poolMaxDebounces *= steps;
98+
pollMaxDebounces *= steps;
9899

99-
log('Found a large number of indexes, increasing timeout to ' + (poolMaxDebounces * POOL_DEBOUNCE / 1000 / 60) + ' minutes')
100+
log('Found a large number of indexes, increasing timeout to ' + (pollMaxDebounces * POLL_DEBOUNCE / 1000 / 60) + ' minutes')
100101
}
101102

102-
await new Promise(resolve => setTimeout(resolve, POOL_DEBOUNCE));
103+
await new Promise(resolve => setTimeout(resolve, POLL_DEBOUNCE));
103104

104105
return await awaitPools.wipeIndexes(
105106
databaseId,
@@ -108,7 +109,7 @@ const awaitPools = {
108109
);
109110
},
110111
wipeVariables: async (functionId, iteration = 1) => {
111-
if (iteration > poolMaxDebounces) {
112+
if (iteration > pollMaxDebounces) {
112113
return false;
113114
}
114115

@@ -124,28 +125,28 @@ const awaitPools = {
124125

125126
let steps = Math.max(1, Math.ceil(total / STEP_SIZE));
126127
if (steps > 1 && iteration === 1) {
127-
poolMaxDebounces *= steps;
128+
pollMaxDebounces *= steps;
128129

129-
log('Found a large number of variables, increasing timeout to ' + (poolMaxDebounces * POOL_DEBOUNCE / 1000 / 60) + ' minutes')
130+
log('Found a large number of variables, increasing timeout to ' + (pollMaxDebounces * POLL_DEBOUNCE / 1000 / 60) + ' minutes')
130131
}
131132

132-
await new Promise(resolve => setTimeout(resolve, POOL_DEBOUNCE));
133+
await new Promise(resolve => setTimeout(resolve, POLL_DEBOUNCE));
133134

134135
return await awaitPools.wipeVariables(
135136
functionId,
136137
iteration + 1
137138
);
138139
},
139140
expectAttributes: async (databaseId, collectionId, attributeKeys, iteration = 1) => {
140-
if (iteration > poolMaxDebounces) {
141+
if (iteration > pollMaxDebounces) {
141142
return false;
142143
}
143144

144145
let steps = Math.max(1, Math.ceil(attributeKeys.length / STEP_SIZE));
145146
if (steps > 1 && iteration === 1) {
146-
poolMaxDebounces *= steps;
147+
pollMaxDebounces *= steps;
147148

148-
log('Creating a large number of attributes, increasing timeout to ' + (poolMaxDebounces * POOL_DEBOUNCE / 1000 / 60) + ' minutes')
149+
log('Creating a large number of attributes, increasing timeout to ' + (pollMaxDebounces * POLL_DEBOUNCE / 1000 / 60) + ' minutes')
149150
}
150151

151152
const { attributes } = await paginate(databasesListAttributes, {
@@ -172,7 +173,7 @@ const awaitPools = {
172173
return true;
173174
}
174175

175-
await new Promise(resolve => setTimeout(resolve, POOL_DEBOUNCE));
176+
await new Promise(resolve => setTimeout(resolve, POLL_DEBOUNCE));
176177

177178
return await awaitPools.expectAttributes(
178179
databaseId,
@@ -182,15 +183,15 @@ const awaitPools = {
182183
);
183184
},
184185
expectIndexes: async (databaseId, collectionId, indexKeys, iteration = 1) => {
185-
if (iteration > poolMaxDebounces) {
186+
if (iteration > pollMaxDebounces) {
186187
return false;
187188
}
188189

189190
let steps = Math.max(1, Math.ceil(indexKeys.length / STEP_SIZE));
190191
if (steps > 1 && iteration === 1) {
191-
poolMaxDebounces *= steps;
192+
pollMaxDebounces *= steps;
192193

193-
log('Creating a large number of indexes, increasing timeout to ' + (poolMaxDebounces * POOL_DEBOUNCE / 1000 / 60) + ' minutes')
194+
log('Creating a large number of indexes, increasing timeout to ' + (pollMaxDebounces * POLL_DEBOUNCE / 1000 / 60) + ' minutes')
194195
}
195196

196197
const { indexes } = await paginate(databasesListIndexes, {
@@ -217,7 +218,7 @@ const awaitPools = {
217218
return true;
218219
}
219220

220-
await new Promise(resolve => setTimeout(resolve, POOL_DEBOUNCE));
221+
await new Promise(resolve => setTimeout(resolve, POLL_DEBOUNCE));
221222

222223
return await awaitPools.expectIndexes(
223224
databaseId,
@@ -237,7 +238,7 @@ const push = new Command("push")
237238
command.help()
238239
}));
239240

240-
const pushFunction = async ({ functionId, all, yes } = {}) => {
241+
const pushFunction = async ({ functionId, all, yes, async } = {}) => {
241242
let response = {};
242243

243244
const functionIds = [];
@@ -312,10 +313,13 @@ const pushFunction = async ({ functionId, all, yes } = {}) => {
312313

313314
Spinner.start(false);
314315
let successfullyPushed = 0;
316+
let successfullyDeployed = 0;
317+
const failedDeployments = [];
315318

316319
await Promise.all(functions.map(async (func) => {
317320
const ignore = func.ignore ? 'appwrite.json' : '.gitignore';
318321
let functionExists = false;
322+
let deploymentCreated = false;
319323

320324
const updaterRow = new Spinner({ status: '', resource: func.name, id: func['$id'], end: `Ignoring using: ${ignore}` });
321325

@@ -437,9 +441,9 @@ const pushFunction = async ({ functionId, all, yes } = {}) => {
437441
parseOutput: false
438442
})
439443

440-
updaterRow.update({ status: 'Pushed' })
444+
updaterRow.update({ status: 'Pushed' });
445+
deploymentCreated = true;
441446
successfullyPushed++;
442-
443447
} catch (e) {
444448
switch (e.code) {
445449
case 'ENOENT':
@@ -449,12 +453,63 @@ const pushFunction = async ({ functionId, all, yes } = {}) => {
449453
updaterRow.fail({ errorMessage: e.message ?? 'General error occurs please try again' })
450454
}
451455
}
456+
457+
if (deploymentCreated && !async) {
458+
try {
459+
const deploymentId = response['$id'];
460+
updaterRow.update({ status: 'Deploying', end: 'Checking deployment status...' })
461+
let pollChecks = 0;
462+
463+
while (true) {
464+
if (pollChecks >= POLL_MAX_DEBOUNCE) {
465+
updaterRow.update({ end: 'Deployment is taking too long. Please check the console for more details.' })
466+
break;
467+
}
468+
469+
response = await functionsGetDeployment({
470+
functionId: func['$id'],
471+
deploymentId: deploymentId,
472+
parseOutput: false
473+
});
474+
475+
476+
const status = response['status'];
477+
if (status === 'ready') {
478+
updaterRow.update({ status: 'Deployed' });
479+
successfullyDeployed++;
480+
481+
break;
482+
} else if (status === 'failed') {
483+
failedDeployments.push({ name: func['name'], $id: func['$id'], deployment: response['$id'] });
484+
updaterRow.fail({ errorMessage: `Failed to deploy` });
485+
486+
break;
487+
} else {
488+
updaterRow.update({ status: 'Deploying', end: `Current status: ${status}` })
489+
}
490+
491+
pollChecks++;
492+
await new Promise(resolve => setTimeout(resolve, POLL_DEBOUNCE));
493+
}
494+
} catch (e) {
495+
updaterRow.fail({ errorMessage: e.message ?? 'Unknown error occurred. Please try again' })
496+
}
497+
}
498+
452499
updaterRow.stopSpinner();
453500
}));
454501

455502
Spinner.stop();
503+
console.log('\n');
504+
505+
failedDeployments.forEach((failed) => {
506+
const { name, deployment, $id } = failed;
507+
const failUrl = `${globalConfig.getEndpoint().replace('/v1', '')}/console/project-${localConfig.getProject().projectId}/functions/function-${$id}/deployment-${deployment}`;
508+
509+
error(`Deployment of ${name} has failed. Check at ${failUrl} for more details\n`);
510+
})
456511

457-
success(`Pushed ${successfullyPushed} functions`);
512+
success(`Pushed ${successfullyPushed} functions with ${successfullyDeployed} successful deployments.`);
458513
}
459514

460515
const createAttribute = async (databaseId, collectionId, attribute) => {
@@ -958,6 +1013,7 @@ push
9581013
.option(`--functionId <functionId>`, `Function ID`)
9591014
.option(`--all`, `Flag to push all functions`)
9601015
.option(`--yes`, `Flag to confirm all warnings`)
1016+
.option(`--async`, `Don't wait for functions deployments status`)
9611017
.action(actionRunner(pushFunction));
9621018

9631019
push

templates/cli/lib/spinner.js.twig

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,12 @@ class Spinner {
3939
let end = chalk.yellow(payload.end);
4040

4141
if (status.toLowerCase().trim() === 'pushed') {
42+
start = chalk.greenBright.bold(status);
43+
prefix = chalk.greenBright.bold('✓');
44+
end = '';
45+
} else if (status.toLowerCase().trim() === 'deploying') {
46+
start = chalk.cyanBright.bold(status);
47+
} else if (status.toLowerCase().trim() === 'deployed') {
4248
start = chalk.green.bold(status);
4349
prefix = chalk.green.bold('✓');
4450
end = '';

0 commit comments

Comments
 (0)