@fishawack/lab-env 2.2.0 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,28 @@
1
1
  ## Changelog
2
2
 
3
+ ### 3.2.0 (2022-09-12)
4
+ * [Feature] Added newly setup AWS accounts to the client prompts on `fw provision`
5
+ * [Change] Clients now listed in alphabetical order
6
+ * [Change] Clients list no longer loops
7
+
8
+ ### 3.1.0 (2022-09-08)
9
+ * [Feature] exec command now has the -g flag to prepend the full grunt path
10
+ * [Feature] Diagnosis now has a version number that will prompt for re-run when needed
11
+ * [Change] Bumped core `0.1.0` to `0.2.0`
12
+ * [Bug] rebuild now passes flags after the service
13
+ * [Bug] Specify platform in core build command
14
+ * [Bug] Login to docker during docker before versioning and building images
15
+ * [Misc] Tests now use cli path
16
+
17
+ ### 3.0.0 (2022-09-05)
18
+ * [Feature] Added newly setup AWS accounts to the client prompts on `fw provision`
19
+ * [Feature] Added key/dekey commands
20
+ * [Change] Provisioned environment variables now append client to uniqueify the services created
21
+ * [Change] `fw provision` no longer does two polls to cloudfront to speed up the process
22
+ * [Change] Drupal now defaults to 8.1 php
23
+ * [Bug] Added protocol to www in cloudfront function to ensure redirect works correctly
24
+ * [Bug] Added posiexem to fix M1 chip issue on drupal
25
+
3
26
  ### 2.2.0 (2022-08-10)
4
27
  * [Feature] Can now skip diagnose in `fw diagnose`
5
28
  * [Feature] Can now provision AWS environments using `fw provision`
@@ -12,17 +12,17 @@ describe('deploy', () => {
12
12
 
13
13
  execSync(`git -C _Test/_fixtures clone git@bitbucket.org:fishawackdigital/${repo}`, {encoding: 'utf8', stdio: 'inherit'});
14
14
 
15
- execSync('fw setup', opts);
15
+ execSync('node ../../../cli.js setup', opts);
16
16
 
17
- execSync('fw prod', opts);
17
+ execSync('node ../../../cli.js prod', opts);
18
18
  });
19
19
 
20
20
  it(`All ${repo} tests should pass`, async () => {
21
- expect(execSync('fw test', opts)).to.not.equal(Error);
21
+ expect(execSync('node ../../../cli.js test', opts)).to.not.equal(Error);
22
22
  });
23
23
 
24
24
  after(() => {
25
- execSync('fw nuke', opts)
25
+ execSync('node ../../../cli.js nuke', opts)
26
26
 
27
27
  execSync(`rm -rf _Test/_fixtures/${repo}`, {encoding: 'utf8', stdio: 'inherit'});
28
28
  });
@@ -12,17 +12,17 @@ describe('deploy', () => {
12
12
 
13
13
  execSync(`git -C _Test/_fixtures clone git@bitbucket.org:fishawackdigital/${repo}`, {encoding: 'utf8', stdio: 'inherit'});
14
14
 
15
- execSync('fw setup', opts);
15
+ execSync('node ../../../cli.js setup', opts);
16
16
 
17
- execSync('fw prod', opts);
17
+ execSync('node ../../../cli.js prod', opts);
18
18
  });
19
19
 
20
20
  it(`All ${repo} tests should pass`, async () => {
21
- expect(execSync('fw test', opts)).to.not.equal(Error);
21
+ expect(execSync('node ../../../cli.js test', opts)).to.not.equal(Error);
22
22
  });
23
23
 
24
24
  after(() => {
25
- execSync('fw nuke', opts)
25
+ execSync('node ../../../cli.js nuke', opts)
26
26
 
27
27
  execSync(`rm -rf _Test/_fixtures/${repo}`, {encoding: 'utf8', stdio: 'inherit'});
28
28
  });
@@ -12,17 +12,17 @@ describe('deploy', () => {
12
12
 
13
13
  execSync(`git -C _Test/_fixtures clone git@bitbucket.org:fishawackdigital/${repo}`, {encoding: 'utf8', stdio: 'inherit'});
14
14
 
15
- execSync('fw setup', opts);
15
+ execSync('node ../../../cli.js setup', opts);
16
16
 
17
- execSync('fw prod', opts);
17
+ execSync('node ../../../cli.js prod', opts);
18
18
  });
19
19
 
20
20
  it(`All ${repo} tests should pass`, async () => {
21
- expect(execSync('fw test', opts)).to.not.equal(Error);
21
+ expect(execSync('node ../../../cli.js test', opts)).to.not.equal(Error);
22
22
  });
23
23
 
24
24
  after(() => {
25
- execSync('fw nuke', opts)
25
+ execSync('node ../../../cli.js nuke', opts)
26
26
 
27
27
  execSync(`rm -rf _Test/_fixtures/${repo}`, {encoding: 'utf8', stdio: 'inherit'});
28
28
  });
@@ -12,17 +12,17 @@ describe('deploy', () => {
12
12
 
13
13
  execSync(`git -C _Test/_fixtures clone git@bitbucket.org:fishawackdigital/${repo}`, {encoding: 'utf8', stdio: 'inherit'});
14
14
 
15
- execSync('fw setup', opts);
15
+ execSync('node ../../../cli.js setup', opts);
16
16
 
17
- execSync('fw prod', opts);
17
+ execSync('node ../../../cli.js prod', opts);
18
18
  });
19
19
 
20
20
  it(`All ${repo} tests should pass`, async () => {
21
- expect(execSync('fw test', opts)).to.not.equal(Error);
21
+ expect(execSync('node ../../../cli.js test', opts)).to.not.equal(Error);
22
22
  });
23
23
 
24
24
  after(() => {
25
- execSync('fw nuke', opts)
25
+ execSync('node ../../../cli.js nuke', opts)
26
26
 
27
27
  execSync(`rm -rf _Test/_fixtures/${repo}`, {encoding: 'utf8', stdio: 'inherit'});
28
28
  });
@@ -12,17 +12,17 @@ describe('deploy', () => {
12
12
 
13
13
  execSync(`git -C _Test/_fixtures clone git@bitbucket.org:fishawackdigital/${repo}`, {encoding: 'utf8', stdio: 'inherit'});
14
14
 
15
- execSync('fw setup', opts);
15
+ execSync('node ../../../cli.js setup', opts);
16
16
 
17
- execSync('fw prod', opts);
17
+ execSync('node ../../../cli.js prod', opts);
18
18
  });
19
19
 
