From 326161b23d7b44ba606d7019a005cc776c03e8df Mon Sep 17 00:00:00 2001 From: Evan Siroky Date: Mon, 2 Sep 2019 22:59:21 -0700 Subject: [PATCH 01/14] feat(deploy): log deployments to MS Teams --- bin/mastarm-deploy | 39 +++++++++++++++++++++++++++++++++++++++ lib/logger.js | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+) diff --git a/bin/mastarm-deploy b/bin/mastarm-deploy index cc95b1f..37c987a 100755 --- a/bin/mastarm-deploy +++ b/bin/mastarm-deploy @@ -89,6 +89,7 @@ logger .log( `:tada: :confetti_ball: :tada: *deploy ${tag} complete* :tada: :confetti_ball: :tada:` ) + .then(() => logToMsTeams()) .then(() => process.exit(0)) ) .catch(err => @@ -96,6 +97,44 @@ logger .log( `:rotating_light: *${tag} error deploying ${tag} ${err.message || err}*` ) + .then(() => logToMsTeams(err)) .then(() => process.exit(1)) ) ) + +/** + * Sends a card to MS Teams with information about the deployment + * @param {[Error]} error the error, if one occurred. A falsy value indicates + * success + */ +function logToMsTeams (error) { + if (!config.env.MS_TEAMS_WEBHOOK) return Promise.resolve() + + const potentialAction = [{ + '@type': 'OpenUri', + name: `View Commit on Github`, + targets: [ + { + os: 'default', + uri: `${url}/commit/${commit}` + } + ] + }] + const text = `📄 *commit:* ${pkg.name}@${commit.slice(0, 6)}\n + 👤 *deployed by:* ${username.sync()}\n + 🚦 *mastarm:* v${mastarmVersion}\n + ☁️ *cloudfront:* ${cloudfront}\n + 🌱 *env:* ${env}\n + 🗜️ *minify:* ${minify}\n + 📦 *s3bucket:* ${s3bucket}\n + ${error + ? `🚨 🚨 *error deploying ${error.message || error}*` + : `🎉 🎊 🎉 *deploy successful!* 🎉 🎊 🎉`}` + + return logger.notifyMsTeams({ + potentialAction, + text, + title: `${error ? 'Failed to deploy' : 'Successfully deployed'} ${pkg.name}`, + webhook: config.env.MS_TEAMS_WEBHOOK + }) +} diff --git a/lib/logger.js b/lib/logger.js index b939976..6af8f6c 100644 --- a/lib/logger.js +++ b/lib/logger.js @@ -48,3 +48,37 @@ function notifySlack ({ channel, text, webhook }) { return err }) } + +/** + * Send a message to MS Teams using a webhook. This will generate a card + * according to the following schema: + * https://docs.microsoft.com/en-us/outlook/actionable-messages/message-card-reference#openuri-action + * + * @param {Array} potentialAction An array of potential actions on a card. + * @param {String} text The card body text + * @param {String} [themeColor='0072C6'] Card theme color + * @param {String} title Title of the card + * @param {String} webhook Webhook url + */ +module.exports.notifyMsTeams = function notifyMSTeams ({ + potentialAction, + text, + themeColor = '0072C6', + title, + webhook +}) { + return fetch( + webhook, + { + method: 'POST', + body: JSON.stringify({ + '@context': 'https://schema.org/extensions', + '@type': 'MessageCard', + themeColor, + title, + text, + potentialAction + }) + } + ) +} From 165dea0dee11079d4ee5a15523378a4768e46298 Mon Sep 17 00:00:00 2001 From: Evan Siroky Date: Tue, 3 Sep 2019 11:13:39 -0700 Subject: [PATCH 02/14] docs(deploy): add documentation for adding MS Teams webhook --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index b89540f..71dc242 100644 --- a/README.md +++ b/README.md @@ -155,6 +155,14 @@ SLACK_CHANNEL: '#devops' SLACK_WEBHOOK: https://hooks.slack.com/services/fake-code ``` +#### MS Teams Notifications + +To enable an MS Teams notification upon the completion (successful or not) of the deploy process, create a [MS Teams Webhook](https://docs.microsoft.com/en-us/microsoftteams/platform/concepts/connectors/connectors-using#setting-up-a-custom-incoming-webhook) and add the incoming webhook url as the `MS_TEAMS_WEBHOOK` key/value to your `env.yml`. + +``` +MS_TEAMS_WEBHOOK: https://outlook.office.com/webhook/123...abc +``` + ### `flow` Run [Flow](https://flow.org/). Must have a `.flowconfig` in the current working directory and a `// @flow` annotation at the top of each file you want to check. See the Flow website for documentation. From 4259d66b5bd40c9180e9947f2ce1c1cee1a73265 Mon Sep 17 00:00:00 2001 From: Evan Siroky Date: Wed, 4 Sep 2019 01:06:16 -0700 Subject: [PATCH 03/14] feat(deploy): add detailed checks and logging of configuration If deploying using a folder from the configurations repo, numerous checks and more logging will be performed given information about the configurations --- bin/mastarm-deploy | 226 +++++++++++++++++++++++++++++++-------------- package.json | 3 + yarn.lock | 119 ++++++++++++++++-------- 3 files changed, 241 insertions(+), 107 deletions(-) diff --git a/bin/mastarm-deploy b/bin/mastarm-deploy index 37c987a..24fc3bc 100755 --- a/bin/mastarm-deploy +++ b/bin/mastarm-deploy @@ -3,11 +3,14 @@ const path = require('path') const commander = require('commander') +const execa = require('execa') +const origin = require('git-remote-origin-url') +const repoInfo = require('git-repo-info') const commit = require('this-commit')() const username = require('username') const build = require('../lib/build') -const {readFile} = require('../lib/fs-promise') +const {readFile, writeFile} = require('../lib/fs-promise') const loadConfig = require('../lib/load-config') const logger = require('../lib/logger') const pkg = require('../lib/pkg') @@ -28,86 +31,157 @@ commander .option('--s3bucket', 'S3 Bucket to push to.') .parse(process.argv) -const url = pkg.repository.url.replace('.git', '') -const tag = `<${url}/commit/${commit}|${pkg.name}@${commit.slice(0, 6)}>` -const config = loadConfig(process.cwd(), commander.config, commander.env) -const get = util.makeGetFn([commander, config.settings]) +// each of these variables are also used in the logToMsTeams function and +// these need to be defined after potentially decoding a sops-encoded file +let cloudfront, config, env, minify, s3bucket, tag, url -if (config.env.SLACK_WEBHOOK && config.env.SLACK_WEBHOOK.length > 0) { - logger.logToSlack({ - channel: config.env.SLACK_CHANNEL || '#devops', - webhook: config.env.SLACK_WEBHOOK - }) -} +async function deploy () { + // get information about the config directory being used + const repoUrl = await origin(commander.config) + let configCommit, configRemoteUrl + const configRepoRoot = repoInfo(commander.config).root + const configDir = path + .resolve(commander.config) + .replace(configRepoRoot, '') -const files = util.parseEntries([...commander.args, ...(get('entries') || [])]) -util.assertEntriesExist(files) -const sourceFiles = files.map(f => f[0]) -const outfiles = [...files.map(f => f[1]), ...files.map(f => `${f[1]}.map`)] - -const env = get('env') || 'development' -const minify = get('minify') -const buildOpts = { - config, - env, - files, - minify -} -const cloudfront = get('cloudfront') -const s3bucket = get('s3bucket') + // check if the config directory being used is a configurations repo + if (repoUrl.endsWith('/configurations.git')) { + // run some extra checks to make sure configurations repo is up to date + // modified from https://stackoverflow.com/a/3278427/269834 + configRemoteUrl = repoUrl.replace('.git', '') + const { stdout: local } = await execa('git', ['-C', configRepoRoot, 'rev-parse', '@']) + const { stdout: remote } = await execa('git', ['-C', configRepoRoot, 'rev-parse', '@{u}']) + const { stdout: base } = await execa('git', ['-C', configRepoRoot, 'merge-base', '@', '@{u}']) + let configurationsOk = false + if (local === remote) { + // Up-to-date + console.log('Configurations up-to-date') + configurationsOk = true + } else if (local === base) { + console.error('Configurations out of sync: Need to pull') + } else if (remote === base) { + console.error('Configurations out of sync: Need to push') + } else { + console.error('Configurations out of sync: Diverged') + } + + // make sure there are no changes to the configurations + const { stdout: status } = await execa( + 'git', + [ + '-C', + configRepoRoot, + 'status', + '-s' + ] + ) + if (status === '') { + console.log('No changes to configurations repo') + } else { + console.error('Configurations out of sync: local changes exist that are not yet committed') + configurationsOk = false + } + + if (!configurationsOk) process.exit(1) + + configCommit = local + + // decrypt env file using sops to make sure old file is overwritten with + // data from encoded sops file + const configPath = path.resolve(commander.config) + console.log('decrypting env file with sops') + const {stdout} = await execa( + 'sops', + [ + '-d', + path.join(configPath, 'env.enc.yml') + ] + ) + await writeFile(path.join(configPath, 'env.yml'), stdout) + // at this point, we can be certain that the local configurations repo + // directory matches what has been committed and pushed to the remote repo + } + + url = pkg.repository.url.replace('.git', '') + tag = `<${url}/commit/${commit}|${pkg.name}@${commit.slice(0, 6)}>` + config = loadConfig(process.cwd(), commander.config, commander.env) + const get = util.makeGetFn([commander, config.settings]) + + if (config.env.SLACK_WEBHOOK && config.env.SLACK_WEBHOOK.length > 0) { + logger.logToSlack({ + channel: config.env.SLACK_CHANNEL || '#devops', + webhook: config.env.SLACK_WEBHOOK + }) + } + + const files = util.parseEntries([...commander.args, ...(get('entries') || [])]) + util.assertEntriesExist(files) + const sourceFiles = files.map(f => f[0]) + const outfiles = [...files.map(f => f[1]), ...files.map(f => `${f[1]}.map`)] -const pushToS3 = createPushToS3({ - cloudfront, - s3bucket -}) + env = get('env') || 'development' + minify = get('minify') + const buildOpts = { + config, + env, + files, + minify + } + cloudfront = get('cloudfront') + s3bucket = get('s3bucket') -logger - .log( + const pushToS3 = createPushToS3({ + cloudfront, + s3bucket + }) + + await logger.log( `:construction: *deploying: ${tag} by <@${username.sync()}>* -:vertical_traffic_light: *mastarm:* v${mastarmVersion} -:cloud: *cloudfront:* ${cloudfront} -:hash: *commit:* ${commit} -:seedling: *env:* ${env} -:compression: *minify:* ${minify} -:package: *s3bucket:* ${s3bucket} -:hammer_and_wrench: *building:* ${sourceFiles.join(', ')}` + :vertical_traffic_light: *mastarm:* v${mastarmVersion} + :cloud: *cloudfront:* ${cloudfront} + :hash: *commit:* ${commit} + :seedling: *env:* ${env} + :compression: *minify:* ${minify} + :package: *s3bucket:* ${s3bucket} + :hammer_and_wrench: *building:* ${sourceFiles.join(', ')}` ) - .then(() => - build(buildOpts) - .then(() => - logger.log(`:rocket: *uploading:* ${sourceFiles.length * 2} file(s)`) - ) - .then(() => - Promise.all( - outfiles.map(outfile => - readFile(outfile).then(body => pushToS3({body, outfile})) - ) - ) - ) - .then(() => - logger - .log( - `:tada: :confetti_ball: :tada: *deploy ${tag} complete* :tada: :confetti_ball: :tada:` - ) - .then(() => logToMsTeams()) - .then(() => process.exit(0)) - ) - .catch(err => - logger - .log( - `:rotating_light: *${tag} error deploying ${tag} ${err.message || err}*` - ) - .then(() => logToMsTeams(err)) - .then(() => process.exit(1)) + + try { + await build(buildOpts) + await logger.log(`:rocket: *uploading:* ${sourceFiles.length * 2} file(s)`) + await Promise.all( + outfiles.map(outfile => + readFile(outfile).then(body => pushToS3({body, outfile})) ) - ) + ) + await logger.log( + `:tada: :confetti_ball: :tada: *deploy ${tag} complete* :tada: :confetti_ball: :tada:` + ) + await logToMsTeams({ configCommit, configDir, configRemoteUrl }) + process.exit(0) + } catch (error) { + await logger.log( + `:rotating_light: *${tag} error deploying ${tag} ${error.message || error}*` + ) + await logToMsTeams({ configCommit, configDir, configRemoteUrl, error }) + process.exit(1) + } +} + +deploy() /** * Sends a card to MS Teams with information about the deployment + * @param {[string]} configCommit hash of the commit in the configurations + * repo (if it exists) + * @param {[string]} configDir partial path to specific config directory used + * to deploy + * @param {[string]} configRemoteUrl base url for the configurations repo + * (if it exists) * @param {[Error]} error the error, if one occurred. A falsy value indicates * success */ -function logToMsTeams (error) { +function logToMsTeams ({ configCommit, configDir, configRemoteUrl, error }) { if (!config.env.MS_TEAMS_WEBHOOK) return Promise.resolve() const potentialAction = [{ @@ -120,8 +194,24 @@ function logToMsTeams (error) { } ] }] + if (configCommit && configRemoteUrl) { + potentialAction.push({ + '@type': 'OpenUri', + name: `View Config Commit on Github`, + targets: [ + { + os: 'default', + uri: `${configRemoteUrl}/tree/${configCommit}/${configDir}` + } + ] + }) + } const text = `📄 *commit:* ${pkg.name}@${commit.slice(0, 6)}\n 👤 *deployed by:* ${username.sync()}\n + ${configCommit + ? `🎛️ *config:* configurations@${configCommit.slice(0, 6)}\n + 📂 *config folder:* ${configDir}\n` // improper indenting here needed to properly format on MS Teams + : '🎛️ *config:* unknown configuration data!\n'} 🚦 *mastarm:* v${mastarmVersion}\n ☁️ *cloudfront:* ${cloudfront}\n 🌱 *env:* ${env}\n diff --git a/package.json b/package.json index b5c5389..27931bc 100644 --- a/package.json +++ b/package.json @@ -84,9 +84,12 @@ "eslint-plugin-promise": "^4.0.1", "eslint-plugin-react": "^7.12.4", "eslint-plugin-standard": "^4.0.0", + "execa": "^2.0.4", "exorcist": "^1.0.1", "flow-bin": "0.84.0", "flow-runtime": "^0.17.0", + "git-remote-origin-url": "^3.0.0", + "git-repo-info": "^2.1.0", "glob": "^7.1.3", "isomorphic-fetch": "^2.2.1", "jest": "^24.1.0", diff --git a/yarn.lock b/yarn.lock index 85370a2..be1b9b6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3137,7 +3137,7 @@ debug@^4.0.0, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1: dependencies: ms "^2.1.1" -debuglog@*, debuglog@^1.0.1: +debuglog@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492" integrity sha1-qiT/uaw9+aI1GDfPstJ5NgzXhJI= @@ -3660,9 +3660,9 @@ eslint-plugin-import@^2.16.0: resolve "^1.11.0" eslint-plugin-jest@^22.3.0: - version "22.14.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-22.14.0.tgz#f9b09837f665cfe360b55c08866904255294cc16" - integrity sha512-Xtc9ZTtxdYFC7vu0PHxDeQ9lOMQ8gjwMmSQq/ni83TdflgL3eVh/qg3t99I7gcDxpeXfcp+lHu9C0vN3QAhATw== + version "22.16.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-22.16.0.tgz#30c4e0e9dc331beb2e7369b70dd1363690c1ce05" + integrity sha512-eBtSCDhO1k7g3sULX/fuRK+upFQ7s548rrBtxDyM1fSoY7dTWp/wICjrJcDZKVsW7tsFfH22SG+ZaxG5BZodIg== dependencies: "@typescript-eslint/experimental-utils" "^1.13.0" @@ -3914,6 +3914,21 @@ execa@^1.0.0: signal-exit "^3.0.0" strip-eof "^1.0.0" +execa@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/execa/-/execa-2.0.4.tgz#2f5cc589c81db316628627004ea4e37b93391d8e" + integrity sha512-VcQfhuGD51vQUQtKIq2fjGDLDbL6N1DTQVpYzxZ7LPIXw3HqTuIz6uxRmpV1qf8i31LHf2kjiaGI+GdHwRgbnQ== + dependencies: + cross-spawn "^6.0.5" + get-stream "^5.0.0" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^3.0.0" + onetime "^5.1.0" + p-finally "^2.0.0" + signal-exit "^3.0.2" + strip-final-newline "^2.0.0" + exit@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" @@ -4445,6 +4460,25 @@ git-log-parser@^1.2.0: through2 "~2.0.0" traverse "~0.6.6" +git-remote-origin-url@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/git-remote-origin-url/-/git-remote-origin-url-3.0.0.tgz#7561ea24bc16e89b39f96d4302fffb0cd990a1d8" + integrity sha512-KXFRTWj4F39zzmeTo4DGDGiZ9dPDsh+HPZiPRQgW0OpnhcmEPSdf3AgLzLqJuuo8t8UGSKKcvK8nmnejWuq3UQ== + dependencies: + gitconfiglocal "^2.1.0" + +git-repo-info@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/git-repo-info/-/git-repo-info-2.1.0.tgz#13d1f753c75bc2994432e65a71e35377ff563813" + integrity sha512-+kigfDB7j3W80f74BoOUX+lKOmf4pR3/i2Ww6baKTCPe2hD4FRdjhV3s4P5Dy0Tak1uY1891QhKoYNtnyX2VvA== + +gitconfiglocal@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/gitconfiglocal/-/gitconfiglocal-2.1.0.tgz#07c28685c55cc5338b27b5acbcfe34aeb92e43d1" + integrity sha512-qoerOEliJn3z+Zyn1HW2F6eoYJqKwS6MgC9cztTLUB/xLWX8gD/6T60pKn4+t/d6tP7JlybI7Z3z+I572CR/Vg== + dependencies: + ini "^1.3.2" + glob-parent@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" @@ -4865,7 +4899,7 @@ import-local@^2.0.0: pkg-dir "^3.0.0" resolve-cwd "^2.0.0" -imurmurhash@*, imurmurhash@^0.1.4: +imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= @@ -4918,7 +4952,7 @@ inherits@2.0.3: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= -ini@^1.3.4, ini@^1.3.5, ini@~1.3.0: +ini@^1.3.2, ini@^1.3.4, ini@^1.3.5, ini@~1.3.0: version "1.3.5" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== @@ -5327,6 +5361,11 @@ is-stream@^1.0.0, is-stream@^1.0.1, is-stream@^1.1.0, is-stream@~1.1.0: resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= +is-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.0.tgz#bde9c32680d6fae04129d6ac9d921ce7815f78e3" + integrity sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw== + is-subset@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/is-subset/-/is-subset-0.1.1.tgz#8a59117d932de1de00f245fcdd39ce43f1e939a6" @@ -6261,11 +6300,6 @@ lockfile@^1.0.4: dependencies: signal-exit "^3.0.2" -lodash._baseindexof@*: - version "3.1.0" - resolved "https://registry.yarnpkg.com/lodash._baseindexof/-/lodash._baseindexof-3.1.0.tgz#fe52b53a1c6761e42618d654e4a25789ed61822c" - integrity sha1-/lK1OhxnYeQmGNZU5KJXie1hgiw= - lodash._baseuniq@~4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash._baseuniq/-/lodash._baseuniq-4.6.0.tgz#0ebb44e456814af7905c6212fa2c9b2d51b841e8" @@ -6274,33 +6308,11 @@ lodash._baseuniq@~4.6.0: lodash._createset "~4.0.0" lodash._root "~3.0.0" -lodash._bindcallback@*: - version "3.0.1" - resolved "https://registry.yarnpkg.com/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz#e531c27644cf8b57a99e17ed95b35c748789392e" - integrity sha1-5THCdkTPi1epnhftlbNcdIeJOS4= - -lodash._cacheindexof@*: - version "3.0.2" - resolved "https://registry.yarnpkg.com/lodash._cacheindexof/-/lodash._cacheindexof-3.0.2.tgz#3dc69ac82498d2ee5e3ce56091bafd2adc7bde92" - integrity sha1-PcaayCSY0u5ePOVgkbr9Ktx73pI= - -lodash._createcache@*: - version "3.1.2" - resolved "https://registry.yarnpkg.com/lodash._createcache/-/lodash._createcache-3.1.2.tgz#56d6a064017625e79ebca6b8018e17440bdcf093" - integrity sha1-VtagZAF2JeeevKa4AY4XRAvc8JM= - dependencies: - lodash._getnative "^3.0.0" - lodash._createset@~4.0.0: version "4.0.3" resolved "https://registry.yarnpkg.com/lodash._createset/-/lodash._createset-4.0.3.tgz#0f4659fbb09d75194fa9e2b88a6644d363c9fe26" integrity sha1-D0ZZ+7CddRlPqeK4imZE02PJ/iY= -lodash._getnative@*, lodash._getnative@^3.0.0: - version "3.9.1" - resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5" - integrity sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U= - lodash._reinterpolate@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" @@ -6366,11 +6378,6 @@ lodash.merge@^4.6.0: resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== -lodash.restparam@*: - version "3.6.1" - resolved "https://registry.yarnpkg.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805" - integrity sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU= - lodash.set@^4.3.2: version "4.3.2" resolved "https://registry.yarnpkg.com/lodash.set/-/lodash.set-4.3.2.tgz#d8757b1da807dde24816b0d6a84bea1a76230b23" @@ -6676,6 +6683,11 @@ merge-stream@^1.0.1: dependencies: readable-stream "^2.0.1" +merge-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== + merge2@^1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.2.3.tgz#7ee99dbd69bb6481689253f018488a1b902b0ed5" @@ -6774,7 +6786,7 @@ mimic-fn@^1.0.0: resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== -mimic-fn@^2.0.0: +mimic-fn@^2.0.0, mimic-fn@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== @@ -7233,6 +7245,13 @@ npm-run-path@^2.0.0: dependencies: path-key "^2.0.0" +npm-run-path@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-3.1.0.tgz#7f91be317f6a466efed3c9f2980ad8a4ee8b0fa5" + integrity sha512-Dbl4A/VfiVGLgQv29URL9xshU8XDY1GeLy+fsaZ1AA8JDSfjvr5P5+pzRbWqRSBxk6/DW7MIh8lTM/PaGnP2kg== + dependencies: + path-key "^3.0.0" + npm-user-validate@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/npm-user-validate/-/npm-user-validate-1.0.0.tgz#8ceca0f5cea04d4e93519ef72d0557a75122e951" @@ -7515,6 +7534,13 @@ onetime@^2.0.0: dependencies: mimic-fn "^1.0.0" +onetime@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.0.tgz#fff0f3c91617fe62bb50189636e99ac8a6df7be5" + integrity sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q== + dependencies: + mimic-fn "^2.1.0" + opener@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.1.tgz#6d2f0e77f1a0af0032aca716c2c1fbb8e7e8abed" @@ -7632,6 +7658,11 @@ p-finally@^1.0.0: resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= +p-finally@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-2.0.1.tgz#bd6fcaa9c559a096b680806f4d657b3f0f240561" + integrity sha512-vpm09aKwq6H9phqRQzecoDpD8TmVyGw70qmWlyq5onxY7tqyTTFVvxMykxQSQKILBSFlbXpypIw2T1Ml7+DDtw== + p-is-promise@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-2.1.0.tgz#918cebaea248a62cf7ffab8e3bca8c5f882fc42e" @@ -7892,6 +7923,11 @@ path-key@^2.0.0, path-key@^2.0.1: resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= +path-key@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.0.tgz#99a10d870a803bdd5ee6f0470e58dfcd2f9a54d3" + integrity sha512-8cChqz0RP6SHJkMt48FW0A7+qUOn+OsnOsVtzI59tZ8m+5bCSk7hzwET0pulwOM2YMn9J1efb07KB9l9f30SGg== + path-parse@^1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" @@ -10205,6 +10241,11 @@ strip-eof@^1.0.0: resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= +strip-final-newline@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" + integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== + strip-indent@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-2.0.0.tgz#5ef8db295d01e6ed6cbf7aab96998d7822527b68" From 07b4ee01ba06e8eeb11922e9eb997b6a6bfcbe2b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 5 Sep 2019 18:57:17 +0000 Subject: [PATCH 04/14] build(deps): bump eslint-utils from 1.4.0 to 1.4.2 Bumps [eslint-utils](https://github.com/mysticatea/eslint-utils) from 1.4.0 to 1.4.2. - [Release notes](https://github.com/mysticatea/eslint-utils/releases) - [Commits](https://github.com/mysticatea/eslint-utils/compare/v1.4.0...v1.4.2) Signed-off-by: dependabot[bot] --- yarn.lock | 48 ++++++++---------------------------------------- 1 file changed, 8 insertions(+), 40 deletions(-) diff --git a/yarn.lock b/yarn.lock index 85370a2..eb536b1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3137,7 +3137,7 @@ debug@^4.0.0, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1: dependencies: ms "^2.1.1" -debuglog@*, debuglog@^1.0.1: +debuglog@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492" integrity sha1-qiT/uaw9+aI1GDfPstJ5NgzXhJI= @@ -3743,16 +3743,16 @@ eslint-scope@^4.0.0, eslint-scope@^4.0.3: estraverse "^4.1.1" eslint-utils@^1.3.0, eslint-utils@^1.3.1: - version "1.4.0" - resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.0.tgz#e2c3c8dba768425f897cf0f9e51fe2e241485d4c" - integrity sha512-7ehnzPaP5IIEh1r1tkjuIrxqhNkzUJa9z3R92tLJdZIVdWaczEhr3EbhGtsMrVxi1KeR8qA7Off6SWc5WNQqyQ== + version "1.4.2" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.2.tgz#166a5180ef6ab7eb462f162fd0e6f2463d7309ab" + integrity sha512-eAZS2sEUMlIeCjBeubdj45dmBHQwPHWyBcT1VSYB7o9x9WRRqKxyUoiXlRjyAwzN7YEzHJlYg0NmzDRWx6GP4Q== dependencies: eslint-visitor-keys "^1.0.0" eslint-visitor-keys@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#3f3180fb2e291017716acb4c9d6d5b5c34a6a81d" - integrity sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ== + version "1.1.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2" + integrity sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A== eslint@^5.0.0, eslint@^5.15.1: version "5.16.0" @@ -4865,7 +4865,7 @@ import-local@^2.0.0: pkg-dir "^3.0.0" resolve-cwd "^2.0.0" -imurmurhash@*, imurmurhash@^0.1.4: +imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= @@ -6261,11 +6261,6 @@ lockfile@^1.0.4: dependencies: signal-exit "^3.0.2" -lodash._baseindexof@*: - version "3.1.0" - resolved "https://registry.yarnpkg.com/lodash._baseindexof/-/lodash._baseindexof-3.1.0.tgz#fe52b53a1c6761e42618d654e4a25789ed61822c" - integrity sha1-/lK1OhxnYeQmGNZU5KJXie1hgiw= - lodash._baseuniq@~4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash._baseuniq/-/lodash._baseuniq-4.6.0.tgz#0ebb44e456814af7905c6212fa2c9b2d51b841e8" @@ -6274,33 +6269,11 @@ lodash._baseuniq@~4.6.0: lodash._createset "~4.0.0" lodash._root "~3.0.0" -lodash._bindcallback@*: - version "3.0.1" - resolved "https://registry.yarnpkg.com/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz#e531c27644cf8b57a99e17ed95b35c748789392e" - integrity sha1-5THCdkTPi1epnhftlbNcdIeJOS4= - -lodash._cacheindexof@*: - version "3.0.2" - resolved "https://registry.yarnpkg.com/lodash._cacheindexof/-/lodash._cacheindexof-3.0.2.tgz#3dc69ac82498d2ee5e3ce56091bafd2adc7bde92" - integrity sha1-PcaayCSY0u5ePOVgkbr9Ktx73pI= - -lodash._createcache@*: - version "3.1.2" - resolved "https://registry.yarnpkg.com/lodash._createcache/-/lodash._createcache-3.1.2.tgz#56d6a064017625e79ebca6b8018e17440bdcf093" - integrity sha1-VtagZAF2JeeevKa4AY4XRAvc8JM= - dependencies: - lodash._getnative "^3.0.0" - lodash._createset@~4.0.0: version "4.0.3" resolved "https://registry.yarnpkg.com/lodash._createset/-/lodash._createset-4.0.3.tgz#0f4659fbb09d75194fa9e2b88a6644d363c9fe26" integrity sha1-D0ZZ+7CddRlPqeK4imZE02PJ/iY= -lodash._getnative@*, lodash._getnative@^3.0.0: - version "3.9.1" - resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5" - integrity sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U= - lodash._reinterpolate@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" @@ -6366,11 +6339,6 @@ lodash.merge@^4.6.0: resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== -lodash.restparam@*: - version "3.6.1" - resolved "https://registry.yarnpkg.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805" - integrity sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU= - lodash.set@^4.3.2: version "4.3.2" resolved "https://registry.yarnpkg.com/lodash.set/-/lodash.set-4.3.2.tgz#d8757b1da807dde24816b0d6a84bea1a76230b23" From 446b520a261aa970f893d5649d5652088c68d8e1 Mon Sep 17 00:00:00 2001 From: Evan Siroky Date: Sun, 8 Sep 2019 14:30:23 -0700 Subject: [PATCH 05/14] feat(jest): allow specifying custom config to jest --- README.md | 24 ++++++++++++++---------- bin/mastarm-test | 4 ++++ lib/jest.js | 10 ++++++++++ 3 files changed, 28 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 71dc242..96796f3 100644 --- a/README.md +++ b/README.md @@ -218,16 +218,20 @@ Run tests using Jest Options: - -h, --help output usage information - -u, --update-snapshots Force update of snapshots. USE WITH CAUTION. - --coverage Run Jest with coverage reporting - --coverage-paths Extra paths to collect code coverage from - --jest-cli-args Extra arguments to pass directly to the Jest Cli. Make sure to encapsulate all extra arguments in quote - --no-cache Run Jest without cache (defaults to using cache) - --run-in-band Run all tests serially in the current process - --setup-files Setup files to run before each test - --test-environment Jest test environment to use (Jest default is jsdom) - --test-path-ignore-patterns File patterns to ignore when scanning for test files +-c, --config Path to configuration files. (default: path.join(process.cwd() + '/configurations/default')) +-e, --env Environment to use. +-u, --update-snapshots Force update of snapshots. USE WITH CAUTION. +--coverage Run Jest with coverage reporting +--coverage-paths Extra paths to collect code coverage from +--customConfigFile Override the Jest config with the values found in a file path relative to the current working directory +--force-exit Force Jest to exit after all tests have completed running. +--jest-cli-args Extra arguments to pass directly to the Jest Cli. Make sure to encapsulate all extra arguments in quotes +--no-cache Run Jest without cache (defaults to using cache) +--run-in-band Run all tests serially in the current process +--setup-files Setup files to run before each test +--test-environment Jest test environment to use (Jest default is jsdom) +--test-path-ignore-patterns File patterns to ignore when scanning for test files +-h, --help output usage information ``` diff --git a/bin/mastarm-test b/bin/mastarm-test index 5d09ba4..5d134fb 100755 --- a/bin/mastarm-test +++ b/bin/mastarm-test @@ -25,6 +25,10 @@ commander '--coverage-paths ', 'Extra paths to collect code coverage from' ) + .option( + '--custom-config-file ', + 'Override the Jest config with the values found in a file path relative to the current working directory' + ) .option('--force-exit', 'Force Jest to exit after all tests have completed running.') .option( '--jest-cli-args ', diff --git a/lib/jest.js b/lib/jest.js index 73184be..ed4436a 100644 --- a/lib/jest.js +++ b/lib/jest.js @@ -51,6 +51,16 @@ module.exports.generateTestConfig = (patterns, options) => { }) } + // override config with the values found in a specified file + if (options.customConfigFile) { + const customConfig = require( + path.resolve(process.cwd(), options.customConfigFile) + ) + Object.keys(customConfig).forEach(key => { + jestConfig[key] = customConfig[key] + }) + } + // jest cli params let jestArguments = [] From 35c5b6625c8231f1e4c64df11ef0c6452b48a8b5 Mon Sep 17 00:00:00 2001 From: Evan Siroky Date: Sun, 8 Sep 2019 14:46:14 -0700 Subject: [PATCH 06/14] test(jest): add custom config file to test of jest --- __tests__/lib/__snapshots__/jest.js.snap | 1 + __tests__/lib/jest.js | 1 + __tests__/lib/mock-jest-config.json | 1 + 3 files changed, 3 insertions(+) create mode 100644 __tests__/lib/mock-jest-config.json diff --git a/__tests__/lib/__snapshots__/jest.js.snap b/__tests__/lib/__snapshots__/jest.js.snap index ec018a8..d48fb6a 100644 --- a/__tests__/lib/__snapshots__/jest.js.snap +++ b/__tests__/lib/__snapshots__/jest.js.snap @@ -13,6 +13,7 @@ Array [ "src", "another-folder", ], + "coverage": true, "coverageDirectory": "coverage", "moduleFileExtensions": Array [ "js", diff --git a/__tests__/lib/jest.js b/__tests__/lib/jest.js index dba26b8..7ae5464 100644 --- a/__tests__/lib/jest.js +++ b/__tests__/lib/jest.js @@ -9,6 +9,7 @@ describe('jest.js', () => { const cfg = jestUtils.generateTestConfig(['these', 'files', 'only'], { cache: false, coveragePaths: 'bin src another-folder', + customConfigFile: '__tests__/lib/mock-jest-config.json', runInBand: true, setupFiles: 'beforeTestsSetup.js', testEnvironment: 'node', diff --git a/__tests__/lib/mock-jest-config.json b/__tests__/lib/mock-jest-config.json new file mode 100644 index 0000000..ea6d5cb --- /dev/null +++ b/__tests__/lib/mock-jest-config.json @@ -0,0 +1 @@ +{ "coverage": true } From 4f4328e0b5b2411d0c548ed55c52c19082d130a1 Mon Sep 17 00:00:00 2001 From: Evan Siroky Date: Wed, 11 Sep 2019 14:48:26 -0700 Subject: [PATCH 07/14] docs(jest): improve documentation of mastarm test --- README.md | 27 +++++++++++++++++-- __tests__/lib/jest.js | 2 +- .../mocks}/mock-jest-config.json | 0 3 files changed, 26 insertions(+), 3 deletions(-) rename __tests__/{lib => test-utils/mocks}/mock-jest-config.json (100%) diff --git a/README.md b/README.md index 96796f3..f2d0650 100644 --- a/README.md +++ b/README.md @@ -207,7 +207,7 @@ $ mastarm prepublish lib:build ### `test` -Run the [Jest](http://facebook.github.io/jest/) test runner on your project. By default, mastarm will run Jest and generate coverage reports on all .js files in the `lib` folder of your project. The `patterns` argument will make Jest run only tests whose filename match the provided pattern. +Run the [Jest](http://facebook.github.io/jest/) test runner on your project. ```shell $ mastarm test @@ -223,7 +223,7 @@ Options: -u, --update-snapshots Force update of snapshots. USE WITH CAUTION. --coverage Run Jest with coverage reporting --coverage-paths Extra paths to collect code coverage from ---customConfigFile Override the Jest config with the values found in a file path relative to the current working directory +--custom-config-file Override the Jest config with the values found in a file path relative to the current working directory --force-exit Force Jest to exit after all tests have completed running. --jest-cli-args Extra arguments to pass directly to the Jest Cli. Make sure to encapsulate all extra arguments in quotes --no-cache Run Jest without cache (defaults to using cache) @@ -235,6 +235,29 @@ Options: ``` +By default, mastarm will run Jest with most of the defaults in place. The defaults that mastarm adds include: + +- some transforms needed to read certain .js files and also YAML files. +- ignoring the test path directory `__tests__/test-utils` +- setting the [testURL](https://jestjs.io/docs/en/configuration#testurl-string) to `http://localhost:9966` +- turning on [notifications](https://jestjs.io/docs/en/configuration#notify-boolean) of test completion + +If the `coverage` flag is set to true, mastarm will automatically generate coverage reports of all .js files in the `lib` folder and will save the reports to the `coverage` folder. + +The `patterns` argument will make Jest run only tests whose filename match the provided pattern. + +There are two ways to override the [Jest config](https://jestjs.io/docs/en/configuration). The first is by adding a `jest` object to the package.json of the project. The second is by sending over a custom config file (either .json or .js) via the `--custom-config-file` option. Ex: + +```shell +matarm test --custom-config-file __tests__/test-utils/mocks/mock-jest-config.json +``` + +It is also possible to override any [Jest CLI Options](https://jestjs.io/docs/en/cli) by setting the `--jest-cli-args` flag. Ex: + +```shell +mastarm test --jest-cli-args "--json --outputFile e2e-test-results/results.json" +``` + ### `lint-messages` ```shell diff --git a/__tests__/lib/jest.js b/__tests__/lib/jest.js index 7ae5464..740dfd8 100644 --- a/__tests__/lib/jest.js +++ b/__tests__/lib/jest.js @@ -9,7 +9,7 @@ describe('jest.js', () => { const cfg = jestUtils.generateTestConfig(['these', 'files', 'only'], { cache: false, coveragePaths: 'bin src another-folder', - customConfigFile: '__tests__/lib/mock-jest-config.json', + customConfigFile: '__tests__/test-utils/mocks/mock-jest-config.json', runInBand: true, setupFiles: 'beforeTestsSetup.js', testEnvironment: 'node', diff --git a/__tests__/lib/mock-jest-config.json b/__tests__/test-utils/mocks/mock-jest-config.json similarity index 100% rename from __tests__/lib/mock-jest-config.json rename to __tests__/test-utils/mocks/mock-jest-config.json From 58df413d5d032f62b023d433cd0f62258cbc4410 Mon Sep 17 00:00:00 2001 From: Landon Reed Date: Mon, 16 Sep 2019 13:05:10 -0400 Subject: [PATCH 08/14] feat(a11y): re-enable jsx-a11y for linting fix #288 --- lib/eslintrc.json | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/eslintrc.json b/lib/eslintrc.json index c83eead..1a63517 100644 --- a/lib/eslintrc.json +++ b/lib/eslintrc.json @@ -8,13 +8,15 @@ "standard", "standard-jsx", "plugin:flowtype/recommended", - "plugin:jest/recommended" + "plugin:jest/recommended", + "plugin:jsx-a11y/strict" ], "parser": "babel-eslint", "plugins": [ "flowtype", "import", - "jest" + "jest", + "jsx-a11y" ], "rules": { "complexity": ["warn", 12], From 9e59283124b5183ecea7acc5f54930bb29f3d4d9 Mon Sep 17 00:00:00 2001 From: Evan Siroky Date: Mon, 16 Sep 2019 23:31:51 -0700 Subject: [PATCH 09/14] test(jest): correct snapshot to use actual jest config value --- __tests__/lib/__snapshots__/jest.js.snap | 2 +- __tests__/test-utils/mocks/mock-jest-config.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/__tests__/lib/__snapshots__/jest.js.snap b/__tests__/lib/__snapshots__/jest.js.snap index d48fb6a..0fe5d71 100644 --- a/__tests__/lib/__snapshots__/jest.js.snap +++ b/__tests__/lib/__snapshots__/jest.js.snap @@ -7,13 +7,13 @@ Array [ "--runInBand", "--config", Object { + "collectCoverage": true, "collectCoverageFrom": Array [ "lib/**/*.js", "bin", "src", "another-folder", ], - "coverage": true, "coverageDirectory": "coverage", "moduleFileExtensions": Array [ "js", diff --git a/__tests__/test-utils/mocks/mock-jest-config.json b/__tests__/test-utils/mocks/mock-jest-config.json index ea6d5cb..d210034 100644 --- a/__tests__/test-utils/mocks/mock-jest-config.json +++ b/__tests__/test-utils/mocks/mock-jest-config.json @@ -1 +1 @@ -{ "coverage": true } +{ "collectCoverage": true } From d5a1dc3765ae08a7f9a9b7050922ab4dfb9450dc Mon Sep 17 00:00:00 2001 From: Evan Siroky Date: Mon, 16 Sep 2019 23:32:32 -0700 Subject: [PATCH 10/14] refactor(jest): rearrange jest config order and add documentation --- README.md | 15 +++++++++++---- lib/jest.js | 14 +++++++------- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index f2d0650..46dffe2 100644 --- a/README.md +++ b/README.md @@ -222,12 +222,12 @@ Options: -e, --env Environment to use. -u, --update-snapshots Force update of snapshots. USE WITH CAUTION. --coverage Run Jest with coverage reporting ---coverage-paths Extra paths to collect code coverage from +--coverage-paths Extra paths to collect code coverage from in addition to the mastarm default of `lib/**/*.js` --custom-config-file Override the Jest config with the values found in a file path relative to the current working directory --force-exit Force Jest to exit after all tests have completed running. --jest-cli-args Extra arguments to pass directly to the Jest Cli. Make sure to encapsulate all extra arguments in quotes --no-cache Run Jest without cache (defaults to using cache) ---run-in-band Run all tests serially in the current process +--run-in-band Run all tests serially in the current process. This is always set to true while running on in a continuous integration environment. --setup-files Setup files to run before each test --test-environment Jest test environment to use (Jest default is jsdom) --test-path-ignore-patterns File patterns to ignore when scanning for test files @@ -246,10 +246,17 @@ If the `coverage` flag is set to true, mastarm will automatically generate cover The `patterns` argument will make Jest run only tests whose filename match the provided pattern. -There are two ways to override the [Jest config](https://jestjs.io/docs/en/configuration). The first is by adding a `jest` object to the package.json of the project. The second is by sending over a custom config file (either .json or .js) via the `--custom-config-file` option. Ex: +There are a number of ways to set the [Jest config](https://jestjs.io/docs/en/configuration). The first is by adding a `jest` object to the package.json of the project. A number of other mastarm options will override the config. And finally, it is possible to use a custom config file (either .json or .js) via the `--custom-config-file` option. The config values are set and potentially overridden in the following order: + +1. mastarm defaults. +2. Options in the `jest` object of the project's package.json file. +3. The values specified in the mastarm arguments `--coverage-paths`, `--setup-files`, `--test-environment` and `--test-path-ignore-patterns` +4. Options set in a custom config file specified in the mastarm argument `--custom-config-file`. + +Here is an example of how to set the config using a custom file: ```shell -matarm test --custom-config-file __tests__/test-utils/mocks/mock-jest-config.json +mastarm test --custom-config-file __tests__/test-utils/mocks/mock-jest-config.json ``` It is also possible to override any [Jest CLI Options](https://jestjs.io/docs/en/cli) by setting the `--jest-cli-args` flag. Ex: diff --git a/lib/jest.js b/lib/jest.js index ed4436a..5d6b4a7 100644 --- a/lib/jest.js +++ b/lib/jest.js @@ -26,6 +26,13 @@ module.exports.generateTestConfig = (patterns, options) => { } } + // add local package.json-level config options + if (pkg.jest != null) { + Object.keys(pkg.jest).forEach(key => { + jestConfig[key] = pkg.jest[key] + }) + } + if (options.coveragePaths) { jestConfig.collectCoverageFrom = jestConfig.collectCoverageFrom.concat( options.coveragePaths.split(' ') @@ -44,13 +51,6 @@ module.exports.generateTestConfig = (patterns, options) => { } }) - // add local package.json-level config options - if (pkg.jest != null) { - Object.keys(pkg.jest).forEach(key => { - jestConfig[key] = pkg.jest[key] - }) - } - // override config with the values found in a specified file if (options.customConfigFile) { const customConfig = require( From 815c3d2279be94222047e05d05438d4769be58aa Mon Sep 17 00:00:00 2001 From: Evan Siroky Date: Wed, 18 Sep 2019 15:14:34 -0700 Subject: [PATCH 11/14] refactor(deploy): use git-repo-is-up-to-date package --- bin/mastarm-deploy | 64 +++++++++++----------------------------------- package.json | 1 + yarn.lock | 9 +++++++ 3 files changed, 25 insertions(+), 49 deletions(-) diff --git a/bin/mastarm-deploy b/bin/mastarm-deploy index 24fc3bc..47ce526 100755 --- a/bin/mastarm-deploy +++ b/bin/mastarm-deploy @@ -4,8 +4,7 @@ const path = require('path') const commander = require('commander') const execa = require('execa') -const origin = require('git-remote-origin-url') -const repoInfo = require('git-repo-info') +const gitRepoIsUpToDate = require('git-repo-is-up-to-date') const commit = require('this-commit')() const username = require('username') @@ -36,56 +35,23 @@ commander let cloudfront, config, env, minify, s3bucket, tag, url async function deploy () { - // get information about the config directory being used - const repoUrl = await origin(commander.config) - let configCommit, configRemoteUrl - const configRepoRoot = repoInfo(commander.config).root - const configDir = path - .resolve(commander.config) - .replace(configRepoRoot, '') - - // check if the config directory being used is a configurations repo - if (repoUrl.endsWith('/configurations.git')) { - // run some extra checks to make sure configurations repo is up to date - // modified from https://stackoverflow.com/a/3278427/269834 - configRemoteUrl = repoUrl.replace('.git', '') - const { stdout: local } = await execa('git', ['-C', configRepoRoot, 'rev-parse', '@']) - const { stdout: remote } = await execa('git', ['-C', configRepoRoot, 'rev-parse', '@{u}']) - const { stdout: base } = await execa('git', ['-C', configRepoRoot, 'merge-base', '@', '@{u}']) - let configurationsOk = false - if (local === remote) { - // Up-to-date - console.log('Configurations up-to-date') - configurationsOk = true - } else if (local === base) { - console.error('Configurations out of sync: Need to pull') - } else if (remote === base) { - console.error('Configurations out of sync: Need to push') - } else { - console.error('Configurations out of sync: Diverged') - } + // get information about the directory that the config is in + const configRepoStatus = await gitRepoIsUpToDate(commander.config) + const { remoteUrl: configRemoteUrl, repoInfo } = configRepoStatus + let configCommit, configDir + if (repoInfo) { + configCommit = repoInfo.localCommit + configDir = repoInfo.root + } - // make sure there are no changes to the configurations - const { stdout: status } = await execa( - 'git', - [ - '-C', - configRepoRoot, - 'status', - '-s' - ] - ) - if (status === '') { - console.log('No changes to configurations repo') - } else { - console.error('Configurations out of sync: local changes exist that are not yet committed') - configurationsOk = false + // do some extra analysis if it looks like a configurations repo is being used + if (configRemoteUrl && configRemoteUrl.endsWith('/configurations.git')) { + if (!configRepoStatus.isUpToDate) { + console.error('Configurations folder is not up-to-date! Errors:') + configRepoStatus.errors.forEach(err => console.error(err)) + process.exit(1) } - if (!configurationsOk) process.exit(1) - - configCommit = local - // decrypt env file using sops to make sure old file is overwritten with // data from encoded sops file const configPath = path.resolve(commander.config) diff --git a/package.json b/package.json index 27931bc..c7a8633 100644 --- a/package.json +++ b/package.json @@ -90,6 +90,7 @@ "flow-runtime": "^0.17.0", "git-remote-origin-url": "^3.0.0", "git-repo-info": "^2.1.0", + "git-repo-is-up-to-date": "^1.0.1", "glob": "^7.1.3", "isomorphic-fetch": "^2.2.1", "jest": "^24.1.0", diff --git a/yarn.lock b/yarn.lock index 8403679..d023f67 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4472,6 +4472,15 @@ git-repo-info@^2.1.0: resolved "https://registry.yarnpkg.com/git-repo-info/-/git-repo-info-2.1.0.tgz#13d1f753c75bc2994432e65a71e35377ff563813" integrity sha512-+kigfDB7j3W80f74BoOUX+lKOmf4pR3/i2Ww6baKTCPe2hD4FRdjhV3s4P5Dy0Tak1uY1891QhKoYNtnyX2VvA== +git-repo-is-up-to-date@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/git-repo-is-up-to-date/-/git-repo-is-up-to-date-1.0.1.tgz#ff9a915fbac1b35a76bf2e39d086fa2dcb474313" + integrity sha512-rg/olld/00pjb2HBIAnca3rTbyWIHnaGFW3WFovCEJ0enB9cwCKHs6M17KnrZxczlGTMGY0IWSwoEFffy6kXmQ== + dependencies: + execa "^2.0.4" + git-remote-origin-url "^3.0.0" + git-repo-info "^2.1.0" + gitconfiglocal@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/gitconfiglocal/-/gitconfiglocal-2.1.0.tgz#07c28685c55cc5338b27b5acbcfe34aeb92e43d1" From 211fbd38a7bfb05be4a218e69213d24ad9cbe87f Mon Sep 17 00:00:00 2001 From: Evan Siroky Date: Thu, 19 Sep 2019 12:22:42 -0700 Subject: [PATCH 12/14] style(deploy): bold titles of MS Teams deploy message --- bin/mastarm-deploy | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/bin/mastarm-deploy b/bin/mastarm-deploy index 47ce526..e446e20 100755 --- a/bin/mastarm-deploy +++ b/bin/mastarm-deploy @@ -172,20 +172,20 @@ function logToMsTeams ({ configCommit, configDir, configRemoteUrl, error }) { ] }) } - const text = `📄 *commit:* ${pkg.name}@${commit.slice(0, 6)}\n - 👤 *deployed by:* ${username.sync()}\n + const text = `📄 **commit:** ${pkg.name}@${commit.slice(0, 6)}\n + 👤 **deployed by:** ${username.sync()}\n ${configCommit - ? `🎛️ *config:* configurations@${configCommit.slice(0, 6)}\n - 📂 *config folder:* ${configDir}\n` // improper indenting here needed to properly format on MS Teams - : '🎛️ *config:* unknown configuration data!\n'} - 🚦 *mastarm:* v${mastarmVersion}\n - ☁️ *cloudfront:* ${cloudfront}\n - 🌱 *env:* ${env}\n - 🗜️ *minify:* ${minify}\n - 📦 *s3bucket:* ${s3bucket}\n + ? `🎛️ **config:** configurations@${configCommit.slice(0, 6)}\n + 📂 **config folder:** ${configDir}\n` // improper indenting here needed to properly format on MS Teams + : '🎛️ **config:** unknown configuration data!\n'} + 🚦 **mastarm:** v${mastarmVersion}\n + ☁️ **cloudfront:** ${cloudfront}\n + 🌱 **env:** ${env}\n + 🗜️ **minify:** ${minify}\n + 📦 **s3bucket:** ${s3bucket}\n ${error - ? `🚨 🚨 *error deploying ${error.message || error}*` - : `🎉 🎊 🎉 *deploy successful!* 🎉 🎊 🎉`}` + ? `🚨 🚨 **error deploying ${error.message || error}**` + : `🎉 🎊 🎉 **deploy successful!** 🎉 🎊 🎉`}` return logger.notifyMsTeams({ potentialAction, From 97568bbb1ac87b38be7cc0409ba776168939066e Mon Sep 17 00:00:00 2001 From: Evan Siroky Date: Tue, 1 Oct 2019 11:16:43 -0400 Subject: [PATCH 13/14] chore(package): update to latest git-repo-is-up-to-date --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index c7a8633..e71e1cb 100644 --- a/package.json +++ b/package.json @@ -90,7 +90,7 @@ "flow-runtime": "^0.17.0", "git-remote-origin-url": "^3.0.0", "git-repo-info": "^2.1.0", - "git-repo-is-up-to-date": "^1.0.1", + "git-repo-is-up-to-date": "^1.1.0", "glob": "^7.1.3", "isomorphic-fetch": "^2.2.1", "jest": "^24.1.0", diff --git a/yarn.lock b/yarn.lock index d023f67..e6bdacb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4472,10 +4472,10 @@ git-repo-info@^2.1.0: resolved "https://registry.yarnpkg.com/git-repo-info/-/git-repo-info-2.1.0.tgz#13d1f753c75bc2994432e65a71e35377ff563813" integrity sha512-+kigfDB7j3W80f74BoOUX+lKOmf4pR3/i2Ww6baKTCPe2hD4FRdjhV3s4P5Dy0Tak1uY1891QhKoYNtnyX2VvA== -git-repo-is-up-to-date@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/git-repo-is-up-to-date/-/git-repo-is-up-to-date-1.0.1.tgz#ff9a915fbac1b35a76bf2e39d086fa2dcb474313" - integrity sha512-rg/olld/00pjb2HBIAnca3rTbyWIHnaGFW3WFovCEJ0enB9cwCKHs6M17KnrZxczlGTMGY0IWSwoEFffy6kXmQ== +git-repo-is-up-to-date@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/git-repo-is-up-to-date/-/git-repo-is-up-to-date-1.1.0.tgz#00e9f5dab56e420e4f6baca4000facdc4bbe7d2a" + integrity sha512-1wmqIbQc9KaK03Szd655uFuZwW9iRcSFb5ail+CMtYy6I7pmbk1XGrewB34hGmJFndHzYr9BtA+mGUYdfWqw1w== dependencies: execa "^2.0.4" git-remote-origin-url "^3.0.0" From 20776cabf534b87970c342527124f791a74e4b77 Mon Sep 17 00:00:00 2001 From: Evan Siroky Date: Tue, 1 Oct 2019 11:23:49 -0400 Subject: [PATCH 14/14] refactor(package): remove packages now contained in git-repo-is-up-to-date --- package.json | 2 -- 1 file changed, 2 deletions(-) diff --git a/package.json b/package.json index e71e1cb..3e773c7 100644 --- a/package.json +++ b/package.json @@ -88,8 +88,6 @@ "exorcist": "^1.0.1", "flow-bin": "0.84.0", "flow-runtime": "^0.17.0", - "git-remote-origin-url": "^3.0.0", - "git-repo-info": "^2.1.0", "git-repo-is-up-to-date": "^1.1.0", "glob": "^7.1.3", "isomorphic-fetch": "^2.2.1",