Skip to content

Commit

Permalink
Merge pull request #163 from conveyal/simplify-deploy
Browse files Browse the repository at this point in the history
Simplify deploy
  • Loading branch information
trevorgerhardt authored Apr 3, 2017
2 parents af50d40 + 6c22637 commit 4b27cde
Show file tree
Hide file tree
Showing 11 changed files with 160 additions and 145 deletions.
2 changes: 1 addition & 1 deletion __tests__/bin/mastarm.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ describe('mastarm cli', () => {
exec(`node ${mastarm} build ${mockDir}/index.js:${buildDir}/index.js ${mockDir}/index.css:${buildDir}/index.css`,
(err, stdout, stderr) => {
expect(err).toBeNull()
expect(stdout).toContain('updated css file')
expect(stdout).toContain('done building')
expect(stderr).toBe('')
expect(fs.existsSync(`${buildDir}/index.js`)).toBeTruthy()
expect(fs.existsSync(`${buildDir}/index.css`)).toBeTruthy()
Expand Down
23 changes: 15 additions & 8 deletions __tests__/lib/push-to-s3.js
Original file line number Diff line number Diff line change
@@ -1,27 +1,34 @@
/* global describe, it */

const fs = require('fs')
const path = require('path')

const BUILD_DIR = path.join(process.cwd(), '__tests__/test-utils/tmp')
const MOCK_DIR = path.join(process.cwd(), '__tests__/test-utils/mocks')
const files = [
[`${MOCK_DIR}/index.js`, `${BUILD_DIR}/index.js`],
[`${MOCK_DIR}/index.css`, `${BUILD_DIR}/index.css`]
]

describe('lib > push to s3', () => {
const configPush = require('../../lib/push-to-s3')
const build = require('../../lib/build')
const createPushToS3 = require('../../lib/push-to-s3')
const loadConfig = require('../../lib/load-config')
const createLogger = require('../../lib/logger')

it('should compile JavaScript and CSS and send to s3 via aws-sdk', () => {
const config = loadConfig(process.cwd(), 'configurations/default', 'development')
const push = configPush({
const push = createPushToS3({
env: 'development',
config,
log: createLogger(),
minify: false,
s3bucket: 'test-bucket'
})
return Promise.all([
push([`${MOCK_DIR}/index.js`, `${BUILD_DIR}/index.js`]),
push([`${MOCK_DIR}/index.css`, `${BUILD_DIR}/index.css`])
])
return build({
config,
env: 'development',
files
}).then(() =>
Promise.all(files.map((f) =>
push({body: fs.readFileSync(f[0]), outfile: f[0]}))))
})
})
83 changes: 54 additions & 29 deletions bin/mastarm
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
#!/usr/bin/env node

const commander = require('commander')
const fs = require('fs')
const path = require('path')

const loadConfig = require('../lib/load-config')
const logger = require('../lib/logger')
const util = require('../lib/util')

commander
Expand Down Expand Up @@ -42,11 +44,11 @@ commander
const build = require('../lib/build')
build(opts)
.then((results) => {
console.log('done building...')
logger.log('done building...')
if (!watch) process.exit(0)
})
.catch((err) => {
console.error(err)
logger.error(err)
if (!watch) process.exit(1)
})
}
Expand Down Expand Up @@ -75,52 +77,69 @@ commander
.action(function (entries, options) {
const commit = require('this-commit')()
const username = require('username')
const createLogger = require('../lib/logger')

const build = require('../lib/build')
const pkg = require('../lib/pkg')
const pushToS3 = require('../lib/push-to-s3')
const createPushToS3 = require('../lib/push-to-s3')

const url = pkg.repository.url.replace('.git', '')
const tag = `<${url}/commit/${commit}|${pkg.name}@${commit.slice(0, 6)}>:`
const user = username.sync()
const tag = `<${url}/commit/${commit}|${pkg.name}@${commit.slice(0, 6)}>`
const config = loadConfig(process.cwd(), commander.config, commander.env)
const get = util.makeGetFn([options, commander, config.settings])

const env = get('env') || 'development'
const s3bucket = get('s3bucket')
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([...entries, ...(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 log = createLogger({channel: config.env.SLACK_CHANNEL || '#devops', webhook: config.env.SLACK_WEBHOOK})
const env = get('env') || 'development'
const minify = get('minify')
const cloudfront = get('cloudfront')
const push = pushToS3({
cloudfront,
const buildOpts = {
config,
env,
log,
minify,
s3bucket,
tag
files,
minify
}
const cloudfront = get('cloudfront')
const s3bucket = get('s3bucket')

const pushToS3 = createPushToS3({
cloudfront,
s3bucket
})

log(
`:construction: *${tag} deploy started by <@${user}>*
logger.log(
`:construction: *deploying: ${tag} by <@${username.sync()}>*
:cloud: *cloudfront:* ${cloudfront}
:hash: *commit:* ${commit}
:seedling: *env:* ${env}
:compression: *minify:* ${minify}
:package: *s3bucket:* ${s3bucket}`
).then(() => {
Promise
.all(files.map(push))
:package: *s3bucket:* ${s3bucket}
:hammer_and_wrench: *building:* ${sourceFiles.join(', ')}`
).then(() =>
build(buildOpts)
.then(() =>
log(`:rocket: ${tag} deploy finished!! :tada: :confetti_ball: :tada:`)
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(() => process.exit(0)))
.catch((err) =>
log(`:rotating_light: *error deploying ${tag} ${err.message}*`)
.then(() => process.exit(1)))
})
logger.log(`:rotating_light: *${tag} error deploying ${tag} ${err.message || err}*`)
.then(() => process.exit(1))))
})

commander
Expand Down Expand Up @@ -158,14 +177,14 @@ commander
const errors = lintMessages(paths.length > 0 ? paths : ['lib'], config.messages)

if (errors.length > 0) {
console.log(`${errors.length} missing messages`)
logger.error(`${errors.length} missing messages`)
for (const [message, file, line] of errors) {
console.log(`${file} line ${line}: ${message} is not defined`)
logger.error(`${file} line ${line}: ${message} is not defined`)
}

process.exit(1)
} else {
console.log('No missing messages found! 💃')
logger.log('No missing messages found! 💃')
}
})

Expand Down Expand Up @@ -212,3 +231,9 @@ commander
})

commander.parse(process.argv)

const readFile = (f) =>
new Promise((resolve, reject) =>
fs.readFile(f, (err, data) => err
? reject(err)
: resolve(data)))
5 changes: 3 additions & 2 deletions lib/budo.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
const budo = require('budo')
const path = require('path')

const transformJs = require('./js-transform')
const transformCss = require('./css-transform')
const logger = require('./logger')
const transformJs = require('./js-transform')

module.exports = function ({
config,
Expand Down Expand Up @@ -55,6 +56,6 @@ module.exports = function ({
budo
.cli(budoFiles, budoOpts)
.on('error', function (err) {
console.error(err.stack)
logger.error(err.stack)
})
}
6 changes: 5 additions & 1 deletion lib/css-transform.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ const postcssImport = require('postcss-import')
const postcssReporter = require('postcss-reporter')
const postcssSafeParser = require('postcss-safe-parser')

const logger = require('./logger')

module.exports = function ({
config,
entry,
Expand Down Expand Up @@ -47,8 +49,10 @@ module.exports = function ({
if (results.map) {
fs.writeFileSync(`${outfile}.map`, results.map)
}
if (watch) {
logger.log(`updated ${outfile}`)
}
}
console.log('updated css file')
return results
})

Expand Down
4 changes: 3 additions & 1 deletion lib/flyle.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ const mkdirp = require('mkdirp')
const path = require('path')
const parse = require('url').parse

const logger = require('./logger')

const DEFAULT_CACHE_DIRECTORY = `${process.env.HOME}/.flyle`
const DEFAULT_PNG = path.resolve(__dirname, '../mastarm.png')

Expand Down Expand Up @@ -43,7 +45,7 @@ module.exports = function (req, res) {
}

function logAndSend ({err, res}) {
console.error('flyle >> sending default image: ', err.message)
logger.error('flyle >> sending default image: ', err.message)
sendImg({
path: DEFAULT_PNG,
res
Expand Down
5 changes: 3 additions & 2 deletions lib/js-build.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const mkdirp = require('mkdirp')
const path = require('path')

const browserify = require('./browserify')
const logger = require('./logger')

/**
*
Expand All @@ -20,7 +21,7 @@ module.exports = function buildJs ({config, entry, env, minify, outfile, watch})
pipeline.bundle()
.pipe(exorcist(`${outfile}.map`))
.pipe(fs.createWriteStream(outfile))
.on('error', (err) => console.error(err) && reject(err))
.on('error', reject)
.on('finish', resolve)
} else {
pipeline.bundle((err, buf) => {
Expand All @@ -34,7 +35,7 @@ module.exports = function buildJs ({config, entry, env, minify, outfile, watch})
pipeline.plugin(require('watchify'), {poll: true})
pipeline.plugin(require('errorify'))
pipeline.on('update', bundle)
pipeline.on('log', console.log)
pipeline.on('log', logger.log)
}

return bundle()
Expand Down
6 changes: 4 additions & 2 deletions lib/lint-messages.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
const { readFileSync, statSync, existsSync } = require('fs')
const glob = require('glob')

const logger = require('./logger')

// the IMPORT expression can be quite slow, so use a fast expression to pre-test if this is even a candidate
const IS_IMPORT = /import.*from '[^ ]+\/messages'/
// This will split up the import statement into the default and named imports. The named imports,
Expand Down Expand Up @@ -97,8 +99,8 @@ module.exports = {
lint: function (files, messages) {
const missingFiles = files.filter(file => !existsSync(file))
if (missingFiles.length > 0) {
console.log('some files were not found:')
missingFiles.forEach(f => console.log(` - ${f}`))
logger.log('some files were not found:')
missingFiles.forEach(f => logger.log(` - ${f}`))
process.exit(1)
}

Expand Down
53 changes: 42 additions & 11 deletions lib/logger.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,50 @@
const fetch = require('isomorphic-fetch')
const nodeEmoji = require('node-emoji')
const slack = require('./notify-slack')

module.exports = function ({channel, webhook} = {}) {
if (webhook) {
return function (text) {
emojifyLog(text)
return slack({channel, text, webhook})
}
const logToConsole = (text) =>
Promise.resolve(console.log(emojify(text)))
const logToErrorConsole = (text) =>
Promise.resolve(console.error(emojify(text)))

module.exports.log = logToConsole
module.exports.error = logToErrorConsole

module.exports.logToSlack = ({channel, webhook}) => {
module.exports.log = (text) => {
logToConsole(text)
return notifySlack({channel, text, webhook})
}
return function (text) {
return Promise.resolve(emojifyLog(text))

module.exports.error = (text) => {
logToErrorConsole(text)
return notifySlack({channel, text, webhook})
}
}

function emojifyLog (text) {
function emojify (text) {
const strippedLinks = text.replace(/<[^|>]+\|([^>]+)>/g, '$1')
console.log(nodeEmoji.emojify(strippedLinks))
return nodeEmoji.emojify(strippedLinks)
}

function notifySlack ({
channel,
text,
webhook
}) {
return fetch(webhook, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
channel,
text
})
})
.then((response) => response.text())
.catch((err) => {
logToErrorConsole('Error posting to Slack webhook')
logToErrorConsole(err)
return err
})
}
24 changes: 0 additions & 24 deletions lib/notify-slack.js

This file was deleted.

Loading

0 comments on commit 4b27cde

Please sign in to comment.