Question

I'm trying to automate a process I go through every time I test my apps and sites on the server. I'm currently running on nodejitsu. When I've tested something and it works on my local machine, the next thing I do is...

  1. Open my package.json file
  2. Delete the domains field and change the name and subdomain to staging. (It might also make sense to change the version number)
  3. Then I jitsu deploy
  4. Confirm any prompts (like approve an increment of the version number)
  5. Once the app starts I check out how my apps working on the server, make changes and so on

After I'm done, and my apps ready to go I undo my changes in my package.json file. I'd like to automate this process. I had the idea of doing so with a tiny node.js file. Here it is so far...

/*
 * Use this file to deploy an app to the staging server on nodejitsu
 */
var bash = require('child_process').spawn('bash');
var colors = require('colors');
var fs = require('fs');

// stdout setup
bash.stdout.on('data', function (data) {
  console.log('stdout: ' + data);
});
bash.stdout.on('error', function (err) {
  console.log('stdout error: '.red, err);
});

// on bash exit
bash.on('exit', function (code) {
  console.log('Exiting... ', code);
});

// grab package.json
var package = '';
fs.readFile('package.json', {encoding: 'utf-8'}, function (err, data) { // grab the package.json file contents
  if (err) throw err;
  package = JSON.parse(data);
  fs.rename('package.json', 'rename-me-before-deploying.json'); // rename the package.json file
  package.name = 'stajing'; // alter json
  package.subdomain = 'stajing'; // alter json
  package.domains = []; // alter json
  fs.writeFile('package.json', JSON.stringify(package, null, 2), function(err) { // write the new package to package.json
    if (err) throw err;
    bash.stdin.write('jitsu deploy\n'); // Deploy to staging app on nodejitsu.
    setTimeout(function () { // this needs to be replaced
      bash.stdin.write('yes\n');
    }, 5000);
    console.log("All done : )");
    // bash.stdin.end(); // close out
  });
});

I have a few issues here. I'm pretty sure all I need to know to complete it, is the event that fires when nodejitsu prompts me to increment the version number prompt: Is this ok?: (yes) so that I can confirm, if that happens, and the event that fires when the whole process finishes so that I can revert the changes to my package.json file, leaving my app deployed to a staging environment and my files essentially untouched.

Was it helpful?

Solution

I'm not setup here to run jitsu deploy. However, here is some code that illustrates how you can deal with the prompts:

var command = require('child_process').spawn('./command.js');
require('colors');

var stdout = "";
var prompt_re = /Is it okay \(yes\)\?.*?$/m;
command.stdout.on('data', function (data) {
    console.log("stdout data: ".green + data);
    stdout += data;
    if (prompt_re.test(stdout)) {
        command.stdin.write("yes\n");
        // Flush the current buffer.
        stdout = "";
    }
});

command.stdout.on('error', function (err) {
    console.log('stdout error: '.red, err);
});

var exit_msg = 'Exited with code... ';
command.on('exit', function (code) {
    if (code != 0) {
        console.log(exit_msg.red, code);
        process.exit(1); // Or whatever you want to handle errors.
    }

    console.log(exit_msg.green, code);
    // The code you want to execute once your command is done goes here.
});

Some explanations:

  1. The code above buffers the data it gets from command.stdout into as string stored in the stdout variable and tests against that because if there's a lot of output there's no guarantee that the prompt will arrive in a single data event. (It could, for instance, come in one event that contains a bunch of data + the string Is it and then the next data event could contain the rest of the prompt.)

  2. The regular expression prompt_re contains '.*?$' because the command I use to simulate getting a prompt uses escape codes for colors and I could not be bothered to match against the exact codes that are output.

  3. This code assumes that the command will stop right away after outputting a prompt and waits there. This seems to be a safe assumption.

  4. It also assumes that the prompt text cannot appear as something which is not a prompt. Whether this is safe depends on your specific scenario.

The ./command.js file I used to simulate the command being run is:

#!/usr/bin/env node

var prompt = require("prompt");

function ask(cb) {
    prompt.get(["Is it okay (yes)?"], function (err, result) {
        console.log("asked");
        cb();
    });
}

setTimeout(function () {
    ask(function () {
        setTimeout(function () {
            ask(function () { process.exit(0); });
        }, 1000);
    });
}, 5000);

It waits 5s, prompts once, waits 1s, prompts a second time and exits.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top