first commit
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
.DS_Store
|
||||
node_modules
|
||||
@@ -0,0 +1,16 @@
|
||||
const { system, filesystem } = require('gluegun')
|
||||
|
||||
const src = filesystem.path(__dirname, '..')
|
||||
|
||||
const cli = async cmd =>
|
||||
system.run('node ' + filesystem.path(src, 'bin', 'pwcli') + ` ${cmd}`)
|
||||
|
||||
test('outputs version', async () => {
|
||||
const output = await cli('--version')
|
||||
expect(output).toContain('0.0.1')
|
||||
})
|
||||
|
||||
test('outputs help', async () => {
|
||||
const output = await cli('--help')
|
||||
expect(output).toContain('0.0.1')
|
||||
})
|
||||
@@ -0,0 +1,21 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
|
||||
/* tslint:disable */
|
||||
// check if we're running in dev mode
|
||||
var devMode = require('fs').existsSync(`${__dirname}/../src`)
|
||||
// or want to "force" running the compiled version with --compiled-build
|
||||
var wantsCompiled = process.argv.indexOf('--compiled-build') >= 0
|
||||
|
||||
if (wantsCompiled || !devMode) {
|
||||
// this runs from the compiled javascript source
|
||||
require(`${__dirname}/../build/cli`).run(process.argv)
|
||||
} else {
|
||||
// this runs from the typescript source (for dev only)
|
||||
// hook into ts-node so we can run typescript on the fly
|
||||
require('ts-node').register({ project: `${__dirname}/../tsconfig.json` })
|
||||
// run the CLI with the current process arguments
|
||||
require(`${__dirname}/../src/cli`).run(process.argv)
|
||||
}
|
||||
|
||||
|
||||
+172
@@ -0,0 +1,172 @@
|
||||
var __awaiter =
|
||||
(this && this.__awaiter) ||
|
||||
function(thisArg, _arguments, P, generator) {
|
||||
function adopt(value) {
|
||||
return value instanceof P
|
||||
? value
|
||||
: new P(function(resolve) {
|
||||
resolve(value)
|
||||
})
|
||||
}
|
||||
return new (P || (P = Promise))(function(resolve, reject) {
|
||||
function fulfilled(value) {
|
||||
try {
|
||||
step(generator.next(value))
|
||||
} catch (e) {
|
||||
reject(e)
|
||||
}
|
||||
}
|
||||
function rejected(value) {
|
||||
try {
|
||||
step(generator['throw'](value))
|
||||
} catch (e) {
|
||||
reject(e)
|
||||
}
|
||||
}
|
||||
function step(result) {
|
||||
result.done
|
||||
? resolve(result.value)
|
||||
: adopt(result.value).then(fulfilled, rejected)
|
||||
}
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next())
|
||||
})
|
||||
}
|
||||
var __generator =
|
||||
(this && this.__generator) ||
|
||||
function(thisArg, body) {
|
||||
var _ = {
|
||||
label: 0,
|
||||
sent: function() {
|
||||
if (t[0] & 1) throw t[1]
|
||||
return t[1]
|
||||
},
|
||||
trys: [],
|
||||
ops: []
|
||||
},
|
||||
f,
|
||||
y,
|
||||
t,
|
||||
g
|
||||
return (
|
||||
(g = { next: verb(0), throw: verb(1), return: verb(2) }),
|
||||
typeof Symbol === 'function' &&
|
||||
(g[Symbol.iterator] = function() {
|
||||
return this
|
||||
}),
|
||||
g
|
||||
)
|
||||
function verb(n) {
|
||||
return function(v) {
|
||||
return step([n, v])
|
||||
}
|
||||
}
|
||||
function step(op) {
|
||||
if (f) throw new TypeError('Generator is already executing.')
|
||||
while (_)
|
||||
try {
|
||||
if (
|
||||
((f = 1),
|
||||
y &&
|
||||
(t =
|
||||
op[0] & 2
|
||||
? y['return']
|
||||
: op[0]
|
||||
? y['throw'] || ((t = y['return']) && t.call(y), 0)
|
||||
: y.next) &&
|
||||
!(t = t.call(y, op[1])).done)
|
||||
)
|
||||
return t
|
||||
if (((y = 0), t)) op = [op[0] & 2, t.value]
|
||||
switch (op[0]) {
|
||||
case 0:
|
||||
case 1:
|
||||
t = op
|
||||
break
|
||||
case 4:
|
||||
_.label++
|
||||
return { value: op[1], done: false }
|
||||
case 5:
|
||||
_.label++
|
||||
y = op[1]
|
||||
op = [0]
|
||||
continue
|
||||
case 7:
|
||||
op = _.ops.pop()
|
||||
_.trys.pop()
|
||||
continue
|
||||
default:
|
||||
if (
|
||||
!((t = _.trys), (t = t.length > 0 && t[t.length - 1])) &&
|
||||
(op[0] === 6 || op[0] === 2)
|
||||
) {
|
||||
_ = 0
|
||||
continue
|
||||
}
|
||||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) {
|
||||
_.label = op[1]
|
||||
break
|
||||
}
|
||||
if (op[0] === 6 && _.label < t[1]) {
|
||||
_.label = t[1]
|
||||
t = op
|
||||
break
|
||||
}
|
||||
if (t && _.label < t[2]) {
|
||||
_.label = t[2]
|
||||
_.ops.push(op)
|
||||
break
|
||||
}
|
||||
if (t[2]) _.ops.pop()
|
||||
_.trys.pop()
|
||||
continue
|
||||
}
|
||||
op = body.call(thisArg, _)
|
||||
} catch (e) {
|
||||
op = [6, e]
|
||||
y = 0
|
||||
} finally {
|
||||
f = t = 0
|
||||
}
|
||||
if (op[0] & 5) throw op[1]
|
||||
return { value: op[0] ? op[1] : void 0, done: true }
|
||||
}
|
||||
}
|
||||
var build = require('gluegun').build
|
||||
/**
|
||||
* Create the cli and kick it off
|
||||
*/
|
||||
function run(argv) {
|
||||
return __awaiter(this, void 0, void 0, function() {
|
||||
var cli, toolbox
|
||||
return __generator(this, function(_a) {
|
||||
switch (_a.label) {
|
||||
case 0:
|
||||
cli = build()
|
||||
.brand('pwcli')
|
||||
.src(__dirname)
|
||||
.plugins('./node_modules', { matching: 'pwcli-*', hidden: true })
|
||||
.plugin(
|
||||
__dirname + '/../node_modules/@lenne.tech/gluegun-menu/dist',
|
||||
{
|
||||
commandFilePattern: '*.js',
|
||||
extensionFilePattern: '*.js'
|
||||
}
|
||||
)
|
||||
.help() // provides default for help, h, --help, -h
|
||||
.version() // provides default for version, v, --version, -v
|
||||
.create()
|
||||
return [
|
||||
4 /*yield*/,
|
||||
cli.run(argv)
|
||||
// send it back (for testing, mostly)
|
||||
]
|
||||
case 1:
|
||||
toolbox = _a.sent()
|
||||
// send it back (for testing, mostly)
|
||||
return [2 /*return*/, toolbox]
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
module.exports = { run: run }
|
||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xpLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2NsaS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBUSxJQUFBLEtBQUssR0FBSyxPQUFPLENBQUMsU0FBUyxDQUFDLE1BQXZCLENBQXVCO0FBRXBDOztHQUVHO0FBQ0gsU0FBZSxHQUFHLENBQUMsSUFBSTs7Ozs7O29CQUVmLEdBQUcsR0FBRyxLQUFLLEVBQUU7eUJBQ2hCLEtBQUssQ0FBQyxPQUFPLENBQUM7eUJBQ2QsR0FBRyxDQUFDLFNBQVMsQ0FBQzt5QkFDZCxPQUFPLENBQUMsZ0JBQWdCLEVBQUUsRUFBRSxRQUFRLEVBQUUsU0FBUyxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsQ0FBQzt5QkFDaEUsTUFBTSxDQUFDLFNBQVMsR0FBRyxnREFBZ0QsRUFBRTt3QkFDcEUsa0JBQWtCLEVBQUUsTUFBTTt3QkFDMUIsb0JBQW9CLEVBQUUsTUFBTTtxQkFDN0IsQ0FBQzt5QkFDRCxJQUFJLEVBQUUsQ0FBQywyQ0FBMkM7eUJBQ2xELE9BQU8sRUFBRSxDQUFDLGlEQUFpRDt5QkFDM0QsTUFBTSxFQUFFLENBQUE7b0JBS0sscUJBQU0sR0FBRyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUM7d0JBRW5DLHFDQUFxQztzQkFGRjs7b0JBQTdCLE9BQU8sR0FBRyxTQUFtQjtvQkFFbkMscUNBQXFDO29CQUNyQyxzQkFBTyxPQUFPLEVBQUE7Ozs7Q0FDZjtBQUVELE1BQU0sQ0FBQyxPQUFPLEdBQUcsRUFBRSxHQUFHLEtBQUEsRUFBRSxDQUFBIn0=
|
||||
@@ -0,0 +1,55 @@
|
||||
"use strict";
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
var __generator = (this && this.__generator) || function (thisArg, body) {
|
||||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
||||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
||||
function verb(n) { return function (v) { return step([n, v]); }; }
|
||||
function step(op) {
|
||||
if (f) throw new TypeError("Generator is already executing.");
|
||||
while (_) try {
|
||||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
||||
if (y = 0, t) op = [op[0] & 2, t.value];
|
||||
switch (op[0]) {
|
||||
case 0: case 1: t = op; break;
|
||||
case 4: _.label++; return { value: op[1], done: false };
|
||||
case 5: _.label++; y = op[1]; op = [0]; continue;
|
||||
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
||||
default:
|
||||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
||||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
||||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
||||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
||||
if (t[2]) _.ops.pop();
|
||||
_.trys.pop(); continue;
|
||||
}
|
||||
op = body.call(thisArg, _);
|
||||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
||||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
||||
}
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
module.exports = {
|
||||
name: 'deployment',
|
||||
alias: ['d'],
|
||||
description: 'Description for deployment',
|
||||
hidden: true,
|
||||
run: function (toolbox) { return __awaiter(void 0, void 0, void 0, function () {
|
||||
return __generator(this, function (_a) {
|
||||
switch (_a.label) {
|
||||
case 0: return [4 /*yield*/, toolbox.menu.showMenu('deployment')];
|
||||
case 1:
|
||||
_a.sent();
|
||||
return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
}); }
|
||||
};
|
||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVwbG95bWVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9jb21tYW5kcy9kZXBsb3ltZW50L2RlcGxveW1lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFFQSxNQUFNLENBQUMsT0FBTyxHQUFHO0lBQ2YsSUFBSSxFQUFFLFlBQVk7SUFDbEIsS0FBSyxFQUFFLENBQUMsR0FBRyxDQUFDO0lBQ1osV0FBVyxFQUFFLDRCQUE0QjtJQUN6QyxNQUFNLEVBQUUsSUFBSTtJQUNaLEdBQUcsRUFBRSxVQUFPLE9BQTJCOzs7d0JBQ3JDLHFCQUFNLE9BQU8sQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLFlBQVksQ0FBQyxFQUFBOztvQkFBekMsU0FBeUMsQ0FBQzs7OztTQUMzQztDQUNGLENBQUMifQ==
|
||||
@@ -0,0 +1,155 @@
|
||||
"use strict";
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
var __generator = (this && this.__generator) || function (thisArg, body) {
|
||||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
||||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
||||
function verb(n) { return function (v) { return step([n, v]); }; }
|
||||
function step(op) {
|
||||
if (f) throw new TypeError("Generator is already executing.");
|
||||
while (_) try {
|
||||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
||||
if (y = 0, t) op = [op[0] & 2, t.value];
|
||||
switch (op[0]) {
|
||||
case 0: case 1: t = op; break;
|
||||
case 4: _.label++; return { value: op[1], done: false };
|
||||
case 5: _.label++; y = op[1]; op = [0]; continue;
|
||||
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
||||
default:
|
||||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
||||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
||||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
||||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
||||
if (t[2]) _.ops.pop();
|
||||
_.trys.pop(); continue;
|
||||
}
|
||||
op = body.call(thisArg, _);
|
||||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
||||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
||||
}
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var cliSelect = require('cli-select');
|
||||
var chalk = require('chalk');
|
||||
var AutoComplete = require('enquirer').AutoComplete;
|
||||
var STACK_DEFAULTS = {
|
||||
STACK_ENVIRONMENT_NAME_TAG: 'test',
|
||||
CPU_SIZE: 512,
|
||||
MEMORY_SIZE: '1GB',
|
||||
HOSTED_ZONE_WITHOUT_TLD: 'photowall-test',
|
||||
PRIMARY_CERTIFICATE_ARN: 'arn:aws:acm:eu-west-1:954747537408:certificate/12e33b74-da14-430d-a7ed-f62fa7113112',
|
||||
STATIC_CDN_CERTIFICATE_ARN: 'arn:aws:acm:us-east-1:954747537408:certificate/223550cf-e404-4ff1-85bb-703b936c9347',
|
||||
DB_SECURITY_GROUP_ID: 'sg-001b3667edf19e1ce',
|
||||
STATIC_CDN_HOSTNAME: 'staging.assets.photowall-test.com',
|
||||
MAX_CONTAINERS: 1,
|
||||
MIN_CONTAINERS: 1,
|
||||
AWS_KEY_ENVIRONMENT: 'staging'
|
||||
};
|
||||
var createCloudFormationCommand = function (environmentName, branch) {
|
||||
return "aws cloudformation update-stack --stack-name " + environmentName + " --template-body file://ecs-service.yaml \n\t\t--capabilities CAPABILITY_NAMED_IAM\n --tags Key=EnvironmentName,Value=test \n\t\t--parameters \n ParameterKey=\"EnvironmentName\",UsePreviousValue=true \n ParameterKey=\"Image\",UsePreviousValue=true \n ParameterKey=\"HostedZoneNameWithOutTLD\",UsePreviousValue=true \n ParameterKey=\"DomainNameWithoutTld\",UsePreviousValue=true \n ParameterKey=\"PrimaryCertificateArn\",UsePreviousValue=true \n ParameterKey=\"GitHubRepo\",UsePreviousValue=true \n ParameterKey=\"GitHubUser\",UsePreviousValue=true \n ParameterKey=\"GitHubBranch\",ParameterValue=\"" + branch + "\" \n ParameterKey=\"GitHubToken\",UsePreviousValue=true \n ParameterKey=\"ComposerAuth\",UsePreviousValue=true \n ParameterKey=\"CpuSize\",ParameterValue=\"" + STACK_DEFAULTS.CPU_SIZE + "\" \n ParameterKey=\"MemorySize\",ParameterValue=\"" + STACK_DEFAULTS.MEMORY_SIZE + "\" \n ParameterKey=\"MinContainers\",ParameterValue=\"" + STACK_DEFAULTS.MIN_CONTAINERS + "\" \n ParameterKey=\"MaxContainers\",ParameterValue=\"" + STACK_DEFAULTS.MAX_CONTAINERS + "\" \n ParameterKey=\"StaticCdnHostName\",ParameterValue=\"" + STACK_DEFAULTS.STATIC_CDN_HOSTNAME + "\" \n ParameterKey=\"StaticCdnCertificateArn\",ParameterValue=\"" + STACK_DEFAULTS.STATIC_CDN_CERTIFICATE_ARN + "\" \n ParameterKey=\"AwsAccessKeyParamNameEnvironment\",ParameterValue=\"" + STACK_DEFAULTS.AWS_KEY_ENVIRONMENT + "\" \n ParameterKey=\"DatabaseSecurityGroup\",ParameterValue=\"" + STACK_DEFAULTS.DB_SECURITY_GROUP_ID + "\"";
|
||||
};
|
||||
/**
|
||||
* Subsection1 menu
|
||||
*/
|
||||
module.exports = {
|
||||
name: 'deploy',
|
||||
alias: ['d'],
|
||||
description: 'Deploy current branch to a testserver',
|
||||
hidden: true,
|
||||
run: function (toolbox) { return __awaiter(void 0, void 0, void 0, function () {
|
||||
var system, strings, stacks, _a, _b, _c, _d, teststacks, curratedStacks, options, prompt, choice, branch, _e, _f, cmd, e_1;
|
||||
return __generator(this, function (_g) {
|
||||
switch (_g.label) {
|
||||
case 0:
|
||||
system = toolbox.system, strings = toolbox.strings;
|
||||
_b = (_a = JSON).parse;
|
||||
_d = (_c = strings).trim;
|
||||
return [4 /*yield*/, system.run("aws cloudformation list-stacks")];
|
||||
case 1:
|
||||
stacks = _b.apply(_a, [_d.apply(_c, [_g.sent()])]);
|
||||
return [4 /*yield*/, Promise.all(stacks.StackSummaries.map(function (item) { return __awaiter(void 0, void 0, void 0, function () {
|
||||
var pipeline, _a, _b, _c, _d, branch, lastUpdated;
|
||||
return __generator(this, function (_e) {
|
||||
switch (_e.label) {
|
||||
case 0:
|
||||
if (!(item.StackName.indexOf('photowall-test-') > -1 &&
|
||||
[
|
||||
'CREATE_COMPLETE',
|
||||
'UPDATE_COMPLETE',
|
||||
'UPDATE_IN_PROGRESS',
|
||||
'UPDATE_FAILED',
|
||||
'CREATE_FAILED',
|
||||
'CREATE_IN_PROGRESS'
|
||||
].includes(item.StackStatus))) return [3 /*break*/, 2];
|
||||
_b = (_a = JSON).parse;
|
||||
_d = (_c = strings).trim;
|
||||
return [4 /*yield*/, system.run("aws codepipeline get-pipeline --name " + item.StackName + "Pipeline")];
|
||||
case 1:
|
||||
pipeline = _b.apply(_a, [_d.apply(_c, [_e.sent()])]);
|
||||
branch = pipeline.pipeline.stages.filter(function (stage) {
|
||||
return stage.name === 'Source';
|
||||
})[0].actions[0].configuration.Branch;
|
||||
lastUpdated = pipeline.metadata.updated;
|
||||
return [2 /*return*/, {
|
||||
name: item.StackName,
|
||||
status: item.StackStatus,
|
||||
drift_status: item.DriftInformation.StackDriftStatus,
|
||||
branch: branch,
|
||||
updated: lastUpdated
|
||||
}];
|
||||
case 2: return [2 /*return*/, Promise.resolve(null)];
|
||||
}
|
||||
});
|
||||
}); }))];
|
||||
case 2:
|
||||
teststacks = _g.sent();
|
||||
curratedStacks = teststacks.filter(Boolean);
|
||||
options = curratedStacks.map(function (item) {
|
||||
return item.name;
|
||||
});
|
||||
console.log("options", options);
|
||||
prompt = new AutoComplete({
|
||||
name: 'testserver',
|
||||
message: 'Choose a server',
|
||||
limit: options.length - 1,
|
||||
initial: options.length - 1,
|
||||
choices: options
|
||||
});
|
||||
_g.label = 3;
|
||||
case 3:
|
||||
_g.trys.push([3, 6, , 7]);
|
||||
return [4 /*yield*/, prompt.run()];
|
||||
case 4:
|
||||
choice = _g.sent();
|
||||
console.log("choice", choice);
|
||||
_f = (_e = strings).trim;
|
||||
return [4 /*yield*/, system.run("git branch --show-current")];
|
||||
case 5:
|
||||
branch = _f.apply(_e, [_g.sent()]);
|
||||
console.log("branch", branch);
|
||||
cmd = createCloudFormationCommand(choice, branch);
|
||||
console.log("cmd", cmd);
|
||||
return [3 /*break*/, 7];
|
||||
case 6:
|
||||
e_1 = _g.sent();
|
||||
console.log("e", e_1);
|
||||
return [3 /*break*/, 7];
|
||||
case 7:
|
||||
if (!toolbox.fromMenu()) return [3 /*break*/, 9];
|
||||
return [4 /*yield*/, toolbox.menu.showMenu('deployment testservers')];
|
||||
case 8:
|
||||
_g.sent();
|
||||
_g.label = 9;
|
||||
case 9: return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
}); }
|
||||
};
|
||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVwbG95LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL2NvbW1hbmRzL2RlcGxveW1lbnQvdGVzdHNlcnZlcnMvZGVwbG95L2RlcGxveS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUVBLElBQU0sU0FBUyxHQUFHLE9BQU8sQ0FBQyxZQUFZLENBQUMsQ0FBQTtBQUN2QyxJQUFNLEtBQUssR0FBRyxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUE7QUFDdEIsSUFBQSxZQUFZLEdBQUssT0FBTyxDQUFDLFVBQVUsQ0FBQyxhQUF4QixDQUF3QjtBQUU1QyxJQUFNLGNBQWMsR0FBRztJQUNyQiwwQkFBMEIsRUFBRSxNQUFNO0lBQ2xDLFFBQVEsRUFBRSxHQUFHO0lBQ2IsV0FBVyxFQUFFLEtBQUs7SUFDbEIsdUJBQXVCLEVBQUUsZ0JBQWdCO0lBQ3pDLHVCQUF1QixFQUNyQixxRkFBcUY7SUFDdkYsMEJBQTBCLEVBQ3hCLHFGQUFxRjtJQUN2RixvQkFBb0IsRUFBRSxzQkFBc0I7SUFDNUMsbUJBQW1CLEVBQUUsbUNBQW1DO0lBQ3hELGNBQWMsRUFBRSxDQUFDO0lBQ2pCLGNBQWMsRUFBRSxDQUFDO0lBQ2pCLG1CQUFtQixFQUFFLFNBQVM7Q0FDL0IsQ0FBQTtBQVVELElBQU0sMkJBQTJCLEdBQUcsVUFBQyxlQUFlLEVBQUUsTUFBTTtJQUMxRCxPQUFPLGtEQUFnRCxlQUFlLHluQkFXdEIsTUFBTSw4S0FHWCxjQUFjLENBQUMsUUFBUSw4REFDcEIsY0FBYyxDQUFDLFdBQVcsaUVBQ3ZCLGNBQWMsQ0FBQyxjQUFjLGlFQUM3QixjQUFjLENBQUMsY0FBYyxxRUFDekIsY0FBYyxDQUFDLG1CQUFtQiwyRUFDNUIsY0FBYyxDQUFDLDBCQUEwQixvRkFDaEMsY0FBYyxDQUFDLG1CQUFtQix5RUFDN0MsY0FBYyxDQUFDLG9CQUFvQixPQUFHLENBQUE7QUFDakcs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
|
||||
@@ -0,0 +1,120 @@
|
||||
"use strict";
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
var __generator = (this && this.__generator) || function (thisArg, body) {
|
||||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
||||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
||||
function verb(n) { return function (v) { return step([n, v]); }; }
|
||||
function step(op) {
|
||||
if (f) throw new TypeError("Generator is already executing.");
|
||||
while (_) try {
|
||||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
||||
if (y = 0, t) op = [op[0] & 2, t.value];
|
||||
switch (op[0]) {
|
||||
case 0: case 1: t = op; break;
|
||||
case 4: _.label++; return { value: op[1], done: false };
|
||||
case 5: _.label++; y = op[1]; op = [0]; continue;
|
||||
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
||||
default:
|
||||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
||||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
||||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
||||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
||||
if (t[2]) _.ops.pop();
|
||||
_.trys.pop(); continue;
|
||||
}
|
||||
op = body.call(thisArg, _);
|
||||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
||||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
||||
}
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var chalk = require('chalk');
|
||||
var tto = require('terminal-table-output').create();
|
||||
/**
|
||||
* Subsection1 menu
|
||||
*/
|
||||
module.exports = {
|
||||
name: 'status',
|
||||
alias: ['s'],
|
||||
description: 'Show status for available testservers',
|
||||
hidden: true,
|
||||
run: function (toolbox) { return __awaiter(void 0, void 0, void 0, function () {
|
||||
var system, strings, stacks, _a, _b, _c, _d, teststacks, curratedStacks, status, _i, curratedStacks_1, stack;
|
||||
return __generator(this, function (_e) {
|
||||
switch (_e.label) {
|
||||
case 0:
|
||||
system = toolbox.system, strings = toolbox.strings;
|
||||
_b = (_a = JSON).parse;
|
||||
_d = (_c = strings).trim;
|
||||
return [4 /*yield*/, system.run("aws cloudformation list-stacks")];
|
||||
case 1:
|
||||
stacks = _b.apply(_a, [_d.apply(_c, [_e.sent()])]);
|
||||
return [4 /*yield*/, Promise.all(stacks.StackSummaries.map(function (item) { return __awaiter(void 0, void 0, void 0, function () {
|
||||
var pipeline, _a, _b, _c, _d, branch, lastUpdated;
|
||||
return __generator(this, function (_e) {
|
||||
switch (_e.label) {
|
||||
case 0:
|
||||
if (!(item.StackName.indexOf('photowall-test-') > -1 && ['CREATE_COMPLETE', 'UPDATE_COMPLETE', 'UPDATE_IN_PROGRESS', 'UPDATE_FAILED', 'CREATE_FAILED', 'CREATE_IN_PROGRESS'].includes(item.StackStatus))) return [3 /*break*/, 2];
|
||||
_b = (_a = JSON).parse;
|
||||
_d = (_c = strings).trim;
|
||||
return [4 /*yield*/, system.run("aws codepipeline get-pipeline --name " + item.StackName + "Pipeline")];
|
||||
case 1:
|
||||
pipeline = _b.apply(_a, [_d.apply(_c, [_e.sent()])]);
|
||||
branch = pipeline.pipeline.stages.filter(function (stage) {
|
||||
return stage.name === 'Source';
|
||||
})[0].actions[0].configuration.Branch;
|
||||
lastUpdated = pipeline.metadata.updated;
|
||||
return [2 /*return*/, {
|
||||
name: item.StackName,
|
||||
status: item.StackStatus,
|
||||
drift_status: item.DriftInformation.StackDriftStatus,
|
||||
branch: branch,
|
||||
updated: lastUpdated,
|
||||
}];
|
||||
case 2: return [2 /*return*/, Promise.resolve(null)];
|
||||
}
|
||||
});
|
||||
}); }))];
|
||||
case 2:
|
||||
teststacks = _e.sent();
|
||||
curratedStacks = teststacks.filter(Boolean);
|
||||
status = function (status) {
|
||||
switch (status) {
|
||||
case 'UPDATE_FAILED':
|
||||
case 'CREATE_FAILED':
|
||||
return " (\uD83D\uDC94) ";
|
||||
case 'UPDATE_IN_PROGRESS':
|
||||
case 'CREATE_IN_PROGRESS':
|
||||
return " (\uD83D\uDFE1) ";
|
||||
case 'UPDATE_COMPLETE':
|
||||
case 'CREATE_COMPLETE':
|
||||
return " (\uD83D\uDFE2) ";
|
||||
}
|
||||
};
|
||||
tto.line('-');
|
||||
tto.pushrow(['| status', 'stack', 'branch', 'updated'])
|
||||
.line('-');
|
||||
for (_i = 0, curratedStacks_1 = curratedStacks; _i < curratedStacks_1.length; _i++) {
|
||||
stack = curratedStacks_1[_i];
|
||||
tto.pushrow([status(stack.status), stack.name, stack.branch, stack.updated]);
|
||||
}
|
||||
tto.print(true);
|
||||
if (!toolbox.fromMenu()) return [3 /*break*/, 4];
|
||||
return [4 /*yield*/, toolbox.menu.showMenu('deployment testservers')];
|
||||
case 3:
|
||||
_e.sent();
|
||||
_e.label = 4;
|
||||
case 4: return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
}); }
|
||||
};
|
||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RhdHVzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL2NvbW1hbmRzL2RlcGxveW1lbnQvdGVzdHNlcnZlcnMvc3RhdHVzL3N0YXR1cy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUVBLElBQU0sS0FBSyxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQztBQUMvQixJQUFNLEdBQUcsR0FBRyxPQUFPLENBQUMsdUJBQXVCLENBQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQztBQVV0RDs7R0FFRztBQUNILE1BQU0sQ0FBQyxPQUFPLEdBQUc7SUFDZixJQUFJLEVBQUUsUUFBUTtJQUNkLEtBQUssRUFBRSxDQUFDLEdBQUcsQ0FBQztJQUNaLFdBQVcsRUFBRSx1Q0FBdUM7SUFDcEQsTUFBTSxFQUFFLElBQUk7SUFDWixHQUFHLEVBQUUsVUFBTyxPQUEyQjs7Ozs7b0JBRTdCLE1BQU0sR0FBYyxPQUFPLE9BQXJCLEVBQUUsT0FBTyxHQUFLLE9BQU8sUUFBWixDQUFZO29CQUVwQixLQUFBLENBQUEsS0FBQSxJQUFJLENBQUEsQ0FBQyxLQUFLLENBQUE7b0JBQUMsS0FBQSxDQUFBLEtBQUEsT0FBTyxDQUFBLENBQUMsSUFBSSxDQUFBO29CQUFDLHFCQUFNLE1BQU0sQ0FBQyxHQUFHLENBQUMsZ0NBQWdDLENBQUMsRUFBQTs7b0JBQW5GLE1BQU0sR0FBRyxjQUFXLGNBQWEsU0FBa0QsRUFBQyxFQUFDO29CQUMvRCxxQkFBTSxPQUFPLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxjQUFjLENBQUMsR0FBRyxDQUFDLFVBQU8sSUFBSTs7Ozs7NkNBQzdFLENBQUEsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsaUJBQWlCLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDLGlCQUFpQixFQUFFLGlCQUFpQixFQUFFLG9CQUFvQixFQUFFLGVBQWUs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
|
||||
@@ -0,0 +1,58 @@
|
||||
"use strict";
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
var __generator = (this && this.__generator) || function (thisArg, body) {
|
||||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
||||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
||||
function verb(n) { return function (v) { return step([n, v]); }; }
|
||||
function step(op) {
|
||||
if (f) throw new TypeError("Generator is already executing.");
|
||||
while (_) try {
|
||||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
||||
if (y = 0, t) op = [op[0] & 2, t.value];
|
||||
switch (op[0]) {
|
||||
case 0: case 1: t = op; break;
|
||||
case 4: _.label++; return { value: op[1], done: false };
|
||||
case 5: _.label++; y = op[1]; op = [0]; continue;
|
||||
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
||||
default:
|
||||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
||||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
||||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
||||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
||||
if (t[2]) _.ops.pop();
|
||||
_.trys.pop(); continue;
|
||||
}
|
||||
op = body.call(thisArg, _);
|
||||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
||||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
||||
}
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
/**
|
||||
* Section1 menu
|
||||
*/
|
||||
module.exports = {
|
||||
name: 'testservers',
|
||||
alias: ['ts'],
|
||||
description: 'Deploy to testservers',
|
||||
hidden: true,
|
||||
run: function (toolbox) { return __awaiter(void 0, void 0, void 0, function () {
|
||||
return __generator(this, function (_a) {
|
||||
switch (_a.label) {
|
||||
case 0: return [4 /*yield*/, toolbox.menu.showMenu('deployment testservers')];
|
||||
case 1:
|
||||
_a.sent();
|
||||
return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
}); }
|
||||
};
|
||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVzdHNlcnZlcnMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvY29tbWFuZHMvZGVwbG95bWVudC90ZXN0c2VydmVycy90ZXN0c2VydmVycy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUVBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE9BQU8sR0FBRztJQUNmLElBQUksRUFBRSxhQUFhO0lBQ25CLEtBQUssRUFBRSxDQUFDLElBQUksQ0FBQztJQUNiLFdBQVcsRUFBRSx1QkFBdUI7SUFDcEMsTUFBTSxFQUFFLElBQUk7SUFDWixHQUFHLEVBQUUsVUFBTyxPQUEyQjs7O3dCQUNyQyxxQkFBTSxPQUFPLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyx3QkFBd0IsQ0FBQyxFQUFBOztvQkFBckQsU0FBcUQsQ0FBQzs7OztTQUN2RDtDQUNGLENBQUMifQ==
|
||||
@@ -0,0 +1,58 @@
|
||||
"use strict";
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
var __generator = (this && this.__generator) || function (thisArg, body) {
|
||||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
||||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
||||
function verb(n) { return function (v) { return step([n, v]); }; }
|
||||
function step(op) {
|
||||
if (f) throw new TypeError("Generator is already executing.");
|
||||
while (_) try {
|
||||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
||||
if (y = 0, t) op = [op[0] & 2, t.value];
|
||||
switch (op[0]) {
|
||||
case 0: case 1: t = op; break;
|
||||
case 4: _.label++; return { value: op[1], done: false };
|
||||
case 5: _.label++; y = op[1]; op = [0]; continue;
|
||||
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
||||
default:
|
||||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
||||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
||||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
||||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
||||
if (t[2]) _.ops.pop();
|
||||
_.trys.pop(); continue;
|
||||
}
|
||||
op = body.call(thisArg, _);
|
||||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
||||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
||||
}
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
/**
|
||||
* interactive menu
|
||||
*/
|
||||
module.exports = {
|
||||
name: 'interactive',
|
||||
alias: ['i'],
|
||||
description: 'Interactive tree view',
|
||||
hidden: true,
|
||||
run: function (toolbox) { return __awaiter(void 0, void 0, void 0, function () {
|
||||
return __generator(this, function (_a) {
|
||||
switch (_a.label) {
|
||||
case 0: return [4 /*yield*/, toolbox.menu.showMenu('deployment')];
|
||||
case 1:
|
||||
_a.sent();
|
||||
return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
}); }
|
||||
};
|
||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW50ZXJhY3RpdmUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY29tbWFuZHMvaW50ZXJhY3RpdmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFFQTs7R0FFRztBQUNILE1BQU0sQ0FBQyxPQUFPLEdBQUc7SUFDZixJQUFJLEVBQUUsYUFBYTtJQUNuQixLQUFLLEVBQUUsQ0FBQyxHQUFHLENBQUM7SUFDWixXQUFXLEVBQUUsdUJBQXVCO0lBQ3BDLE1BQU0sRUFBRSxJQUFJO0lBQ1osR0FBRyxFQUFFLFVBQU8sT0FBMkI7Ozt3QkFDckMscUJBQU0sT0FBTyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsWUFBWSxDQUFDLEVBQUE7O29CQUF6QyxTQUF5QyxDQUFDOzs7O1NBQzNDO0NBQ0YsQ0FBQyJ9
|
||||
@@ -0,0 +1,51 @@
|
||||
"use strict";
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
var __generator = (this && this.__generator) || function (thisArg, body) {
|
||||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
||||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
||||
function verb(n) { return function (v) { return step([n, v]); }; }
|
||||
function step(op) {
|
||||
if (f) throw new TypeError("Generator is already executing.");
|
||||
while (_) try {
|
||||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
||||
if (y = 0, t) op = [op[0] & 2, t.value];
|
||||
switch (op[0]) {
|
||||
case 0: case 1: t = op; break;
|
||||
case 4: _.label++; return { value: op[1], done: false };
|
||||
case 5: _.label++; y = op[1]; op = [0]; continue;
|
||||
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
||||
default:
|
||||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
||||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
||||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
||||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
||||
if (t[2]) _.ops.pop();
|
||||
_.trys.pop(); continue;
|
||||
}
|
||||
op = body.call(thisArg, _);
|
||||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
||||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
||||
}
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var command = {
|
||||
name: 'pwcli',
|
||||
run: function (toolbox) { return __awaiter(void 0, void 0, void 0, function () {
|
||||
var print;
|
||||
return __generator(this, function (_a) {
|
||||
print = toolbox.print;
|
||||
print.info('Welcome to your CLI');
|
||||
return [2 /*return*/];
|
||||
});
|
||||
}); },
|
||||
};
|
||||
module.exports = command;
|
||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHdjbGkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY29tbWFuZHMvcHdjbGkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFJQSxJQUFNLE9BQU8sR0FBbUI7SUFDOUIsSUFBSSxFQUFFLE9BQU87SUFDYixHQUFHLEVBQUUsVUFBTSxPQUFPOzs7WUFDUixLQUFLLEdBQUssT0FBTyxNQUFaLENBQVk7WUFFekIsS0FBSyxDQUFDLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxDQUFBOzs7U0FDbEM7Q0FDRixDQUFBO0FBRUQsTUFBTSxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUEifQ==
|
||||
@@ -0,0 +1,17 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
// add your CLI-specific functionality here, which will then be accessible
|
||||
// to your commands
|
||||
module.exports = function (toolbox) {
|
||||
toolbox.foo = function () {
|
||||
toolbox.print.info('called foo extension');
|
||||
};
|
||||
// enable this if you want to read configuration in from
|
||||
// the current folder's package.json (in a "pwcli" property),
|
||||
// pwcli.config.json, etc.
|
||||
// toolbox.config = {
|
||||
// ...toolbox.config,
|
||||
// ...toolbox.config.loadConfig("pwcli", process.cwd())
|
||||
// }
|
||||
};
|
||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xpLWV4dGVuc2lvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9leHRlbnNpb25zL2NsaS1leHRlbnNpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFJQSwwRUFBMEU7QUFDMUUsbUJBQW1CO0FBQ25CLE1BQU0sQ0FBQyxPQUFPLEdBQUcsVUFBQyxPQUF1QjtJQUN2QyxPQUFPLENBQUMsR0FBRyxHQUFHO1FBQ1osT0FBTyxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsc0JBQXNCLENBQUMsQ0FBQTtJQUM1QyxDQUFDLENBQUE7SUFFRCx3REFBd0Q7SUFDeEQsNkRBQTZEO0lBQzdELDBCQUEwQjtJQUMxQixxQkFBcUI7SUFDckIsdUJBQXVCO0lBQ3ZCLHlEQUF5RDtJQUN6RCxJQUFJO0FBQ04sQ0FBQyxDQUFBIn0=
|
||||
@@ -0,0 +1,2 @@
|
||||
// export types
|
||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvdHlwZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsZUFBZSJ9
|
||||
Vendored
+5
@@ -0,0 +1,5 @@
|
||||
declare const build: any;
|
||||
/**
|
||||
* Create the cli and kick it off
|
||||
*/
|
||||
declare function run(argv: any): Promise<any>;
|
||||
@@ -0,0 +1 @@
|
||||
export {};
|
||||
@@ -0,0 +1 @@
|
||||
export {};
|
||||
@@ -0,0 +1 @@
|
||||
export {};
|
||||
@@ -0,0 +1 @@
|
||||
export {};
|
||||
+1
@@ -0,0 +1 @@
|
||||
export {};
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
export {};
|
||||
+1
@@ -0,0 +1 @@
|
||||
export {};
|
||||
Vendored
@@ -0,0 +1,3 @@
|
||||
# Command Reference for pwcli
|
||||
|
||||
TODO: Add your command reference here
|
||||
@@ -0,0 +1,47 @@
|
||||
# Plugin guide for pwcli
|
||||
|
||||
Plugins allow you to add features to pwcli, such as commands and
|
||||
extensions to the `toolbox` object that provides the majority of the functionality
|
||||
used by pwcli.
|
||||
|
||||
Creating a pwcli plugin is easy. Just create a repo with two folders:
|
||||
|
||||
```
|
||||
commands/
|
||||
extensions/
|
||||
```
|
||||
|
||||
A command is a file that looks something like this:
|
||||
|
||||
```js
|
||||
// commands/foo.js
|
||||
|
||||
module.exports = {
|
||||
run: (toolbox) => {
|
||||
const { print, filesystem } = toolbox
|
||||
|
||||
const desktopDirectories = filesystem.subdirectories(`~/Desktop`)
|
||||
print.info(desktopDirectories)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
An extension lets you add additional features to the `toolbox`.
|
||||
|
||||
```js
|
||||
// extensions/bar-extension.js
|
||||
|
||||
module.exports = (toolbox) => {
|
||||
const { print } = toolbox
|
||||
|
||||
toolbox.bar = () => { print.info('Bar!') }
|
||||
}
|
||||
```
|
||||
|
||||
This is then accessible in your plugin's commands as `toolbox.bar`.
|
||||
|
||||
# Loading a plugin
|
||||
|
||||
To load a particular plugin (which has to start with `pwcli-*`),
|
||||
install it to your project using `npm install --save-dev pwcli-PLUGINNAME`,
|
||||
and pwcli will pick it up automatically.
|
||||
@@ -0,0 +1,62 @@
|
||||
{
|
||||
"name": "pwcli",
|
||||
"version": "0.0.1",
|
||||
"description": "pwcli CLI",
|
||||
"private": true,
|
||||
"types": "build/types/types.d.ts",
|
||||
"bin": {
|
||||
"pwcli": "bin/pwcli"
|
||||
},
|
||||
"scripts": {
|
||||
"format": "prettier --write **/*.{js,ts,tsx,json}",
|
||||
"lint": "tslint -p .",
|
||||
"clean-build": "rm -rf ./build",
|
||||
"compile": "tsc -p .",
|
||||
"copy-templates": "if [ -e ./src/templates ]; then cp -a ./src/templates ./build/; fi",
|
||||
"build": "yarn format && yarn lint && yarn clean-build && yarn compile && yarn copy-templates",
|
||||
"prepublishOnly": "yarn build",
|
||||
"test": "jest",
|
||||
"watch": "jest --watch",
|
||||
"snapupdate": "jest --updateSnapshot",
|
||||
"coverage": "jest --coverage"
|
||||
},
|
||||
"files": [
|
||||
"tsconfig.json",
|
||||
"tslint.json",
|
||||
"build",
|
||||
"LICENSE",
|
||||
"readme.md",
|
||||
"docs",
|
||||
"bin"
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@lenne.tech/gluegun-menu": "^0.0.5",
|
||||
"@octokit/core": "^3.5.1",
|
||||
"chalk": "^4.1.2",
|
||||
"cli-select": "^1.1.2",
|
||||
"enquirer": "^2.3.6",
|
||||
"gluegun": "latest",
|
||||
"terminal-table-output": "^1.3.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "^24.0.18",
|
||||
"@types/node": "^12.7.11",
|
||||
"jest": "^24.1.0",
|
||||
"prettier": "^1.12.1",
|
||||
"ts-jest": "^24.1.0",
|
||||
"ts-node": "^8.4.1",
|
||||
"tslint": "^5.12.0",
|
||||
"tslint-config-prettier": "^1.17.0",
|
||||
"tslint-config-standard": "^8.0.1",
|
||||
"typescript": "^3.6.3"
|
||||
},
|
||||
"jest": {
|
||||
"preset": "ts-jest",
|
||||
"testEnvironment": "node"
|
||||
},
|
||||
"prettier": {
|
||||
"semi": false,
|
||||
"singleQuote": true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
# pwcli CLI
|
||||
|
||||
A CLI for pwcli.
|
||||
|
||||
## Customizing your CLI
|
||||
|
||||
Check out the documentation at https://github.com/infinitered/gluegun/tree/master/docs.
|
||||
|
||||
## Publishing to NPM
|
||||
|
||||
To package your CLI up for NPM, do this:
|
||||
|
||||
```shell
|
||||
$ npm login
|
||||
$ npm whoami
|
||||
$ npm lint
|
||||
$ npm test
|
||||
(if typescript, run `npm run build` here)
|
||||
$ npm publish
|
||||
```
|
||||
|
||||
# License
|
||||
|
||||
MIT - see LICENSE
|
||||
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
const { build } = require('gluegun');
|
||||
|
||||
/**
|
||||
* Create the cli and kick it off
|
||||
*/
|
||||
async function run(argv) {
|
||||
// create a CLI runtime
|
||||
const cli = build()
|
||||
.brand('pwcli')
|
||||
.src(__dirname)
|
||||
.plugins('./node_modules', { matching: 'pwcli-*', hidden: true })
|
||||
.plugin(__dirname + '/../node_modules/@lenne.tech/gluegun-menu/dist', {
|
||||
commandFilePattern: '*.js',
|
||||
extensionFilePattern: '*.js'
|
||||
})
|
||||
.help({
|
||||
name: 'help',
|
||||
alias: 'helpmeplease',
|
||||
hidden: true,
|
||||
dashed: true,
|
||||
run: toolbox => toolbox.print.info('No help for you!')
|
||||
}) // provides default for help, h, --help, -h
|
||||
.version() // provides default for version, v, --version, -v
|
||||
.create();
|
||||
// enable the following method if you'd like to skip loading one of these core extensions
|
||||
// this can improve performance if they're not necessary for your project:
|
||||
// .exclude(['meta', 'strings', 'print', 'filesystem', 'semver', 'system', 'prompt', 'http', 'template', 'patching', 'package-manager'])
|
||||
// and run it
|
||||
const toolbox = await cli.run(argv);
|
||||
|
||||
// send it back (for testing, mostly)
|
||||
return toolbox;
|
||||
}
|
||||
|
||||
module.exports = { run }
|
||||
@@ -0,0 +1,11 @@
|
||||
import { GluegunMenuToolbox } from '@lenne.tech/gluegun-menu';
|
||||
|
||||
module.exports = {
|
||||
name: 'deployment',
|
||||
alias: ['d'],
|
||||
description: 'Description for deployment (d)',
|
||||
hidden: true,
|
||||
run: async (toolbox: GluegunMenuToolbox) => {
|
||||
await toolbox.menu.showMenu('deployment');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,251 @@
|
||||
import { GluegunMenuToolbox } from '@lenne.tech/gluegun-menu'
|
||||
const chalk = require('chalk');
|
||||
const { AutoComplete, Input, Confirm } = require('enquirer');
|
||||
import { Octokit } from "@octokit/core";
|
||||
import { GluegunPrint } from 'gluegun';
|
||||
const os = require("os");
|
||||
|
||||
const STACK_DEFAULTS = {
|
||||
STACK_ENVIRONMENT_NAME_TAG: 'test',
|
||||
CPU_SIZE: 512,
|
||||
MEMORY_SIZE: '1GB',
|
||||
HOSTED_ZONE_WITHOUT_TLD: 'photowall-test',
|
||||
DOMAIN_NAME_WITHOUT_TLD: '.photowall-test',
|
||||
PRIMARY_CERTIFICATE_ARN:
|
||||
'arn:aws:acm:eu-west-1:954747537408:certificate/12e33b74-da14-430d-a7ed-f62fa7113112',
|
||||
STATIC_CDN_CERTIFICATE_ARN:
|
||||
'arn:aws:acm:us-east-1:954747537408:certificate/223550cf-e404-4ff1-85bb-703b936c9347',
|
||||
DB_SECURITY_GROUP_ID: 'sg-001b3667edf19e1ce',
|
||||
GITHUB_REPO: 'photowall',
|
||||
GITHUB_USER: 'Photowall',
|
||||
STATIC_CDN_HOSTNAME: `''`,
|
||||
MAX_CONTAINERS: 1,
|
||||
MIN_CONTAINERS: 1,
|
||||
AWS_KEY_ENVIRONMENT: 'staging'
|
||||
}
|
||||
|
||||
type Stack = {
|
||||
name: string
|
||||
status: string
|
||||
drift_status: string
|
||||
branch: string
|
||||
updated: string
|
||||
}
|
||||
|
||||
const getDownloadFileFromRepoCommand = (token: string, org: string, repo: string, path: string) => {
|
||||
const file = path.split('/').pop();
|
||||
return `curl -o /tmp/${file} -H 'Authorization: token ${token} ' -H 'Accept: application/vnd.github.v3.raw' -O -L https://api.github.com/repos/${org}/${repo}/contents/${path}`;
|
||||
}
|
||||
|
||||
const getCreateStackCommand = (stackName: string, branch: string, templateFile: string, dockerImage: string, githubToken: string, composerAuth: string) => {
|
||||
const stack = 'photowall';
|
||||
const stackDomain = stackName.replace('photowall-', '');
|
||||
const cmd = [
|
||||
`aws cloudformation create-stack --stack-name ${stackName}`,
|
||||
`--template-body ${templateFile}`,
|
||||
`--capabilities CAPABILITY_NAMED_IAM`,
|
||||
`--tags Key=EnvironmentName,Value=test`,
|
||||
`--parameters`,
|
||||
`ParameterKey=EnvironmentName,ParameterValue=${stackDomain}`,
|
||||
`ParameterKey=Image,ParameterValue=${dockerImage}`,
|
||||
`ParameterKey=HostedZoneNameWithOutTLD,ParameterValue=${STACK_DEFAULTS.HOSTED_ZONE_WITHOUT_TLD}`,
|
||||
`ParameterKey=DomainNameWithoutTld,ParameterValue=${stackDomain}${STACK_DEFAULTS.DOMAIN_NAME_WITHOUT_TLD}`,
|
||||
`ParameterKey=PrimaryCertificateArn,ParameterValue='${STACK_DEFAULTS.PRIMARY_CERTIFICATE_ARN}'`,
|
||||
`ParameterKey=GitHubRepo,ParameterValue=${STACK_DEFAULTS.GITHUB_REPO}`,
|
||||
`ParameterKey=GitHubUser,ParameterValue=${STACK_DEFAULTS.GITHUB_USER}`,
|
||||
`ParameterKey=GitHubBranch,ParameterValue=${branch}`,
|
||||
`ParameterKey=GitHubToken,ParameterValue=${githubToken}`,
|
||||
`ParameterKey=ComposerAuth,ParameterValue="${composerAuth}"`,
|
||||
`ParameterKey=CpuSize,ParameterValue=${STACK_DEFAULTS.CPU_SIZE}`,
|
||||
`ParameterKey=MemorySize,ParameterValue=${STACK_DEFAULTS.MEMORY_SIZE}`,
|
||||
`ParameterKey=MinContainers,ParameterValue=${STACK_DEFAULTS.MIN_CONTAINERS}`,
|
||||
`ParameterKey=MaxContainers,ParameterValue=${STACK_DEFAULTS.MAX_CONTAINERS}`,
|
||||
`ParameterKey=StaticCdnHostName,ParameterValue=${STACK_DEFAULTS.STATIC_CDN_HOSTNAME}`,
|
||||
`ParameterKey=StaticCdnCertificateArn,ParameterValue=${STACK_DEFAULTS.STATIC_CDN_CERTIFICATE_ARN}`,
|
||||
`ParameterKey=AwsAccessKeyParamNameEnvironment,ParameterValue=${STACK_DEFAULTS.AWS_KEY_ENVIRONMENT}`,
|
||||
`ParameterKey=DatabaseSecurityGroup,ParameterValue=${STACK_DEFAULTS.DB_SECURITY_GROUP_ID}`,
|
||||
];
|
||||
|
||||
return cmd.join(' ');
|
||||
};
|
||||
|
||||
const getBranchName = async (print: GluegunPrint, token: string) => {
|
||||
const input = new Input({
|
||||
type: 'input',
|
||||
name: 'branch',
|
||||
message: 'What github branch should be deployed?'
|
||||
});
|
||||
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 url = stackName.replace('photowall-', '');
|
||||
const confirm = new Confirm({
|
||||
name: 'confirm',
|
||||
message: `Will create ${chalk.yellow(url + '.photowall-test.xx')} and publish ${chalk.green(branchName)} to it, continue?`
|
||||
});
|
||||
|
||||
try {
|
||||
return confirm.run();
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Subsection1 menu
|
||||
*/
|
||||
module.exports = {
|
||||
name: 'create',
|
||||
alias: ['c'],
|
||||
description: 'Create new testserver on aws (c)',
|
||||
hidden: true,
|
||||
run: async (toolbox: GluegunMenuToolbox) => {
|
||||
const { system, strings, print, filesystem } = toolbox;
|
||||
|
||||
// Load settings
|
||||
const config = await filesystem.readAsync(`${os.homedir()}/.pwcli_settings`, "json");
|
||||
if (!config) {
|
||||
print.error(`
|
||||
|
||||
No config found, please run [ ${chalk.cyan('pwcli s')} ] or setup from the menu.
|
||||
|
||||
`);
|
||||
if (toolbox.fromMenu()) {
|
||||
await toolbox.menu.showMenu()
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
let branchName = null;
|
||||
while (!branchName) {
|
||||
branchName = await getBranchName(print, config.gh_token);
|
||||
}
|
||||
|
||||
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 input = new Input({
|
||||
type: 'input',
|
||||
name: 'stack',
|
||||
message: `Insert name of the new stack (${chalk.yellow('photowall-test-xx-x')})`
|
||||
});
|
||||
const stackName = await input.run();
|
||||
|
||||
if (options.includes(stackName)) {
|
||||
print.error(`
|
||||
|
||||
The stack ${chalk.yellow(stackName)} is already taken, try the update command instead.
|
||||
|
||||
`);
|
||||
if (toolbox.fromMenu()) {
|
||||
await toolbox.menu.showMenu('deployment testservers');
|
||||
}
|
||||
} else if (stackName.indexOf('photowall-test-') !== 0) {
|
||||
print.error(`
|
||||
|
||||
The stack must begin with ${chalk.yellow('photowall-test-')}.
|
||||
|
||||
`);
|
||||
if (toolbox.fromMenu()) {
|
||||
await toolbox.menu.showMenu('deployment testservers');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
|
||||
const shouldRun = await getConfirmation(branchName, stackName);
|
||||
|
||||
if (shouldRun) {
|
||||
// Download files to /tmp
|
||||
await system.run(getDownloadFileFromRepoCommand(config.gh_token, 'Photowall', 'photowall', 'cloudformation/ecr-lifecycle-policy.json'));
|
||||
await system.run(getDownloadFileFromRepoCommand(config.gh_token, 'Photowall', 'photowall', 'cloudformation/ecs-service.yaml'));
|
||||
|
||||
const aws_account_id = strings.trim(await system.run(`aws sts get-caller-identity --query Account --output text`));
|
||||
const aws_region = strings.trim(await system.run(`aws configure get region`));
|
||||
const github_token = strings.trim(await system.run(`aws ssm get-parameter --with-decryption --name /github/CODE_PIPELINE_TOKEN --output text --query Parameter.Value`));
|
||||
|
||||
print.fancy(await system.run(`aws ecr create-repository --repository ${stackName}`));
|
||||
print.fancy(await system.run(`aws ecr get-login-password --region ${aws_region} | docker login --username AWS --password-stdin ${aws_account_id}.dkr.ecr.${aws_region}.amazonaws.com`));
|
||||
print.fancy(await system.run(`docker pull nginx`));
|
||||
print.fancy(await system.run(`docker tag nginx ${aws_account_id}.dkr.ecr.${aws_region}.amazonaws.com/${stackName}:latest`));
|
||||
print.fancy(await system.run(`docker push ${aws_account_id}.dkr.ecr.${aws_region}.amazonaws.com/${stackName}:latest`));
|
||||
|
||||
const dockerImage = `${aws_account_id}.dkr.ecr.${aws_region}.amazonaws.com/${stackName}`;
|
||||
let composerAuthToken = await system.run(`aws ssm get-parameter --with-decryption --name /github/COMPOSER_TOKEN --output text --query Parameter.Value`);
|
||||
composerAuthToken = composerAuthToken.replace('\n', '');
|
||||
const composer_auth = `'{\"github-oauth\":{\"github.com\":\"${composerAuthToken}\"}}'`;
|
||||
|
||||
const createCommand = getCreateStackCommand(stackName, branchName, 'file://ecs-service.yaml', dockerImage, github_token, composer_auth);
|
||||
print.fancy(await system.run(createCommand, {cwd: '/tmp/', trim: true}));
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(`e`, e)
|
||||
}
|
||||
|
||||
if (toolbox.fromMenu()) {
|
||||
await toolbox.menu.showMenu('deployment testservers')
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
import { GluegunMenuToolbox } from '@lenne.tech/gluegun-menu'
|
||||
import { GluegunSystem, print } from 'gluegun';
|
||||
const chalk = require('chalk');
|
||||
const { AutoComplete, Input, Confirm } = require('enquirer');
|
||||
|
||||
type Stack = {
|
||||
name: string,
|
||||
status: string,
|
||||
drift_status: string,
|
||||
branch: string,
|
||||
updated: string,
|
||||
};
|
||||
|
||||
const getConfirmation = async (stackName: string) => {
|
||||
const confirm = new Confirm({
|
||||
name: 'confirm',
|
||||
message: `The stack ${chalk.yellow(stackName)} will be ${chalk.red.bold('deleted')}`
|
||||
});
|
||||
|
||||
try {
|
||||
return confirm.run();
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const confirmCommand = async (cmd: string) => {
|
||||
const confirm = new Confirm({
|
||||
name: 'confirm',
|
||||
message: `RUN COMMAND > [${chalk.yellow(cmd)}] ?`,
|
||||
});
|
||||
|
||||
try {
|
||||
const resp = await confirm.run();
|
||||
if (resp) {
|
||||
return cmd;
|
||||
}
|
||||
return null;
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
const runCommand = async (system: GluegunSystem, cmd : string | null) => {
|
||||
if (cmd) {
|
||||
return system.run(cmd);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Subsection1 menu
|
||||
*/
|
||||
module.exports = {
|
||||
name: 'delete',
|
||||
alias: ['d'],
|
||||
description: 'Choose a testserver to delete (d)',
|
||||
hidden: true,
|
||||
run: async (toolbox: GluegunMenuToolbox) => {
|
||||
|
||||
const { system, strings, print } = toolbox;
|
||||
|
||||
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
|
||||
});
|
||||
|
||||
const stackName = await prompt.run();
|
||||
|
||||
const shouldRun = await getConfirmation(stackName);
|
||||
|
||||
if (shouldRun) {
|
||||
await runCommand(system, await confirmCommand(`aws cloudformation delete-stack --stack-name ${stackName}`));
|
||||
await runCommand(system, await confirmCommand(`aws ecr delete-repository --force --repository-name ${stackName}`));
|
||||
await runCommand(system, await confirmCommand(`aws logs delete-log-group --log-group-name /aws/codebuild/${stackName}`));
|
||||
await runCommand(system, await confirmCommand(`aws logs delete-log-group --log-group-name ${stackName}`));
|
||||
const artifacts = strings.trim(
|
||||
await system.run(`aws s3 ls | grep ${stackName}-artifactbucket | awk '{print $3}'`)
|
||||
).split('\n');
|
||||
for (const artifact of artifacts) {
|
||||
await runCommand(system, await confirmCommand(`aws s3 rb --force s3://${artifact}`));
|
||||
}
|
||||
}
|
||||
|
||||
if (toolbox.fromMenu()) {
|
||||
await toolbox.menu.showMenu('deployment testservers');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
import { GluegunMenuToolbox } from '@lenne.tech/gluegun-menu'
|
||||
const tto = require('terminal-table-output').create();
|
||||
|
||||
type Stack = {
|
||||
name: string,
|
||||
status: string,
|
||||
drift_status: string,
|
||||
branch: string,
|
||||
updated: string,
|
||||
};
|
||||
|
||||
/**
|
||||
* Subsection1 menu
|
||||
*/
|
||||
module.exports = {
|
||||
name: 'status',
|
||||
alias: ['s'],
|
||||
description: 'Show status for available testservers (s)',
|
||||
hidden: true,
|
||||
run: async (toolbox: GluegunMenuToolbox) => {
|
||||
|
||||
const { system, strings } = toolbox
|
||||
|
||||
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 status = (status: string) => {
|
||||
switch(status) {
|
||||
case 'UPDATE_FAILED':
|
||||
case 'CREATE_FAILED':
|
||||
return ` (💔) `;
|
||||
case 'UPDATE_IN_PROGRESS':
|
||||
case 'CREATE_IN_PROGRESS':
|
||||
return ` (🟡) `;
|
||||
case 'UPDATE_COMPLETE':
|
||||
case 'CREATE_COMPLETE':
|
||||
return ` (🟢) `;
|
||||
}
|
||||
}
|
||||
|
||||
tto.line('-');
|
||||
tto.pushrow(['| status', 'stack', 'branch', 'updated'])
|
||||
.line('-');
|
||||
for (const stack of curratedStacks) {
|
||||
tto.pushrow([status(stack.status), stack.name, stack.branch, stack.updated]);
|
||||
}
|
||||
tto.print(true);
|
||||
|
||||
if (toolbox.fromMenu()) {
|
||||
await toolbox.menu.showMenu('deployment testservers');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import { GluegunMenuToolbox } from '@lenne.tech/gluegun-menu';
|
||||
|
||||
/**
|
||||
* Section1 menu
|
||||
*/
|
||||
module.exports = {
|
||||
name: 'testservers',
|
||||
alias: ['ts'],
|
||||
description: 'Deploy to testservers (ts)',
|
||||
hidden: true,
|
||||
run: async (toolbox: GluegunMenuToolbox) => {
|
||||
await toolbox.menu.showMenu('deployment testservers');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,221 @@
|
||||
import { GluegunMenuToolbox } from '@lenne.tech/gluegun-menu'
|
||||
const chalk = require('chalk');
|
||||
const { AutoComplete, Input, Confirm } = require('enquirer');
|
||||
import { Octokit } from "@octokit/core";
|
||||
import { GluegunPrint } from 'gluegun';
|
||||
const os = require("os");
|
||||
|
||||
const STACK_DEFAULTS = {
|
||||
STACK_ENVIRONMENT_NAME_TAG: 'test',
|
||||
CPU_SIZE: 512,
|
||||
MEMORY_SIZE: '1GB',
|
||||
HOSTED_ZONE_WITHOUT_TLD: 'photowall-test',
|
||||
PRIMARY_CERTIFICATE_ARN:
|
||||
'arn:aws:acm:eu-west-1:954747537408:certificate/12e33b74-da14-430d-a7ed-f62fa7113112',
|
||||
STATIC_CDN_CERTIFICATE_ARN:
|
||||
'arn:aws:acm:us-east-1:954747537408:certificate/223550cf-e404-4ff1-85bb-703b936c9347',
|
||||
DB_SECURITY_GROUP_ID: 'sg-001b3667edf19e1ce',
|
||||
STATIC_CDN_HOSTNAME: `''`,
|
||||
MAX_CONTAINERS: 1,
|
||||
MIN_CONTAINERS: 1,
|
||||
AWS_KEY_ENVIRONMENT: 'staging'
|
||||
}
|
||||
|
||||
type Stack = {
|
||||
name: string
|
||||
status: string
|
||||
drift_status: string
|
||||
branch: string
|
||||
updated: string
|
||||
}
|
||||
|
||||
const getDownloadFileFromRepoCommand = (token: string, org: string, repo: string, path: string) => {
|
||||
const file = path.split('/').pop();
|
||||
return `curl -o /tmp/${file} -H 'Authorization: token ${token} ' -H 'Accept: application/vnd.github.v3.raw' -O -L https://api.github.com/repos/${org}/${repo}/contents/${path}`;
|
||||
}
|
||||
|
||||
const getLifeCyclePolicyCommand = (stackName: string, policyFile: string) => {
|
||||
return `aws ecr put-lifecycle-policy --repository-name ${stackName} --lifecycle-policy-text "${policyFile}"`;
|
||||
}
|
||||
|
||||
const getUpdateStackCommand = (stackName: string, branch: string, templateFile: string) => {
|
||||
const cmd = [
|
||||
`aws cloudformation update-stack --stack-name ${stackName}`,
|
||||
`--template-body ${templateFile}`,
|
||||
`--capabilities CAPABILITY_NAMED_IAM`,
|
||||
`--tags Key=EnvironmentName,Value=test`,
|
||||
`--parameters`,
|
||||
`ParameterKey=EnvironmentName,UsePreviousValue=true`,
|
||||
`ParameterKey=Image,UsePreviousValue=true`,
|
||||
`ParameterKey=HostedZoneNameWithOutTLD,UsePreviousValue=true`,
|
||||
`ParameterKey=DomainNameWithoutTld,UsePreviousValue=true`,
|
||||
`ParameterKey=PrimaryCertificateArn,UsePreviousValue=true`,
|
||||
`ParameterKey=GitHubRepo,UsePreviousValue=true`,
|
||||
`ParameterKey=GitHubUser,UsePreviousValue=true`,
|
||||
`ParameterKey=GitHubBranch,ParameterValue=${branch}`,
|
||||
`ParameterKey=GitHubToken,UsePreviousValue=true`,
|
||||
`ParameterKey=ComposerAuth,UsePreviousValue=true`,
|
||||
`ParameterKey=CpuSize,ParameterValue=${STACK_DEFAULTS.CPU_SIZE}`,
|
||||
`ParameterKey=MemorySize,ParameterValue=${STACK_DEFAULTS.MEMORY_SIZE}`,
|
||||
`ParameterKey=MinContainers,ParameterValue=${STACK_DEFAULTS.MIN_CONTAINERS}`,
|
||||
`ParameterKey=MaxContainers,ParameterValue=${STACK_DEFAULTS.MAX_CONTAINERS}`,
|
||||
`ParameterKey=StaticCdnHostName,ParameterValue=${STACK_DEFAULTS.STATIC_CDN_HOSTNAME}`,
|
||||
`ParameterKey=StaticCdnCertificateArn,ParameterValue=${STACK_DEFAULTS.STATIC_CDN_CERTIFICATE_ARN}`,
|
||||
`ParameterKey=AwsAccessKeyParamNameEnvironment,ParameterValue=${STACK_DEFAULTS.AWS_KEY_ENVIRONMENT}`,
|
||||
`ParameterKey=DatabaseSecurityGroup,ParameterValue=${STACK_DEFAULTS.DB_SECURITY_GROUP_ID}`
|
||||
];
|
||||
return cmd.join(' ');
|
||||
}
|
||||
|
||||
const getBranchName = async (print: GluegunPrint, token: string) => {
|
||||
const input = new Input({
|
||||
type: 'input',
|
||||
name: 'branch',
|
||||
message: 'What github branch should be deployed?'
|
||||
});
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Subsection1 menu
|
||||
*/
|
||||
module.exports = {
|
||||
name: 'update',
|
||||
alias: ['u'],
|
||||
description: 'Update stack with different branch (u)',
|
||||
hidden: true,
|
||||
run: async (toolbox: GluegunMenuToolbox) => {
|
||||
const { system, strings, print, filesystem } = toolbox;
|
||||
|
||||
// Load settings
|
||||
const config = await filesystem.readAsync(`${os.homedir()}/.pwcli_settings`, "json");
|
||||
if (!config) {
|
||||
print.error(`
|
||||
|
||||
No config found, please run [ ${chalk.cyan('pwcli s')} ] or setup from the menu.
|
||||
|
||||
`);
|
||||
if (toolbox.fromMenu()) {
|
||||
await toolbox.menu.showMenu()
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
let branchName = null;
|
||||
while (!branchName) {
|
||||
branchName = await getBranchName(print, config.gh_token);
|
||||
}
|
||||
|
||||
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 {
|
||||
|
||||
// Download files to /tmp
|
||||
await system.run(getDownloadFileFromRepoCommand(config.gh_token, 'Photowall', 'photowall', 'cloudformation/ecr-lifecycle-policy.json'));
|
||||
await system.run(getDownloadFileFromRepoCommand(config.gh_token, 'Photowall', 'photowall', 'cloudformation/ecs-service.yaml'));
|
||||
|
||||
const stackName = await prompt.run();
|
||||
|
||||
const lifeCycleCommand = getLifeCyclePolicyCommand(stackName, `file://ecr-lifecycle-policy.json`);
|
||||
const updateStackCommand = getUpdateStackCommand(stackName, branchName, `file://ecs-service.yaml`);
|
||||
|
||||
const shouldRun = await getConfirmation(branchName, stackName);
|
||||
|
||||
if (shouldRun) {
|
||||
let output = await system.run(lifeCycleCommand, {cwd: '/tmp/', trim: true});
|
||||
print.fancy(output);
|
||||
output = await system.run(updateStackCommand, {cwd: '/tmp/', trim: true});
|
||||
print.fancy(output);
|
||||
}
|
||||
|
||||
} catch (e) {
|
||||
console.log(`e`, e)
|
||||
}
|
||||
|
||||
if (toolbox.fromMenu()) {
|
||||
await toolbox.menu.showMenu('deployment testservers')
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
|
||||
import { GluegunMenuToolbox } from '@lenne.tech/gluegun-menu';
|
||||
import { GluegunCommand } from 'gluegun'
|
||||
|
||||
|
||||
const command: GluegunCommand = {
|
||||
name: 'pwcli',
|
||||
run: async (toolbox: GluegunMenuToolbox) => {
|
||||
const { print } = toolbox;
|
||||
print.info('Welcome to photowall CLI for everything, almost 😬');
|
||||
await toolbox.menu.showMenu();
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = command;
|
||||
@@ -0,0 +1,131 @@
|
||||
import { GluegunMenuToolbox } from '@lenne.tech/gluegun-menu';
|
||||
import chalk = require('chalk');
|
||||
import { system } from 'gluegun';
|
||||
const { Confirm, Input } = require('enquirer');
|
||||
|
||||
const checkCLIProgram = async (toolbox: GluegunMenuToolbox, cmd: string) => {
|
||||
const {print, system, strings} = toolbox;
|
||||
try {
|
||||
const result = strings.trim(await system.run(`command -v ${cmd}`));
|
||||
return true;
|
||||
} catch(e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
name: 'settings',
|
||||
alias: ['se'],
|
||||
description: 'Setup settings for pwcli (se)',
|
||||
hidden: true,
|
||||
run: async (toolbox: GluegunMenuToolbox) => {
|
||||
|
||||
const {print, system, strings} = toolbox;
|
||||
|
||||
print.info(chalk.yellow(`
|
||||
|
||||
This will help you setup everything needed to run pwcli on a mac (maby linux).
|
||||
All settings will be saved to ${chalk.cyan('~/.pwcli_settings')}
|
||||
|
||||
First step is to install aws cli [https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html]
|
||||
and configuring it. Install it either with brew or do as specified in the link.
|
||||
|
||||
`));
|
||||
|
||||
// Check if brew is installed
|
||||
// if (await checkCLIProgram(toolbox, 'brew')) {
|
||||
// print.info(`\nDetected ${chalk.green('brew')}`);
|
||||
// } else {
|
||||
// print.info(`\nRequired program ${chalk.green('brew')} is not installed.`);
|
||||
|
||||
// if (await (new Confirm({
|
||||
// name: 'confirm',
|
||||
// message: `Do you want pwcli to install it?`
|
||||
// })).run()) {
|
||||
// print.info(`/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"`);
|
||||
// // system.run('/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"');
|
||||
// } else {
|
||||
// if (await (new Confirm({
|
||||
// name: 'confirm',
|
||||
// message: `Do you want to install it your self?`
|
||||
// })).run()) {
|
||||
// system.run('open https://brew.sh');
|
||||
// } else {
|
||||
// print.info('😔 ok, your choice..');
|
||||
// }
|
||||
// }
|
||||
|
||||
// if (await (new Confirm({
|
||||
// name: 'confirm',
|
||||
// message: `Is ${chalk.green('brew')} installed?`
|
||||
// })).run()) {
|
||||
// print.info('Great, lets continue!');
|
||||
// } else {
|
||||
// print.info('😔 ok, your choice..');
|
||||
// }
|
||||
// }
|
||||
|
||||
// if (await checkCLIProgram(toolbox, 'asdf')) {
|
||||
// print.info(`\nDetected ${chalk.green('aws cli')}`);
|
||||
// } else {
|
||||
// print.info(`\nRequired program ${chalk.green('aws cli')} is not installed.`);
|
||||
// if (await (new Confirm({
|
||||
// name: 'confirm',
|
||||
// message: `Do you want pwcli to install it?`
|
||||
// })).run()) {
|
||||
// print.info(`brew install awscli`);
|
||||
// // system.run('brew install awscli');
|
||||
// } else {
|
||||
// if (await (new Confirm({
|
||||
// name: 'confirm',
|
||||
// message: `Do you want to install it your self?`
|
||||
// })).run()) {
|
||||
// system.run('open https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html');
|
||||
// } else {
|
||||
// print.info('😔 ok, your choice..');
|
||||
// }
|
||||
// }
|
||||
|
||||
// if (await (new Confirm({
|
||||
// name: 'confirm',
|
||||
// message: `Is ${chalk.green('aws cli')} installed and configured?`
|
||||
// })).run()) {
|
||||
|
||||
// } else {
|
||||
// print.info('😔 ok, install it and run ..');
|
||||
// await toolbox.menu.showMenu();
|
||||
// }
|
||||
// }
|
||||
|
||||
system.run('touch ~/.pwcli_settings');
|
||||
print.info(`Created configuration file ${chalk.yellow(`~/.pwcli_settings`)}`);
|
||||
const config = {
|
||||
gh_token: '',
|
||||
photowall_repo: '',
|
||||
};
|
||||
|
||||
config.gh_token = await (new Input({
|
||||
message: `A github accesstoken is required with ${chalk.yellow('Full control of private repositories')}, please insert the key >`
|
||||
})).run();
|
||||
|
||||
config.photowall_repo = await (new Input({
|
||||
message: `If you want to be able to push active branch in your photowall repository, please insert the absolute path to the project >`
|
||||
})).run();
|
||||
|
||||
print.info(`
|
||||
|
||||
${JSON.stringify(config)}
|
||||
|
||||
`);
|
||||
if (await (new Confirm({
|
||||
message: `Ok to save the these settings to ${chalk.yellow(`~/.pwcli_settings`)}?`
|
||||
})).run()) {
|
||||
system.run(`echo '${JSON.stringify(config)}' > ~/.pwcli_settings`);
|
||||
} else {
|
||||
print.info('Ok then.');
|
||||
if (toolbox.fromMenu()) await toolbox.menu.showMenu();
|
||||
}
|
||||
|
||||
if (toolbox.fromMenu()) await toolbox.menu.showMenu();
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,14 @@
|
||||
import { GluegunMenuToolbox } from '@lenne.tech/gluegun-menu';
|
||||
|
||||
/**
|
||||
* Section1 menu
|
||||
*/
|
||||
module.exports = {
|
||||
name: 'setup',
|
||||
alias: ['s'],
|
||||
description: 'Setup pwcli (s)',
|
||||
hidden: true,
|
||||
run: async (toolbox: GluegunMenuToolbox) => {
|
||||
await toolbox.menu.showMenu('setup');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,19 @@
|
||||
|
||||
import { GluegunToolbox } from 'gluegun'
|
||||
|
||||
|
||||
// add your CLI-specific functionality here, which will then be accessible
|
||||
// to your commands
|
||||
module.exports = (toolbox: GluegunToolbox) => {
|
||||
toolbox.foo = () => {
|
||||
toolbox.print.info('called foo extension')
|
||||
}
|
||||
|
||||
// enable this if you want to read configuration in from
|
||||
// the current folder's package.json (in a "pwcli" property),
|
||||
// pwcli.config.json, etc.
|
||||
// toolbox.config = {
|
||||
// ...toolbox.config,
|
||||
// ...toolbox.config.loadConfig("pwcli", process.cwd())
|
||||
// }
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
// export types
|
||||
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"allowSyntheticDefaultImports": false,
|
||||
"experimentalDecorators": true,
|
||||
"lib": [
|
||||
"es2015",
|
||||
"scripthost",
|
||||
"es2015.promise",
|
||||
"es2015.generator",
|
||||
"es2015.iterable",
|
||||
"dom"
|
||||
],
|
||||
"module": "commonjs",
|
||||
"moduleResolution": "node",
|
||||
"noImplicitAny": false,
|
||||
"noImplicitThis": true,
|
||||
"noUnusedLocals": false,
|
||||
"sourceMap": false,
|
||||
"inlineSourceMap": true,
|
||||
"outDir": "build",
|
||||
"strict": false,
|
||||
"target": "es5",
|
||||
"declaration": true,
|
||||
"declarationDir": "build/types"
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"exclude": ["node_modules"]
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"extends": ["tslint-config-standard", "tslint-config-prettier"],
|
||||
"rules": {
|
||||
"strict-type-predicates": false
|
||||
},
|
||||
"env": {
|
||||
"jest": true
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user