20
20
  it(`All ${repo} tests should pass`, async () => {
21
- expect(execSync('fw test', opts)).to.not.equal(Error);
21
+ expect(execSync('node ../../../cli.js test', opts)).to.not.equal(Error);
22
22
  });
23
23
 
24
24
  after(() => {
25
- execSync('fw nuke', opts)
25
+ execSync('node ../../../cli.js nuke', opts)
26
26
 
27
27
  execSync(`rm -rf _Test/_fixtures/${repo}`, {encoding: 'utf8', stdio: 'inherit'});
28
28
  });
package/_Test/check.js ADDED
@@ -0,0 +1,29 @@
1
+ 'use strict';
2
+
3
+ const repo = `newrepo`;
4
+ const opts = {encoding: 'utf8', stdio: 'inherit', cwd: `_Test/_fixtures/${repo}`};
5
+
6
+ const expect = require('chai').expect;
7
+ const execSync = require('child_process').execSync;
8
+
9
+ describe('check', () => {
10
+ before(function(){
11
+ execSync(`mkdir _Test/_fixtures/${repo} && cd _Test/_fixtures/${repo} && npm init -y`, {encoding: 'utf8', stdio: 'inherit'});
12
+
13
+ execSync('node ../../../cli.js install lodash@4.17.15 query-string@7.1.1', opts);
14
+ });
15
+
16
+ it(`Should flag query-string as non es5 dependency`, () => {
17
+ expect(execSync('node ../../../cli.js check', {cwd: `_Test/_fixtures/${repo}`}).toString()).to.contain('query-string');
18
+ });
19
+
20
+ it(`Should not flag lodash as es5 dependency`, () => {
21
+ expect(execSync('node ../../../cli.js check', {cwd: `_Test/_fixtures/${repo}`}).toString()).to.not.contain('lodash');
22
+ });
23
+
24
+ after(() => {
25
+ execSync('node ../../../cli.js nuke', opts)
26
+
27
+ execSync(`rm -rf _Test/_fixtures/${repo}`, {encoding: 'utf8', stdio: 'inherit'});
28
+ });
29
+ });
package/_Test/key.js ADDED
@@ -0,0 +1,33 @@
1
+ 'use strict';
2
+
3
+ const expect = require('chai').expect;
4
+ const aws = require("../commands/create/services/aws/index.js");
5
+
6
+ describe('key', async () => {
7
+ let account = 'fishawack';
8
+
9
+ before(async () => {
10
+ let res = await aws.iam.createFWIAMUser('fw-test-user', account);
11
+
12
+ // Wait for key as AWS doesn't provide a way to wait for it to becom eactive
13
+ await new Promise(resolve => setTimeout(() => resolve(), 10000));
14
+
15
+ process.env.AWS_ACCESS_KEY_ID = res.AccessKey.AccessKeyId;
16
+ process.env.AWS_SECRET_ACCESS_KEY = res.AccessKey.SecretAccessKey;
17
+ });
18
+
19
+ it('Should be able to access AWS service', async () => {
20
+ let res;
21
+
22
+ try{ res = await aws.s3.listS3Buckets(); } catch(e){ console.log(e.message); }
23
+
24
+ expect(res).to.not.be.undefined;
25
+ });
26
+
27
+ after(async () => {
28
+ delete process.env.AWS_ACCESS_KEY_ID;
29
+ delete process.env.AWS_SECRET_ACCESS_KEY;
30
+
31
+ await aws.iam.removeIAMUser('fw-test-user', account);
32
+ });
33
+ });
package/cli.js CHANGED
@@ -59,7 +59,7 @@ if(!_.services && !(args[0] === 'origin' || args[0] === '--version')) process.ex
59
59
  ['build', 'config', 'down', 'mocha', 'rebuild', 'up', 'volumes', 'compose'].forEach(d => cli.command(...require(`./commands/docker/${d}.js`)));
60
60
 
61
61
  // Create commands
62
- ['new', 'provision', 'deprovision', 'diagnose', 'delete'].forEach(d => cli.command(...require(`./commands/create/cmds/${d}.js`)));
62
+ ['new', 'provision', 'deprovision', 'diagnose', 'delete', 'key', 'dekey'].forEach(d => cli.command(...require(`./commands/create/cmds/${d}.js`)));
63
63
 
64
64
  cli.demandCommand(1, '')
65
65
  .wrap(null)
package/commands/check.js CHANGED
@@ -13,7 +13,7 @@ module.exports = [
13
13
  });
14
14
  },
