diff --git a/bin/acceptance.js b/bin/acceptance.js index baa40df..51a00c3 100755 --- a/bin/acceptance.js +++ b/bin/acceptance.js @@ -1,25 +1,112 @@ #!/usr/bin/env node +const Axios = require('axios') const ChildProcess = require('child_process') -const app = ChildProcess.spawn('npm', ['start'], { - detach: true, - stdio: 'inherit' +const { CI, CIRCLE_BRANCH, NETLIFY_ACCESS_TOKEN } = process.env + +const netlify = Axios.create({ + baseURL: 'https://api.netlify.com/api/v1/', + headers: { + Authorization: 'Bearer ' + NETLIFY_ACCESS_TOKEN, + 'content-type': 'application/json' + } }) -const acceptanceScript = - process.env.CI === 'true' ? 'acceptance-ci' : 'acceptance' +async function main() { + if (CI === 'true') { + console.log('ci detected. checking netlify status') -const test = ChildProcess.spawn('npm', ['run', acceptanceScript], { - detach: true, - stdio: 'inherit' -}) + console.log('getting site id') + const sites = await netlify + .get('sites?name=react-browser-hooks&filter=all') + .then(({ data }) => data) -app.on('error', (err) => { - console.log('Failed to start subprocess:', err) - test.kill() -}) + if (!sites.length) { + throw new Error('react-browser-hooks site not found') + } -test.on('close', () => { - app.kill() -}) + const [site] = sites + console.log(`site found: ${site.id}`) + + console.log('getting deploy id') + const deploys = await netlify + .get(`sites/${site.id}/deploys?branch=${CIRCLE_BRANCH}`) + .then(({ data }) => data) + + if (!deploys.length) { + throw new Error(`no deploys found for branch: ${CIRCLE_BRANCH}`) + } + + const [deploy] = deploys // assumes most recent deploy is the right one + console.log(`deploy found: ${deploy.id}`) + + async function waitForNetlifyDeploy(deployId, options = {}) { + options.rate = options.rate || 30000 // 30s default + options.timeout = options.timeout || 300000 // 5m default + options.total = options.total || 0 + + const { summary } = await netlify + .get(`sites/${site.id}/deploys/${deployId}`) + .then(({ data }) => data) + + console.log('waiting for netlify to deploy...') + console.log(`status: ${summary.status}`) + + if (options.total >= options.timeout) { + throw new Error( + `polling ended after ${options.total}ms (max wait reached)` + ) + } + + if (summary.status === 'ready') { + return + } + + await wait(options.rate) + options.total += options.rate + + await waitForNetlifyDeploy(deployId, options) + } + + await waitForNetlifyDeploy(deploy.id) + console.log(`netlify deployed: ${deploy.deploy_ssl_url}`) + console.log('starting acceptance') + + const test = ChildProcess.spawn('npm', ['run', 'acceptance-ci'], { + env: Object.assign({}, process.env, { + ACCEPTANCE_URL: deploy.deploy_ssl_url + }), + stdio: 'inherit' + }) + + test.on('close', (code) => { + console.log(`test process exited with code ${code}`) + }) + + test.on('error', console.error) + } else { + console.log('local development detected. starting with npm start') + const app = ChildProcess.spawn('npm', ['start'], { + detach: true, + stdio: 'inherit' + }) + const test = ChildProcess.spawn('npm', ['run', 'acceptance'], { + detach: true, + stdio: 'inherit' + }) + app.on('error', (err) => { + console.log('Failed to start subprocess:', err) + test.kill() + }) + test.on('close', () => { + app.kill() + }) + } +} + +function wait(ms) { + return new Promise((resolve) => setTimeout(resolve, ms)) +} + +main().catch(console.error) diff --git a/package.json b/package.json index 1e7efcd..0e9d0f2 100644 --- a/package.json +++ b/package.json @@ -38,6 +38,7 @@ "@storybook/addon-options": "4.1.13", "@storybook/addons": "4.1.13", "@storybook/react": "4.1.13", + "axios": "^0.18.0", "babel-eslint": "10.0.1", "babel-loader": "8.0.5", "eslint": "5.14.1",