cheapsteak
7/24/2015 - 3:39 PM

deploy-script.js

import exec from 'promised-exec';
import chalk from 'chalk';
import {argv} from 'yargs';
import rimraf from 'rimraf';
import buildConfig from './build-config.js';

const error = chalk.red;
const ok = chalk.green;
const yellow = chalk.yellow;

const {dev: devDir, deploy: deployDir} = buildConfig;
const env = argv.env || 'dev';

const checkout = async function (branch='dev') {

  // Ensure branch exists. create if necessary
  try {
    await exec(`git rev-parse --verify ${branch}`);
  } catch (e) {
    console.log(`local branch ${branch} does not exist. creating.`);
    await exec(`git branch ${branch}`);
  }

  // Checkout branch
  try {
    await exec(`git checkout ${branch}`);
  } catch (e) {
    if (e.string.indexOf('Switched to branch') === 0) {
      // It succeeded. Not sure why this throws when it succeeds.
    } else {
      console.log('error checking out branch: ' + JSON.stringify(e));
    }
  }
};

const deploy = async function (env) {

  const deploymentBranch = `deploy/${env}`;
  console.log(`initializing deployment for "${yellow(deploymentBranch)}"`);

  // Ensure working directory is clean
  const changed = (await exec('git diff | wc -l')).trim() !== '0';
  if (changed) {
    console.log(error('Please commit or stash changes before deployment.'));
    return;
  }
  console.log(ok('Working directory is clean.'));

  const initialBranch = (await exec('git rev-parse --abbrev-ref HEAD')).trim();

  // If not on deployment branch, switch to it.
  if (initialBranch.indexOf(deploymentBranch) !== 0) {
    console.log(`Not on deployment branch`);
    await checkout(deploymentBranch);
    console.log(ok(`Switched to deployment branch ${yellow(deploymentBranch)}`));
  }

  // Pull from remote
  const remoteBranchExists = (await exec(`git ls-remote --heads origin ${deploymentBranch} | wc -l`)).trim() === '1';

  if (remoteBranchExists) {
    console.log(`pulling from remote ${yellow(deploymentBranch)}`);
    try {
      await exec(`git pull origin ${deploymentBranch}`);
    } catch (e) {
      console.log(error('error pulling from origin: ', e));
    }
  }

  // Merge from initial branch
  await exec(`git merge ${initialBranch}`);
  console.log(ok(`merged from ${yellow(initialBranch)}`));

  // Build
  try {
    console.log('npm run build. This could take a minute...');
    await exec(`npm run build:${env}`);
  } catch (e) {
    console.log('failed');
    console.log(e);
  }

  // Clean deploy directory
  rimraf.sync(deployDir);
  console.log(`mv ${devDir} ${deployDir}`);
  try {
    await exec(`mv ${devDir} ${deployDir}`);
  } catch (e) {
    console.log(e);
  }

  // Commit and push
  try {
    await exec(`git commit -am "deploying to ${env}"`);
    console.log(ok(`committed`));
  } catch (e) {
    if (e.buffer.code === 1) {
      console.log(error('Theres nothing to commit. Something might have gone wrong.'));
    } else {
      console.log('error committing ', JSON.stringify(e));
    }
  }

  try {
    await exec(`git push origin ${deploymentBranch}`);
    console.log(ok(`pushed`));
  } catch (e) {
    console.log('"git push" threw, but it throws when it works');
    console.log(e);
  }

  await checkout(initialBranch);
  console.log(ok(`switched back to initial branch: ${yellow(initialBranch)}`));

}

deploy(env);