15
15
  argv => {
16
- execSync(`${_.docker} ${_.run}c "check-dependencies ${argv.v ? '' : '&>/dev/null'} && echo -e '\\033[0;32mNpm deps OK\\033[0m' || { echo -e '\\033[0;31mNpm deps missing or outdated\\033[0m'; }"`, _.opts);
16
+ execSync(`${_.docker} ${_.run}c "check-dependencies ${argv.v ? '' : '&>/dev/null'} && echo -e '\\033[0;32mNpm deps OK\\033[0m' || { echo -e '\\033[0;31mNpm deps missing or outdated\\033[0m'; } && are-you-es5 check . && echo -e '\\033[0;32mNpm-ES5 compatibility OK\\033[0m' || { echo -e '\\033[0;31mNpm-ES5 incompatibilities detected\\033[0m'; }"`, _.opts);
17
17
 
18
18
  if(_.platform === "laravel" || _.platform === "drupal" || _.platform === "craftcms"){
19
19
  execSync(`${_.docker} ${_.method} php bash -lc "composer install --dry-run ${argv.v ? '' : '2>&1'} | grep -q 'Nothing to install, update or remove' && echo -e '\\033[0;32mComposer deps OK\\033[0m' || echo -e '\\033[0;31mComposer deps missing or outdated\\033[0m'"`, _.opts);
@@ -0,0 +1,72 @@
1
+ const _ = require('../../../globals.js');
2
+ const utilities = require('../libs/utilities');
3
+ const inquirer = require('inquirer');
4
+ const aws = require('../services/aws/index.js');
5
+
6
+ module.exports = [
7
+ 'dekey',
8
+ false,
9
+ yargs => {},
10
+ async argv => {
11
+ let users = [];
12
+ let clients = [];
13
+
14
+ let answer = await inquirer.prompt([
15
+ {
16
+ type: 'confirm',
17
+ name: 'check',
18
+ message: `Remove keys for all users`,
19
+ default: 'Y'
20
+ }
21
+ ]);
22
+
23
+ if(answer.check){
24
+ users = _.config.users.map(d => d.username);
25
+ } else {
26
+ answer = await inquirer.prompt([
27
+ {
28
+ type: 'checkbox',
29
+ name: 'users',
30
+ message: 'Select users',
31
+ choices: _.config.users.map(d => d.username)
32
+ }
33
+ ]);
34
+
35
+ users = answer.users;
36
+ }
37
+
38
+ answer = await inquirer.prompt([
39
+ {
40
+ type: 'confirm',
41
+ name: 'check',
42
+ message: `Remove keys for all clients`,
43
+ default: 'Y'
44
+ }
45
+ ]);
46
+
47
+ if(answer.check){
48
+ clients = aws.clients;
49
+ } else {
50
+ answer = await inquirer.prompt([
51
+ {
52
+ type: 'checkbox',
53
+ name: 'clients',
54
+ message: 'Select clients',
55
+ choices: aws.clients
56
+ }
57
+ ]);
58
+
59
+ clients = answer.clients;
60
+ }
61
+
62
+ for(let i = 0; i < clients.length; i++){
63
+ let client = clients[i];
64
+
65
+ for(let j = 0; j < users.length; j++){
66
+ let user = users[j];
67
+
68
+ await aws.iam.removeIAMUser(`fw-automation-${user}`, client);
69
+ }
70
+ }
71
+ }
72
+ ];
@@ -1,6 +1,7 @@
1
1
  const _ = require('../../../globals.js');
2
2
  const inquirer = require('inquirer');
3
3
  const aws = require('../services/aws/index.js');
4
+ const utilities = require('../libs/utilities');
4
5
 
5
6
  module.exports = [
6
7
  ['deprovision', 'deprov'],
@@ -14,19 +15,6 @@ module.exports = [
14
15
  },
15
16
  async argv => {
16
17
  let branch = argv.branch || _.branch;
17
-
18
- let answer = await inquirer.prompt([
19
- {
20
- type: 'confirm',
21
- name: 'check',
22
- message: `Deprovisioning fw-auto-${_.repo}-${branch}, are you sure you want to continue?`,
23
- default: 'Y'
24
- }
25
- ]);
26
-
27
- if(!answer.check){
28
- process.exit(1);
29
- }
30
18
 
31
19
  const answers = await inquirer.prompt([
32
20
  {
@@ -39,15 +27,28 @@ module.exports = [
39
27
  type: 'list',
40
28
  name: 'client',
41
29
  message: 'Which AWS account is this deployed too?',
42
- choices: ['fishawack', 'abbvie', 'sanofigenzyme', 'gsk', 'janssen', 'astrazeneca', 'training'],
30
+ choices: aws.clients,
43
31
  default: 'fishawack'
44
32
  }
45
33
  ]);
46
34
 
47
- try { await aws.s3.removeS3Bucket(`fw-auto-${_.repo}-${branch}`, answers.client); } catch(e) {}
35
+ let answer = await inquirer.prompt([
36
+ {
37
+ type: 'confirm',
38
+ name: 'check',
39
+ message: `Deprovisioning ${utilities.colorize(aws.slug(_.repo, answers.client, branch), 'error')} from ${utilities.colorize(answers.client, 'error')} AWS account, are you sure you want to continue?`,
40
+ default: false
41
+ }
42
+ ]);
43
+
44
+ if(!answer.check){
45
+ process.exit(1);
46
+ }
47
+
48
+ try { await aws.s3.removeS3Bucket(aws.slug(_.repo, answers.client, branch), answers.client); } catch(e) {}
48
49
 
49
50
  try { await aws.cloudfront.removeCloudFrontDistribution(answers.id, answers.client); } catch(e) {}
50
51
 
51
- try { await aws.cloudfront.removeCloudFrontFunction(`fw-auto-${_.repo}-${branch}`, answers.client); } catch(e) {}
52
+ try { await aws.cloudfront.removeCloudFrontFunction(aws.slug(_.repo, answers.client, branch), answers.client); } catch(e) {}
52
53
  }
53
54
  ];
@@ -4,6 +4,10 @@ const egnyte = require("../services/egnyte");
4
4
  const gitlab = require("../services/gitlab");
5
5
  const guide = require("../services/guide");
6
6
  const test = require("../services/test");
7
+ const _ = require('../../../globals.js');
8
+ const path = require('path');
9
+ const {writeFileSync} = require('fs');
10
+ const os = require('os');
7
11
 
8
12
  module.exports = [
9
13
  ['diagnose', 'diag'],
@@ -73,6 +77,12 @@ module.exports = [
73
77
 
74
78
  await bitbucket.remove(userRepoName);
75
79
  }
80
+
81
+ // Update diagnosis version in ~/.lab-env config file
82
+ if(_.config.diagnosis !== _.diagnosis){
83
+ _.config.diagnosis = _.diagnosis;
84
+ writeFileSync(path.join(os.homedir(), '', '.lab-env'), JSON.stringify(_.config, null, 4));
85
+ }
76
86
  } catch(e){
77
87
  if(e.message){
78
88
  console.log(`\nError: ${e.message}`);
@@ -0,0 +1,96 @@
1
+ const _ = require('../../../globals.js');
2
+ const utilities = require('../libs/utilities');
3
+ const inquirer = require('inquirer');
4
+ const aws = require('../services/aws/index.js');
5
+
6
+ module.exports = [
7
+ 'key',
8
+ false,
9
+ yargs => {},
10
+ async argv => {
11
+ let users = [];
12
+ let clients = [];
13
+
14
+ let answer = await inquirer.prompt([
15
+ {
16
+ type: 'confirm',
17
+ name: 'check',
18
+ message: `Set keys for all users`,
19
+ default: 'Y'
20
+ }
21
+ ]);
22
+
23
+ if(answer.check){
24
+ users = _.config.users.map(d => d.username);
25
+ } else {
26
+ answer = await inquirer.prompt([
27
+ {
28
+ type: 'checkbox',
29
+ name: 'users',
30
+ message: 'Select users',
31
+ choices: _.config.users.map(d => d.username)
32
+ }
33
+ ]);
34
+
35
+ users = answer.users;
36
+ }
37
+
38
+ answer = await inquirer.prompt([
39
+ {
40
+ type: 'confirm',
41
+ name: 'check',
42
+ message: `Set keys for all clients`,
43
+ default: 'Y'
44
+ }
45
+ ]);
46
+
47
+ if(answer.check){
48
+ clients = aws.clients;
49
+ } else {
50
+ answer = await inquirer.prompt([
51
+ {
52
+ type: 'checkbox',
53
+ name: 'clients',
54
+ message: 'Select clients',
55
+ choices: aws.clients
56
+ }
57
+ ]);
58
+
59
+ clients = answer.clients;
60
+ }
61
+
62
+ let credentials = {};
63
+
64
+ for(let i = 0; i < clients.length; i++){
65
+ let client = clients[i];
66
+
67
+ for(let j = 0; j < users.length; j++){
68
+ let user = users[j];
69
+
70
+ if(!credentials[user]){
71
+ credentials[user] = {};
72
+ }
73
+
74
+ let res = await aws.iam.createFWIAMUser(`fw-automation-${user}`, client);
75
+
76
+ credentials[user][client] = {
77
+ key: res.AccessKey && res.AccessKey.AccessKeyId || res.AccessKeyMetadata[0].AccessKeyId,
78
+ secret: res.AccessKey && res.AccessKey.SecretAccessKey || '** secret **'
79
+ }
80
+ }
81
+ }
82
+
83
+ let output = '';
84
+
85
+ for(var user in credentials){
86
+ output += utilities.colorize(`\n${user}\n`, 'title');
87
+ for(var client in credentials[user]){
88
+ output += `\n[${client}]\n`;
89
+ output += `aws_access_key_id = ${credentials[user][client].key}\n`;
90
+ output += `aws_secret_access_key = ${credentials[user][client].secret}\n`;
91
+ }
92
+ }
93
+
94
+ console.log(output);
95
+ }
96
+ ];
@@ -37,14 +37,15 @@ module.exports = [
37
37
  name: 'stack',
38
38
  message: 'What type of project are you deploying?',
39
39
  choices: ['static'],
40
- default: 'static'
40
+ default: 0
41
41
  },
42
42
  {
43
43
  type: 'list',
44
44
  name: 'client',
45
45
  message: 'Which AWS account should this be deployed too?',
46
- choices: ['fishawack', 'abbvie', 'sanofigenzyme', 'gsk', 'janssen', 'astrazeneca', 'training'],
47
- default: 'fishawack'
46
+ choices: aws.clients.sort(),
47
+ default: 0,
48
+ loop: false
48
49
  },
49
50
  {
50
51
  type: 'confirm',
@@ -93,7 +94,7 @@ module.exports = [
93
94
  let infastructure;
94
95
 
95
96
  try{
96
- infastructure = await aws.static(`fw-auto-${_.repo}-${branch}`, answers.client, [{Key: 'repository', Value: _.repo}, {Key: 'environment', Value: branch}], credentials);
97
+ infastructure = await aws.static(aws.slug(_.repo, answers.client, branch), answers.client, [{Key: 'repository', Value: _.repo}, {Key: 'environment', Value: branch}], credentials);
97
98
  } catch(e){
98
99
  console.log(e.message);
99
100
  process.exit(1);
@@ -12,7 +12,7 @@ function handler(event) {
12
12
  var response = {
13
13
  statusCode: 301,
14
14
  statusDescription: 'Moved Permanently',
15
- headers: { "location": { "value": `${event.request.headers.host.value.split('www.')[1]}${event.request.uri}${query}` } }
15
+ headers: { "location": { "value": `https://${event.request.headers.host.value.split('www.')[1]}${event.request.uri}${query}` } }
16
16
  };
17
17
 
18
18
  return response;
@@ -12,7 +12,7 @@ function handler(event) {
12
12
  var response = {
13
13
  statusCode: 301,
14
14
  statusDescription: 'Moved Permanently',
15
- headers: { "location": { "value": `${event.request.headers.host.value.split('www.')[1]}${event.request.uri}${query}` } }
15
+ headers: { "location": { "value": `https://${event.request.headers.host.value.split('www.')[1]}${event.request.uri}${query}` } }
16
16
  };
17
17
 
18
18
  return response;
@@ -8,6 +8,8 @@ const colorize = module.exports.colorize = (str, type) => {
8
8
  switch (type) {
9
9
  case 'success':
10
10
  return chalk.green(str);
11
+ case 'warning':
12
+ return chalk.yellow(str);
11
13
  case 'error':
12
14
  return chalk.red(str);
13
15
  case 'title':
@@ -1,13 +1,10 @@
1
1
  const { CloudFrontClient, CreateDistributionWithTagsCommand, CreateCloudFrontOriginAccessIdentityCommand, DeleteDistributionCommand , DeleteCloudFrontOriginAccessIdentityCommand, GetDistributionCommand, UpdateDistributionCommand, GetCloudFrontOriginAccessIdentityCommand, CreateFunctionCommand, GetFunctionCommand, UpdateFunctionCommand, PublishFunctionCommand, DeleteFunctionCommand, DescribeFunctionCommand } = require("@aws-sdk/client-cloudfront");
2
2
  const fs = require('fs');
3
3
  const { Spinner } = require('../../libs/utilities');
4
+ const { createClient } = require('./misc.js');
4
5
 
5
- let region = `us-east-1`;
6
-
7
- const client = new CloudFrontClient({ region });
8
-
9
- module.exports.createCloudFrontDistribution = async (name, account, tags = []) => {
10
- process.env.AWS_PROFILE = account;
6
+ module.exports.createCloudFrontDistribution = async (name, account, tags = [], FunctionARN = null, region = 'us-east-1') => {
7
+ const client = createClient(CloudFrontClient, account, region);
11
8
 
12
9
  let OAI = await Spinner.prototype.simple(`Creating CloudFront OAI`, () => {
13
10
  return client.send(
@@ -46,7 +43,16 @@ module.exports.createCloudFrontDistribution = async (name, account, tags = []) =
46
43
  Compress: true,
47
44
  TargetOriginId: `${name}.s3.${region}.amazonaws.com`,
48
45
  ViewerProtocolPolicy: 'redirect-to-https',
49
- CachePolicyId: '658327ea-f89d-4fab-a63d-7e88639e58f6' // Built in, Managed AWS Policy - Cache Optimized
46
+ CachePolicyId: '658327ea-f89d-4fab-a63d-7e88639e58f6', // Built in, Managed AWS Policy - Cache Optimized
47
+ FunctionAssociations: FunctionARN && {
48
+ Items: [
49
+ {
50
+ EventType: 'viewer-request',
51
+ FunctionARN
52
+ }
53
+ ],
54
+ Quantity: 1
55
+ }
50
56
  },
51
57
  Origins: {
52
58
  Items: [
@@ -86,7 +92,7 @@ module.exports.createCloudFrontDistribution = async (name, account, tags = []) =
86
92
  }
87
93
 
88
94
  module.exports.removeCloudFrontDistribution = async (Id, account) => {
89
- process.env.AWS_PROFILE = account;
95
+ const client = createClient(CloudFrontClient, account);
90
96
 
91
97
  let res = await Spinner.prototype.simple(`Retrieving the CloudFront distribution ${Id}`, () => {
92
98
  return client.send(
@@ -128,7 +134,7 @@ module.exports.removeCloudFrontDistribution = async (Id, account) => {
128
134
  }
129
135
 
130
136
  module.exports.waitForCloudFrontDistribution = async (Id, account) => {
131
- process.env.AWS_PROFILE = account;
137
+ const client = createClient(CloudFrontClient, account);
132
138
 
133
139
  let status;
134
140
 
@@ -146,7 +152,7 @@ module.exports.waitForCloudFrontDistribution = async (Id, account) => {
146
152
  }
147
153
 
148
154
  module.exports.createCloudFrontFunction = async (name, account, fn, config) => {
149
- process.env.AWS_PROFILE = account;
155
+ const client = createClient(CloudFrontClient, account);
150
156
 
151
157
  let FunctionConfig = {
152
158
  Comment: `lab-env provisioned cloudfront function for project ${name} using code snippet ${fn}.js`,
@@ -202,7 +208,7 @@ module.exports.createCloudFrontFunction = async (name, account, fn, config) => {
202
208
  }
203
209
 
204
210
  module.exports.removeCloudFrontFunction = async (name, account) => {
205
- process.env.AWS_PROFILE = account;
211
+ const client = createClient(CloudFrontClient, account);
206
212
 
207
213
  let res = await Spinner.prototype.simple(`Retrieving CloudFront function`, () => {
208
214
  return client.send(
@@ -225,7 +231,7 @@ module.exports.removeCloudFrontFunction = async (name, account) => {
225
231
  }
226
232
 
227
233
  module.exports.setCloudFrontFunctionAssociation = async (Id, account) => {
228
- process.env.AWS_PROFILE = account;
234
+ const client = createClient(CloudFrontClient, account);
229
235
 
230
236
  let res = await Spinner.prototype.simple(`Retrieving CloudFront distribution`, () => {
231
237
  return client.send(
@@ -264,7 +270,7 @@ module.exports.setCloudFrontFunctionAssociation = async (Id, account) => {
264
270
  };
265
271
 
266
272
  module.exports.removeCloudFrontFunctionAssociation = async (Id, account) => {
267
- process.env.AWS_PROFILE = account;
273
+ const client = createClient(CloudFrontClient, account);
268
274
 
269
275
  let res = await Spinner.prototype.simple(`Retrieving CloudFront distribution`, () => {
270
276
  return client.send(
@@ -0,0 +1,170 @@
1
+ const { IAMClient, CreateUserCommand, GetUserCommand, DeleteUserCommand, AttachUserPolicyCommand, ListAttachedUserPoliciesCommand, DetachUserPolicyCommand, CreateAccessKeyCommand, DeleteAccessKeyCommand, ListAccessKeysCommand } = require("@aws-sdk/client-iam");
2
+ const { Spinner } = require('../../libs/utilities');
3
+ const { createClient } = require('./misc.js');
4
+
5
+ module.exports.createIAMUser = async (UserName, account) => {
6
+ const client = createClient(IAMClient, account);
7
+
8
+ let res;
9
+
10
+ try{
11
+ res = await Spinner.prototype.simple(`Creating IAM user ${UserName}`, () => {
12
+ return client.send(
13
+ new CreateUserCommand({ UserName })
14
+ );
15
+ });
16
+ } catch(e){
17
+ res = await Spinner.prototype.simple(`Retrieving the already existing IAM user ${UserName}`, () => {
18
+ return client.send(
19
+ new GetUserCommand({ UserName })
20
+ );
21
+ });
22
+ }
23
+
24
+ return res;
25
+ };
26
+
27
+ module.exports.createFWIAMUser = async (UserName, account) => {
28
+ await module.exports.createIAMUser(UserName, account);
29
+
30
+ await module.exports.syncFWIAMPolicies(UserName, account);
31
+
32
+ let res = await module.exports.createAccessKeySafe(UserName, account);
33
+
34
+ return res;
35
+ };
36
+
37
+ module.exports.removeIAMUser = async (UserName, account) => {
38
+ const client = createClient(IAMClient, account);
39
+
40
+ let res;
41
+
42
+ try{
43
+ await Spinner.prototype.simple(`Checking if IAM user ${UserName} exists`, () => {
44
+ return client.send(
45
+ new GetUserCommand({ UserName })
46
+ );
47
+ });
48
+
49
+ await module.exports.removeAllIAMPolicies(UserName, account);
50
+
51
+ await module.exports.removeAllAccessKeys(UserName, account);
52
+
53
+ res = await Spinner.prototype.simple(`Removing IAM user ${UserName}`, () => {
54
+ return client.send(
55
+ new DeleteUserCommand({ UserName })
56
+ );
57
+ });
58
+ } catch(e){
59
+ }
60
+
61
+ return res;
62
+ };
63
+
64
+ module.exports.attachIAMPolicy = async (UserName, account, policy) => {
65
+ const client = createClient(IAMClient, account);
66
+
67
+ let res = await Spinner.prototype.simple(`Attaching IAM policy ${policy}`, () => {
68
+ return client.send(
69
+ new AttachUserPolicyCommand({ UserName, PolicyArn: policy })
70
+ );
71
+ });
72
+
73
+ return res;
74
+ };
75
+
76
+ module.exports.syncFWIAMPolicies = async (UserName, account) => {
77
+ await module.exports.removeAllIAMPolicies(UserName, account);
78
+ await module.exports.attachIAMPolicy(UserName, account, 'arn:aws:iam::aws:policy/AmazonS3FullAccess');
79
+ await module.exports.attachIAMPolicy(UserName, account, 'arn:aws:iam::aws:policy/CloudFrontFullAccess');
80
+ };
81
+
82
+ module.exports.removeIAMPolicy = async (UserName, account, policy) => {
83
+ const client = createClient(IAMClient, account);
84
+
85
+ let res = await Spinner.prototype.simple(`Detaching IAM policy ${policy}`, () => {
86
+ return client.send(
87
+ new DetachUserPolicyCommand({ UserName, PolicyArn: policy })
88
+ );
89
+ });
90
+
91
+ return res;
92
+ };
93
+
94
+ module.exports.listIAMPolicies = async (UserName, account) => {
95
+ const client = createClient(IAMClient, account);
96
+
97
+ let res = await Spinner.prototype.simple(`Listing IAM policies`, () => {
98
+ return client.send(
99
+ new ListAttachedUserPoliciesCommand({ UserName })
100
+ );
101
+ });
102
+
103
+ return res;
104
+ };
105
+
106
+ module.exports.removeAllIAMPolicies = async (UserName, account) => {
107
+ let res = await module.exports.listIAMPolicies(UserName, account);
108
+
109
+ for(let i = 0; i < res.AttachedPolicies.length; i++){
110
+ await module.exports.removeIAMPolicy(UserName, account, res.AttachedPolicies[i].PolicyArn);
111
+ }
112
+
113
+ return res;
114
+ };
115
+
116
+ module.exports.createAccessKey = async (UserName, account) => {
117
+ const client = createClient(IAMClient, account);
118
+
119
+ let res = await Spinner.prototype.simple(`Creating access key`, () => {
120
+ return client.send(
121
+ new CreateAccessKeyCommand({ UserName })
122
+ );
123
+ });
124
+
125
+ return res;
126
+ };
127
+
128
+ module.exports.removeAccessKey = async (UserName, account, AccessKeyId) => {
129
+ const client = createClient(IAMClient, account);
130
+
131
+ let res = await Spinner.prototype.simple(`Removing access key ${AccessKeyId}`, () => {
132
+ return client.send(
133
+ new DeleteAccessKeyCommand({ AccessKeyId, UserName })
134
+ );
135
+ });
136
+
137
+ return res;
138
+ };
139
+
140
+ module.exports.listAccessKeys = async (UserName, account) => {
141
+ const client = createClient(IAMClient, account);
142
+
143
+ let res = await Spinner.prototype.simple(`Listing access keys`, () => {
144
+ return client.send(
145
+ new ListAccessKeysCommand({ UserName })
146
+ );
147
+ });
148
+
149
+ return res;
150
+ };
151
+
152
+ module.exports.removeAllAccessKeys = async (UserName, account) => {
153
+ let res = await module.exports.listAccessKeys(UserName, account);
154
+
155
+ for(let i = 0; i < res.AccessKeyMetadata.length; i++){
156
+ await module.exports.removeAccessKey(UserName, account, res.AccessKeyMetadata[i].AccessKeyId);
157
+ }
158
+
159
+ return res;
160
+ };
161
+
162
+ module.exports.createAccessKeySafe = async (UserName, account) => {
163
+ let res = await module.exports.listAccessKeys(UserName, account);
164
+
165
+ if(!res.AccessKeyMetadata.length){
166
+ res = await module.exports.createAccessKey(UserName, account);
167
+ }
168
+
169
+ return res;
170
+ };
@@ -1,16 +1,19 @@
1
1
  module.exports.s3 = require("./s3.js");
2
2
  module.exports.cloudfront = require("./cloudfront.js");
3
+ module.exports.iam = require("./iam.js");
4
+
5
+ module.exports.slug = (repo, client, branch) => `fw-auto-${client}-${repo}-${branch}`;
6
+
7
+ module.exports.clients = ['fishawack', 'abbvie', 'sanofigenzyme', 'gsk', 'janssen', 'astrazeneca', 'ptc', 'jazz', 'pfizer', 'heron', 'novartis', 'training', 'merck', 'acadia', 'travere'];
3
8
 
4
9
  module.exports.static = async (name, account, tags = [], credentials = []) => {
5
10
  let s3 = await module.exports.s3.createS3Bucket(name, account, tags);
6
11
 
7
- let cloudfront = await module.exports.cloudfront.createCloudFrontDistribution(name, account, tags);
12
+ let cloudfrontFunction = await module.exports.cloudfront.createCloudFrontFunction(name, account, credentials.length ? 'aws-cloudfront-auth' : 'aws-cloudfront-simple', {credentials: credentials.map(d => `Basic ${Buffer.from(`${d.username}:${d.password}`).toString('base64')}`)});
8
13
 
9
- await module.exports.s3.setS3BucketPolicy(name, account, cloudfront.Distribution.DistributionConfig.Origins.Items[0].S3OriginConfig.OriginAccessIdentity.split('origin-access-identity/cloudfront/')[1]);
14
+ let cloudfront = await module.exports.cloudfront.createCloudFrontDistribution(name, account, tags, cloudfrontFunction.FunctionSummary.FunctionMetadata.FunctionARN);
10
15
 
11
- await module.exports.cloudfront.createCloudFrontFunction(name, account, credentials.length ? 'aws-cloudfront-auth' : 'aws-cloudfront-simple', {credentials: credentials.map(d => `Basic ${Buffer.from(`${d.username}:${d.password}`).toString('base64')}`)});
12
-
13
- await module.exports.cloudfront.setCloudFrontFunctionAssociation(cloudfront.Distribution.Id, account);
16
+ await module.exports.s3.setS3BucketPolicy(name, account, cloudfront.Distribution.DistributionConfig.Origins.Items[0].S3OriginConfig.OriginAccessIdentity.split('origin-access-identity/cloudfront/')[1]);
14
17
 
15
18
  let config = {
16
19
  "bucket": s3.Location,
@@ -0,0 +1,9 @@
1
+ module.exports.createClient = (client, account, region = 'us-east-1') => {
2
+ delete process.env.AWS_PROFILE;
3
+
4
+ if(account){
5
+ process.env.AWS_PROFILE = account;
6
+ }
7
+
8
+ return new client({ region });
9
+ }
@@ -1,12 +1,9 @@
1
- const { S3Client, CreateBucketCommand, DeleteBucketCommand, PutPublicAccessBlockCommand, PutBucketTaggingCommand, PutBucketPolicyCommand, PutObjectCommand, DeleteObjectCommand } = require("@aws-sdk/client-s3");
1
+ const { S3Client, CreateBucketCommand, DeleteBucketCommand, ListBucketsCommand, PutPublicAccessBlockCommand, PutBucketTaggingCommand, PutBucketPolicyCommand, PutObjectCommand, DeleteObjectCommand } = require("@aws-sdk/client-s3");
2
2
  const { Spinner } = require('../../libs/utilities');
3
-
4
- let region = `us-east-1`;
5
-
6
- const client = new S3Client({ region });
3
+ const { createClient } = require('./misc.js');
7
4
 
8
5
  module.exports.createS3Bucket = async (bucket, account, tags = []) => {
9
- process.env.AWS_PROFILE = account;
6
+ const client = createClient(S3Client, account);
10
7
 
11
8
  let res = await Spinner.prototype.simple(`Creating s3 bucket ${bucket}`, () => {
12
9
  return client.send(
@@ -29,8 +26,20 @@ module.exports.createS3Bucket = async (bucket, account, tags = []) => {
29
26
  return res;
30
27
  }
31
28
 
29
+ module.exports.listS3Buckets = async (account) => {
30
+ const client = createClient(S3Client, account);
31
+
32
+ let res = await Spinner.prototype.simple(`Listing s3 buckets`, () => {
33
+ return client.send(
34
+ new ListBucketsCommand({})
35
+ );
36
+ });
37
+
38
+ return res;
39
+ }
40
+
32
41
  module.exports.removeS3Bucket = async (bucket, account) => {
33
- process.env.AWS_PROFILE = account;
42
+ const client = createClient(S3Client, account);
34
43
 
35
44
  await Spinner.prototype.simple(`Removing s3 bucket ${bucket}`, () => {
36
45
  return client.send(
@@ -40,7 +49,7 @@ module.exports.removeS3Bucket = async (bucket, account) => {
40
49
  }
41
50
 
42
51
  module.exports.setS3BucketPolicy = async (bucket, account, OAI) => {
43
- process.env.AWS_PROFILE = account;
52
+ const client = createClient(S3Client, account);
44
53
 
45
54
  let res = await Spinner.prototype.simple(`Updating s3 bucket policy`, () => {
46
55
  return client.send(
@@ -69,7 +78,7 @@ module.exports.setS3BucketPolicy = async (bucket, account, OAI) => {
69
78
  }
70
79
 
71
80
  module.exports.addFileToS3Bucket = async (bucket, account, filepath, file) => {
72
- process.env.AWS_PROFILE = account;
81
+ const client = createClient(S3Client, account);
73
82
 
74
83
  let res = await Spinner.prototype.simple(`Adding file to s3 bucket`, () => {
75
84
  return client.send(
@@ -85,7 +94,7 @@ module.exports.addFileToS3Bucket = async (bucket, account, filepath, file) => {
85
94
  };
86
95
 
87
96
  module.exports.removeFileToS3Bucket = async (bucket, account, filepath) => {
88
- process.env.AWS_PROFILE = account;
97
+ const client = createClient(S3Client, account);
89
98
 
90
99
  let res = await Spinner.prototype.simple(`Removing file from s3 bucket`, () => {
91
100
  return client.send(
@@ -11,5 +11,5 @@ module.exports = [
11
11
  default: ''
12
12
  });
13
13
  },
14
- argv => execSync(`${_.docker} build ${argv.image} --no-cache`, _.opts)
14
+ argv => execSync(`${_.docker} build --no-cache ${argv.image}`, _.opts)
15
15
  ];
@@ -16,6 +16,15 @@ module.exports = [
16
16
  describe: 'Run with a virtual display',
17
17
  type: 'boolean'
18
18
  });
19
+
20
+ yargs.option('grunt', {
21
+ alias: 'g',
22
+ describe: 'Execute a grunt command',
23
+ type: 'boolean'
24
+ });
19
25
  },
20
- argv => execSync(`${_.docker} ${_.run}c "${argv.d ? 'xvfb-run ' : ''}${argv.command.join(' ')}"`, _.opts)
26
+ argv => {
27
+ const prep = argv.g ? '$grunt ' : ' ';
28
+ execSync(`${_.docker} ${_.run}c "${argv.d ? 'xvfb-run ' : ''}${prep}${argv.command.join(prep)}"`, _.opts)
29
+ }
21
30
  ];
@@ -37,6 +37,9 @@ RUN npm install grunt-cli -g
37
37
  # Install package.json checker
38
38
  RUN npm install check-dependencies -g
39
39
 
40
+ # Install node_modules checker
41
+ RUN npm install are-you-es5 -g
42
+
40
43
  # Install imagemagick
41
44
  RUN apt-get update && apt-get install -y imagemagick
42
45
 
@@ -105,7 +108,7 @@ RUN apt-get update
105
108
 
106
109
  # Specific chrome version
107
110
  # Check available versions here: https://www.ubuntuupdates.org/package/google_chrome/stable/main/base/google-chrome-stable
108
- ARG CHROME_VERSION="87.0.4280.141-1"
111
+ ARG CHROME_VERSION="105.0.5195.102-1"
109
112
  RUN wget --no-verbose -O /tmp/chrome.deb http://dl.google.com/linux/chrome/deb/pool/main/g/google-chrome-stable/google-chrome-stable_${CHROME_VERSION}_amd64.deb
110
113
  RUN apt install -y /tmp/chrome.deb
111
114
 
@@ -185,10 +188,11 @@ npm(){(\n\
185
188
  sed -i \'s/watchTask: true,/watchTask: true,watchOptions: { usePolling: true },port: process.env.PORT || 3000, ui: {port: +process.env.PORT_OPT || 3001},/g\' $PWD/node_modules/@fishawack/core/_Tasks/options/browserSync.js 2>/dev/null || true\n\
186
189
  sed -i \'s/watchTask: true,/watchTask: true,watchOptions: { usePolling: true },port: process.env.PORT || 3000, ui: {port: +process.env.PORT_OPT || 3001},/g\' $PWD/node_modules/@fishawack/config-grunt/_Tasks/options/browserSync.js 2>/dev/null || true\n\
187
190
  echo "Overwrite webdriver browsers to fix them to specific browser versions"\n\
188
- sed -i \'s/exports.config = {.*/exports.config = { seleniumArgs: { drivers: {chrome: { version: "87.0.4280.88" },firefox: { version: "0.28.0" }} },/\' $PWD/node_modules/@fishawack/core/wdio.conf.js 2>/dev/null || true\n\
189
- sed -i \'s/exports.config = {.*/exports.config = { seleniumArgs: { drivers: {chrome: { version: "87.0.4280.88" },firefox: { version: "0.28.0" }} },/\' $PWD/node_modules/@fishawack/config-grunt/wdio.conf.js 2>/dev/null || true\n\
191
+ sed -i \'s/exports.config = {.*/exports.config = { seleniumArgs: { drivers: {chrome: { version: "105.0.5195.52" },firefox: { version: "0.28.0" }} },/\' $PWD/node_modules/@fishawack/core/wdio.conf.js 2>/dev/null || true\n\
192
+ sed -i \'s/exports.config = {.*/exports.config = { seleniumArgs: { drivers: {chrome: { version: "105.0.5195.52" },firefox: { version: "0.28.0" }} },/\' $PWD/node_modules/@fishawack/config-grunt/wdio.conf.js 2>/dev/null || true\n\
193
+ sed -i \'s/87.0.4280.88/105.0.5195.52/\' $PWD/node_modules/@fishawack/core/wdio.conf.js 2>/dev/null || true\n\
190
194
  sed -i \'s/puppeteer.launch({headless: true}).*/puppeteer.launch({headless: true, args: [ "--no-sandbox", "--disable-setuid-sandbox", "--disable-dev-shm-usage" ]}).then(async browser => {/\' $PWD/node_modules/sprinkle/bin/commands/screenshots.js 2>/dev/null || true\n\
191
- npx --no-install selenium-standalone --singleDriverInstall=chrome install --drivers.chrome.version=87.0.4280.88 2>/dev/null || true\n\
195
+ npx --no-install selenium-standalone --singleDriverInstall=chrome install --drivers.chrome.version=105.0.5195.52 2>/dev/null || true\n\
192
196
  npx --no-install selenium-standalone --singleDriverInstall=firefox install --drivers.firefox.version=0.28.0 2>/dev/null || true\n\
193
197
  export OVERRIDE=true\n\
194
198
  else\n\
File without changes
package/core/CHANGELOG.md CHANGED
@@ -1,4 +1,8 @@
1
1
  ## Changelog
2
2
 
3
+ ### 0.2.0 (2022-09-08)
4
+ * [Feature] are-you-es5 dependency now globally installed with npm
5
+ * [Fix] core now points to google-chrome 105 now that 87 is no longer available to download through the image
6
+
3
7
  ### 0.1.0 (2022-05-27)
4
8
  * [Feature] Added aws-cli@2 to core container
package/core/package.json CHANGED
@@ -1,9 +1,10 @@
1
1
  {
2
2
  "name": "core",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "lab-env docker config for the @fishawack/core npm module",
5
5
  "scripts": {
6
- "postversion": "mv ./*/ ./$npm_package_version && docker build ./*/ -t fishawack/core:$npm_package_version -t fishawack/core:latest && docker push fishawack/core:$npm_package_version && docker push fishawack/core:latest && git add . && git commit -m 'Bumped core to $npm_package_version'"
6
+ "preversion": "docker login",
7
+ "postversion": "mv ./*/ ./$npm_package_version && docker build ./*/ -t fishawack/core:$npm_package_version --platform linux/amd64 -t fishawack/core:latest && docker push fishawack/core:$npm_package_version && docker push fishawack/core:latest && git add . && git commit -m 'Bumped core to $npm_package_version'"
7
8
  },
8
9
  "author": "Mike Mellor",
9
10
  "license": "ISC"
@@ -1,3 +1,4 @@
1
+ Mutex posixsem
1
2
  LoadModule proxy_fcgi_module modules/mod_proxy_fcgi.so
2
3
 
3
4
  <VirtualHost *:8080>
@@ -36,7 +36,7 @@ services:
36
36
  build:
37
37
  context: ./php/
38
38
  dockerfile: Dockerfile
39
- image: lab-env/drupal/9/php:0.0.3
39
+ image: lab-env/drupal/9/php:0.0.4
40
40
  init: true
41
41
  working_dir: /app
42
42
  networks:
@@ -1,4 +1,4 @@
1
- FROM chialab/php:7.4-fpm
1
+ FROM chialab/php:8.1-fpm
2
2
 
3
3
  MAINTAINER Mike Mellor
4
4
 
package/globals.js CHANGED
@@ -1,15 +1,19 @@
1
1
  const execSync = require('child_process').execSync;
2
2
  const path = require('path');
3
- const { lstatSync, readdirSync, copyFileSync, existsSync } = require('fs');
3
+ const { lstatSync, readdirSync, copyFileSync, existsSync, readFileSync } = require('fs');
4
4
  const semver = require('semver');
5
5
  const getPort = require('get-port');
6
6
  const utilities = require('./commands/create/libs/utilities');
7
+ const os = require('os');
8
+ const { hideBin } = require('yargs/helpers');
9
+ const args = hideBin(process.argv);
7
10
 
8
11
  process.env.DIRNAME = __dirname;
9
12
 
10
13
  const isDirectory = source => lstatSync(source).isDirectory();
11
14
  const getDirectories = source => readdirSync(source).map(name => path.join(source, name)).filter(isDirectory);
12
15
 
16
+ var config;
13
17
  var repo;
14
18
  var platform;
15
19
  var pkg;
@@ -21,8 +25,24 @@ var exec;
21
25
  var running;
22
26
  var services;
23
27
  var branch;
28
+ var diagnosis = '1.0.0';
24
29
  var opts = {encoding: 'utf8', stdio: 'inherit', shell: '/bin/bash'};
25
30
 
31
+ try{
32
+ config = JSON.parse(readFileSync(`${os.homedir()}/.lab-env`, {encoding: 'utf8'}));
33
+ } catch(e){
34
+ config = {};
35
+ }
36
+
37
+ if(args[0] !== 'diag' && args[0] !== 'diagnose'){
38
+ if(!config.diagnosis || semver.diff(config.diagnosis, diagnosis) === 'major'){
39
+ console.log(`${utilities.colorize(`@fishawack/lab-env`, 'title')} diagnosis is ${utilities.colorize(`outdated`, 'error')}.\n\nRun ${utilities.colorize(`fw diagnose`, 'success')} to reconfigure.`);
40
+ process.exit(1);
41
+ } else if(semver.diff(config.diagnosis, diagnosis) !== null){
42
+ console.log(`${utilities.colorize(`@fishawack/lab-env`, 'title')} diagnosis is ${utilities.colorize(`outdated`, 'warning')}.\n\nRun ${utilities.colorize(`fw diagnose`, 'success')} to reconfigure.`);
43
+ }
44
+ }
45
+
26
46
  try{
27
47
  branch = process.env.BRANCH || process.env.CI_COMMIT_REF_NAME || require('git-branch').sync();
28
48
  } catch(e){
@@ -117,6 +137,8 @@ try{
117
137
  }
118
138
 
119
139
  module.exports = {
140
+ config,
141
+ diagnosis,
120
142
  services,
121
143
  platform,
122
144
  repo,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fishawack/lab-env",
3
- "version": "2.2.0",
3
+ "version": "3.2.0",
4
4
  "description": "Docker manager for FW",
5
5
  "main": "cli.js",
6
6
  "scripts": {
@@ -23,6 +23,7 @@
23
23
  },
24
24
  "dependencies": {
25
25
  "@aws-sdk/client-cloudfront": "^3.141.0",
26
+ "@aws-sdk/client-iam": "^3.150.0",
26
27
  "@aws-sdk/client-s3": "^3.141.0",
27
28
  "axios": "^0.21.4",
28
29
  "chalk": "4.1.0",