Files
pwcli/src/commands/deployment/testservers/update/update.ts
T
Arwid ThornströmandGitHub 258e0b2dde 3296: now starts the codepipeline after stack update through pwcli (#17)
* now starts the codepipeline after stack update through pwcli

* cleanup
2023-02-03 09:11:20 +01:00

189 lines
6.0 KiB
TypeScript

import { GluegunMenuToolbox } from '@lenne.tech/gluegun-menu'
const chalk = require('chalk');
const { AutoComplete, Input, Confirm } = require('enquirer');
import { Octokit } from "@octokit/core";
import { exit } from 'process';
import { defaultMenuSettings, getCurrentBranch, getSettings, sleep } from '../../../../globals';
type Stack = {
name: string
status: string
drift_status: string
branch: string
updated: string
}
const getBranchName = async (toolbox: GluegunMenuToolbox, token: string, repoPath: string) => {
const {print} = toolbox;
const currentBranch = await getCurrentBranch(repoPath, toolbox);
const input = new Input({
type: 'input',
name: 'branch',
message: 'What github branch should be deployed?',
initial: currentBranch,
});
const responseBranch = await input.run();
// First ask what branch should be deployed
const octokit = new Octokit({ auth: token });
try {
const response = await octokit.request("GET /repos/{owner}/{repo}/branches/{branch}", {
owner: "photowall",
repo: "photowall",
branch: responseBranch
});
if (response.status === 200) {
return responseBranch;
}
} catch (e) {
print.error('Not a valid branch on photowall repo');
return null;
}
};
const getConfirmation = async (branchName: string, stackName: string) => {
const confirm = new Confirm({
name: 'confirm',
message: `The branch ${chalk.green(branchName)} will deploy to ${chalk.yellow(stackName)}`
});
try {
return confirm.run();
} catch (e) {
console.error(e);
return false;
}
}
module.exports = {
name: 'update',
alias: ['u'],
description: 'Update stack with different branch (u)',
hidden: false,
run: async (toolbox: GluegunMenuToolbox) => {
const { system, strings, print } = toolbox;
// Load settings
const config = await getSettings(toolbox);
if (!config || (!config.photowall_repo || config.photowall_repo === "")) {
print.error(`
The create command requires that you set an absolute path to your local photowall repository.
`);
await toolbox.menu.showMenu('setup', defaultMenuSettings);
return;
}
let branchName = null;
while (!branchName) {
branchName = await getBranchName(toolbox, config.gh_token, config.photowall_repo);
}
const stacks = JSON.parse(
strings.trim(await system.run(`aws cloudformation list-stacks`))
)
const teststacks: Stack[] = await Promise.all(
stacks.StackSummaries.map(async item => {
if (
item.StackName.indexOf('photowall-test-') > -1 &&
[
'CREATE_COMPLETE',
'UPDATE_COMPLETE',
'UPDATE_IN_PROGRESS',
'UPDATE_FAILED',
'CREATE_FAILED',
'CREATE_IN_PROGRESS'
].includes(item.StackStatus)
) {
const pipeline = JSON.parse(
strings.trim(
await system.run(
`aws codepipeline get-pipeline --name ${item.StackName}Pipeline`
)
)
)
const branch = pipeline.pipeline.stages.filter(stage => {
return stage.name === 'Source'
})[0].actions[0].configuration.Branch
const lastUpdated = pipeline.metadata.updated
return {
name: item.StackName,
status: item.StackStatus,
drift_status: item.DriftInformation.StackDriftStatus,
branch: branch,
updated: lastUpdated
}
}
return Promise.resolve(null)
})
)
const curratedStacks: Stack[] = teststacks.filter(Boolean)
const options = curratedStacks.map(item => {
return item.name;
});
const prompt = new AutoComplete({
name: 'testserver',
message: 'Choose a server',
limit: options.length - 1,
initial: options.length - 1,
choices: options
});
try {
const stackName = await prompt.run();
const stacksuffix = stackName.replace('photowall-', '');
const shouldRun = await getConfirmation(branchName, stackName);
if (shouldRun) {
const cmd = `make update-stack STACK_ENVIRONMENT_NAME=${stacksuffix} GITHUB_BRANCH=${branchName}`;
print.fancy(`Running [${chalk.yellow(cmd)}] in folder [${`${config.photowall_repo}/cloudformation/`}]`);
const output = await system.run(cmd, {cwd: `${config.photowall_repo}/cloudformation/`, trim: true});
print.fancy(output);
// Check the status
const spinner = print.spin(`Waiting for stack to update`);
let currentStackStatus = "";
while (currentStackStatus !== "UPDATE_COMPLETE") {
const stackCmd = `aws cloudformation describe-stacks --stack-name photowall-${stacksuffix}`;
const response = await system.run(stackCmd, {trim: true});
const stackData = JSON.parse(response);
currentStackStatus = stackData.Stacks[0].StackStatus;
switch (currentStackStatus) {
case "UPDATE_IN_PROGRESS":
spinner.text = `[${chalk.red(currentStackStatus)}]: Updating the stack`;
case "UPDATE_COMPLETE_CLEANUP_IN_PROGRESS":
spinner.text = `[${chalk.yellow(currentStackStatus)}]: Almost done, cleanup in progress`;
case "UPDATE_COMPLETE":
spinner.text = `[${chalk.green(currentStackStatus)}]: Update complete`;
break;
}
if (currentStackStatus !== 'UPDATE_COMPLETE') {
await sleep(1000);
}
}
spinner.text = `Will start the pipeline now [${chalk.yellow(`photowall-${stacksuffix}Pipeline`)}]`;
const runPipelineCmd = `aws codepipeline start-pipeline-execution --name photowall-${stacksuffix}Pipeline`;
await system.run(runPipelineCmd);
await sleep(2000);
spinner.stop();
print.fancy('Pipeline started, bye! 🚀');
}
} catch (e) {
console.log(`e`, e)
}
if (toolbox.fromMenu()) {
await toolbox.menu.showMenu('deployment testservers', defaultMenuSettings)
} else {
exit();
}
}
}