Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixing multi resource lifecycle hooks #1130

Merged
merged 13 commits into from Feb 8, 2019
1 change: 1 addition & 0 deletions changelog.txt
@@ -0,0 +1 @@
fixed - Multi-Site predeploy and postdeploy hooks now trigger
157 changes: 93 additions & 64 deletions src/deploy/lifecycleHooks.js
@@ -1,18 +1,18 @@
"use strict";

var _ = require("lodash");
const _ = require("lodash");

var utils = require("../utils");
var clc = require("cli-color");
var childProcess = require("child_process");
var FirebaseError = require("../error");
var getProjectId = require("../getProjectId");
var logger = require("../logger");
var path = require("path");
const utils = require("../utils");
const clc = require("cli-color");
const childProcess = require("child_process");
const FirebaseError = require("../error");
const getProjectId = require("../getProjectId");
const logger = require("../logger");
const path = require("path");

function runCommand(command, childOptions) {
var escapedCommand = command.replace(/\"/g, '\\"');
var translatedCommand =
const escapedCommand = command.replace(/\"/g, '\\"');
const translatedCommand =
'"' +
process.execPath +
'" "' +
Expand All @@ -26,7 +26,7 @@ function runCommand(command, childOptions) {
if (translatedCommand === "") {
resolve();
}
var child = childProcess.spawn(translatedCommand, [], childOptions);
const child = childProcess.spawn(translatedCommand, [], childOptions);
child.on("error", function(err) {
reject(err);
});
Expand All @@ -42,69 +42,98 @@ function runCommand(command, childOptions) {
});
}

module.exports = function(target, hook) {
// Errors in postdeploy script will not exit the process since it's too late to stop the deploy.
var exit = hook !== "postdeploy" ? undefined : { exit: 2 };
function getChildEnvironment(target, overallOptions, config) {
// active project ID
const projectId = getProjectId(overallOptions);
// root directory where firebase.json can be found
const projectDir = overallOptions.projectRoot;
// location of hosting site or functions deploy, defaults project directory
let resourceDir;
switch (target) {
case "hosting":
resourceDir = overallOptions.config.path(config.public);
break;
case "functions":
resourceDir = overallOptions.config.path(config.source);
break;
default:
resourceDir = overallOptions.config.path(overallOptions.config.projectDir);
}

return function(context, options) {
var commands = options.config.get(target + "." + hook);
// Copying over environment variables
return _.assign({}, process.env, {
GCLOUD_PROJECT: projectId,
PROJECT_DIR: projectDir,
RESOURCE_DIR: resourceDir,
});
}

if (!commands) {
return Promise.resolve();
}
if (typeof commands === "string") {
commands = [commands];
}
function runTargetCommands(target, hook, overallOptions, config) {
let commands = config[hook];
if (!commands) {
return Promise.resolve();
}
if (typeof commands === "string") {
commands = [commands];
}

// active project ID
var projectId = getProjectId(options);
// root directory where firebase.json can be found
var projectDir = options.projectRoot;
// location of hosting site or functions deploy, defaults project directory
var resourceDir;
switch (target) {
case "hosting":
resourceDir = options.config.path(options.config.get("hosting.public"));
break;
case "functions":
resourceDir = options.config.path(options.config.get("functions.source"));
break;
default:
resourceDir = options.config.path(options.config.projectDir);
}
const childOptions = {
cwd: overallOptions.config.projectDir,
env: getChildEnvironment(target, overallOptions, config),
shell: true,
stdio: [0, 1, 2], // Inherit STDIN, STDOUT, and STDERR
};

const runAllCommands = _.reduce(
commands,
function(soFar, command) {
return soFar.then(function() {
return runCommand(command, childOptions);
});
},
Promise.resolve()
);

// Copying over environment variables
var childEnv = _.assign({}, process.env, {
GCLOUD_PROJECT: projectId,
PROJECT_DIR: projectDir,
RESOURCE_DIR: resourceDir,
// Errors in postdeploy script will not exit the process since it's too late to stop the deploy.
const exit = hook !== "postdeploy" ? undefined : { exit: 2 };
Memeriaj marked this conversation as resolved.
Show resolved Hide resolved

// We currently use the resource name in info logs in the rest of the deploy.
// However we don't have access to that here because predeploy hooks will
// happen before we figure that out. Internal bug tracking number: 123715324
let logIdentifier = target;
if (config.target) {
logIdentifier += `[${config.target}]`;
}

return runAllCommands
.then(function() {
utils.logSuccess(
clc.green.bold(logIdentifier + ":") + " Finished running " + clc.bold(hook) + " script."
);
})
.catch(function(err) {
throw new FirebaseError(logIdentifier + " " + hook + " error: " + err.message, exit);
});
}

var childOptions = {
cwd: options.config.projectDir,
env: childEnv,
shell: true,
stdio: [0, 1, 2], // Inherit STDIN, STDOUT, and STDERR
};
module.exports = function(target, hook) {
return function(context, options) {
let targetConfigs = options.config.get(target);
if (!targetConfigs) {
return Promise.resolve();
}
if (!_.isArray(targetConfigs)) {
targetConfigs = [targetConfigs];
}

var runAllCommands = _.reduce(
commands,
function(soFar, command) {
return soFar.then(function() {
return runCommand(command, childOptions);
return _.reduce(
targetConfigs,
function(previousCommands, individualConfig) {
return previousCommands.then(function() {
return runTargetCommands(target, hook, options, individualConfig);
});
},
Promise.resolve()
);

return runAllCommands
.then(function() {
utils.logSuccess(
clc.green.bold(target + ":") + " Finished running " + clc.bold(hook) + " script."
);
})
.catch(function(err) {
throw new FirebaseError(target + " " + hook + " error: " + err.message, exit);
});
};
};