scripts should be given a callback to define when work is done
tommedema opened this issue · comments
If I define a script like so:
custom:
scriptHooks:
before:aws:package:finalize:saveServiceState: scripts/define-certificate-is-valid.js # define whether the stack's certificate is valid prior to consuming it
It should run BEFORE aws:package:finalize:saveServiceState
. SaveServiceState runs code that compiles the cloudformation template. I can then confirm if the script is run at the correct time by adding a log line at saveCompiledTemplate.js:
'use strict';
const BbPromise = require('bluebird');
const path = require('path');
module.exports = {
saveCompiledTemplate() {
const compiledTemplateFileName = this.provider.naming.getCompiledTemplateFileName();
const compiledTemplateFilePath = path.join(
this.serverless.config.servicePath,
'.serverless',
compiledTemplateFileName
);
console.log('!!! writing compiled template file')
console.log(this.serverless.service.provider.compiledCloudFormationTemplate)
this.serverless.utils.writeFileSync(compiledTemplateFilePath,
this.serverless.service.provider.compiledCloudFormationTemplate);
return BbPromise.resolve();
},
};
And a log line in my script, which should run first:
/* global serverless, options */
log('initializing')
const getServerlessPlugin = require(__dirname + '/lib/get-serverless-plugin')(serverless)
const awsInfo = getServerlessPlugin('AwsInfo')
const getOutput = require(__dirname + '/lib/get-cf-output')(serverless, awsInfo)
const get = require('lodash.get')
const util = require('util')
awsInfo.getStackInfo()
.then(() => {
var condition = get(serverless,
['service', 'provider', 'compiledCloudFormationTemplate',
'Conditions', 'ShouldConsumeCertificate'])
log(`initial certificate condition is ${util.inspect(condition, { depth: 10 })}`)
var updatedCondition = JSON.parse(
JSON.stringify(condition).replace('%SCRIPT_SUBSTITUTE_CERTIFICATE_IS_VALID%', 'true'))
condition = updatedCondition
serverless.service.provider.compiledCloudFormationTemplate.Conditions.ShouldConsumeCertificate = updatedCondition
serverless.service.resources.Conditions.ShouldConsumeCertificate = updatedCondition
log(`updated certificate condition is ${util.inspect(condition, { depth: 10 })}`)
})
.catch((err) => console.error(err))
function log(msg) {
serverless.cli.log(`define-certificate-is-valid: ${msg}`)
}
And the console logs:
Serverless: Invoke aws:package:finalize
Running javascript file: scripts/define-certificate-is-valid.js
Serverless: define-certificate-is-valid: initializing
!!! writing compiled template file
{ ... }
Serverless: Invoke aws:common:moveArtifactsToPackage
Serverless: Invoke aws:common:validate
Serverless: Invoke aws:deploy:deploy
Serverless: define-certificate-is-valid: initial certificate condition is { 'Fn::Equals': [ '%SCRIPT_SUBSTITUTE_CERTIFICATE_IS_VALID%', 'true' ] }
Serverless: define-certificate-is-valid: updated certificate condition is { 'Fn::Equals': [ 'true', 'true' ] }
So, while it outputs initializing
at the right time, the rest is executed after awsInfo.getStackInfo()
resolves. Meanwhile serverless continues its work before my script can do its job.
Serverless should pause execution while my script its doing its job.
Note that with plugins this can be solved by returning a promise (see serverless/serverless#4557).
But in this case this is not possible since you are calling a node script without a function wrapper, and there is no return statement.
Fixed in the new version 0.7.0, could you please upgrade the module and have a test?
@tommedema Any updates on this issue?
Hey @weixu365 . I actually switched to using plugins, because I didn't like how this plugin requires me to use globals (serverless
and options
)
Let me know if you really want me to test this anyway