1 | #!/usr/bin/env node
|
2 |
|
3 | 'use strict'
|
4 |
|
5 | const debug = require('debug')('now-pipeline')
|
6 | const initCrashReporter = require('node-sentry-error-reporter')
|
7 | initCrashReporter()
|
8 |
|
9 | const R = require('ramda')
|
10 | const runCommand = require('../src/run-command')
|
11 | const is = require('check-more-types')
|
12 | const la = require('lazy-ass')
|
13 | const pkgd = require('pkgd')
|
14 | const argv = require('minimist')(process.argv.slice(2))
|
15 |
|
16 | const envUrlName = 'NOW_URL'
|
17 | const passAsName = argv.as || envUrlName
|
18 | const testCommand = argv.test || 'npm test'
|
19 |
|
20 | const nowPipeline = require('..')
|
21 | const pkg = nowPipeline.getPackage()
|
22 |
|
23 | function findFiles () {
|
24 | return pkgd(process.cwd())
|
25 | .then(R.prop('files'))
|
26 | }
|
27 |
|
28 | var start
|
29 |
|
30 | function findDeploy (url) {
|
31 | la(is.url(url), 'expected url', url)
|
32 |
|
33 | return nowPipeline.deployments()
|
34 | .then(deploys => {
|
35 | debug('looking for url %s in %d deploys', url, deploys.length)
|
36 |
|
37 | const found = deploys.find(d => {
|
38 | return url.endsWith(d.url)
|
39 | })
|
40 | if (!found) {
|
41 | console.error('Could not find deploy for url', url)
|
42 | process.exit(-1)
|
43 | }
|
44 | debug('found deployment', found)
|
45 | return found
|
46 | })
|
47 | }
|
48 |
|
49 | if (process.env[envUrlName]) {
|
50 | const url = process.env[envUrlName]
|
51 | console.log(`found existing env variable ${envUrlName} ${url}`)
|
52 |
|
53 |
|
54 |
|
55 | start = findFiles().then((filenames) => findDeploy(url))
|
56 | } else {
|
57 | start = findFiles().then(nowPipeline.deploy)
|
58 | }
|
59 |
|
60 | function setFullHost (deploy) {
|
61 | if (!deploy.url) {
|
62 | deploy.url = deploy.host
|
63 | }
|
64 | deploy.url = addHttps(deploy.url)
|
65 |
|
66 | console.log('deployed to url', deploy.url)
|
67 | la(is.url(deploy.url), 'expected deploy.url to be full https', deploy.url)
|
68 | return deploy
|
69 | }
|
70 |
|
71 | function deployIsWorking (deploy) {
|
72 | console.log(`deployed url ${deploy.url} is working`)
|
73 | }
|
74 |
|
75 | function addHttps (url) {
|
76 | return url.startsWith('https://') ? url : 'https://' + url
|
77 | }
|
78 |
|
79 | const updateAliasIfNecessary = R.curry(
|
80 | function updateAliasIfNecessary (aliasName, deploy) {
|
81 | la(is.maybe.string(aliasName), 'alias name should be a string', aliasName)
|
82 |
|
83 | return nowPipeline.deployments(pkg.name)
|
84 | .then(deploys => {
|
85 | return R.filter(R.prop('alias'))(deploys)
|
86 | })
|
87 | .then(deployed => {
|
88 | console.log('found %d deploy(s) with aliases', deployed.length)
|
89 | debug(deployed)
|
90 |
|
91 | if (!deployed.length) {
|
92 | console.log('there is no existing alias')
|
93 | if (!aliasName) {
|
94 | console.log('will skip updating alias to', deploy.url)
|
95 | return
|
96 | }
|
97 | console.log('setting new alias to %s', aliasName)
|
98 | return nowPipeline.now.createAlias(deploy.uid, aliasName)
|
99 | .catch(err => {
|
100 | console.error('Could not create alias')
|
101 | console.error(err.message)
|
102 | console.error('Note: you need to create a FIRST alias to domain MANUALLY')
|
103 | console.error('using a command like this:')
|
104 | console.error(` now alias ${deployed.url} ${aliasName}`)
|
105 | return Promise.reject(err)
|
106 | })
|
107 | }
|
108 |
|
109 | if (deployed.length > 1) {
|
110 | console.log('found %d deployed aliases', deployed.length)
|
111 | console.log('not sure which one to update')
|
112 | return Promise.reject(new Error('Multiple aliases'))
|
113 | }
|
114 |
|
115 | la(deployed.length === 1, 'expect single alias')
|
116 |
|
117 | const alias = deployed[0]
|
118 | if (alias.uid === deploy.uid) {
|
119 | console.log('The current alias %s points at the same deploy %s',
|
120 | alias.alias, deploy.url)
|
121 | console.log('Nothing to do')
|
122 | return
|
123 | }
|
124 |
|
125 | console.log('switching alias %s to point at new deploy %s',
|
126 | alias.alias, deploy.url)
|
127 | la(is.unemptyString(alias.alias), 'invalid alias', alias)
|
128 |
|
129 | return nowPipeline.now.createAlias(deploy.uid, alias.alias)
|
130 | .then(result => {
|
131 | debug('createAlias result', result)
|
132 | console.log('switched alias %s to point at %s',
|
133 | alias.alias, deploy.url)
|
134 | console.log('taking down previously aliased deploy',
|
135 | alias.uid)
|
136 | return nowPipeline.remove(alias.uid)
|
137 | })
|
138 | .catch(error => {
|
139 | console.error('error switching alias', deploy.uid, alias.alias)
|
140 | console.error(error)
|
141 | throw error
|
142 | })
|
143 | })
|
144 | })
|
145 |
|
146 | function testDeploy (deploy) {
|
147 | la(is.object(deploy), 'wrong deploy object', deploy)
|
148 | console.log('testing url %s', deploy.url)
|
149 | console.log('passing it as env variable %s', passAsName)
|
150 | console.log('test command "%s"', testCommand)
|
151 | la(is.url(deploy.url), 'missing deploy url in', deploy)
|
152 |
|
153 | const env = {}
|
154 | env[passAsName] = deploy.url
|
155 | return runCommand(testCommand, env)
|
156 | .then(R.always(deploy))
|
157 | }
|
158 |
|
159 | start
|
160 | .then(setFullHost)
|
161 | .then(testDeploy)
|
162 | .then(R.tap(deployIsWorking))
|
163 | .then(updateAliasIfNecessary(argv.alias))
|
164 | .catch(err => {
|
165 | console.error('Something went wrong')
|
166 | console.error('Sometimes restarting pipeline can help')
|
167 | console.error(err)
|
168 | process.exit(-1)
|
169 | })
|