weixu365 / serverless-scriptable-plugin Goto Github PK
View Code? Open in Web Editor NEWAdding script support to Serverless 1.x which enables you to customize Serverless behavior without writing a plugin.
License: MIT License
Adding script support to Serverless 1.x which enables you to customize Serverless behavior without writing a plugin.
License: MIT License
This looks great. However, where can I find a list of hooks to attach to?
If you require directory-local dependencies inside a script called by serverless-scriptable-plugin
and use relative imports:
const myLib = require('./myLib')
it will try to resolve './myLib' against a base path of <PROJECT_ROOT>/node_modules/serverless-scriptable-plugin/index.js
A workaround is
const myLib = require(`${__dirname}/myLib`)
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.
Hey, I missed that the runcmd
string is exposed to users, sorry! See here:
custom:
scriptable:
hooks:
before:migrate:runcmd: echo before migrating
after:migrate:runcmd: echo after migrating
commands:
migrate: echo Running migration
Before there's too much uptake, how about if I change that to something cleaner? For example, how about a change for getting this:
custom:
scriptable:
hooks:
before:command:migrate: echo before migrating
after:command:migrate: echo after migrating
commands:
migrate: echo Running migration
Hi there,
I am using your plugin to build my web app after a serverless deploy
returns relevant cloudformation outputs, such as the API gateway path.
Ultimately I did it like so:
serverless.yml
custom:
scriptHooks:
after:aws:info:gatherData: scripts/compile-web.js
compile-web.js
/* global serverless */
console.log('Compile-web: compiling web package with cloudformation outputs')
const shell = require('shelljs')
const awsInfo = serverless.pluginManager.plugins.find(p => p.constructor.name === 'AwsInfo')
const getOutput = key => awsInfo.gatheredData.outputs.find(o => o.OutputKey === key).OutputValue
const region = serverless.service.provider.region
const apiRoot = getOutput('ServiceEndpoint')
console.log(`Gathered cloudformation outputs:\n
region: ${region}\n
apiRoot: ${apiRoot}`)
if (shell.exec(
`cd ${__dirname}/../src/web && \
REACT_APP_AWS_REGION=${region} \
REACT_APP_API_ROOT=${apiRoot} \
npm run build`).code !== 0
) {
shell.echo('Error: we build failed with exit code !== 0')
shell.exit(1)
}
My concern: it seems not very clean. Would like to check-in with people here what you think. Is there a better approach?
Hi there, the plugin works smooth when I declare the scripthooks in the main serverless.yml file. But to keep a clean yml, I have split my custom declarations in another file, referenced like this:
custom: ${file(./custom.yml)}
the rest of the variables declared there work fine, except for the scriptHooks one:
env:
app:
...
scriptHooks:
after:aws:deploy:finalize:cleanup: ./export-frontend-config.js
So, the above scriptHooks declaration works only when declared in the serverless.yml, but not in the custom.yml.
Thanks for any suggestion.
Best regards,
There is an error with this repository's Renovate configuration that needs to be fixed. As a precaution, Renovate will stop PRs until it is resolved.
Location: renovate.json
Error type: Invalid JSON (parsing failed)
Message: Syntax error: expecting String near : true, }
Would love if there was a way to pass into the custom script either SLS outputs or SLS cloudformation Refs. This way, you could act on dynamic resources that have been created.
This is a question, not an issue.
I see that this plugin supports running bash scripts.
My serverless.yml creates some AWS resources.
I want my bash script to know the ARN's of those various resources.
Is this possible? Is there an example of this?
Thanks!
By
@weixu365 I've modified your plugin to support custom commands instead of hooks.
commands executed via serverless have the big advantage of allowing to feed the serverless
variable including environment to scripts, e.g. for running migrations etc.
Would you welcome a PR of "command" functionality back into your lib?
Will able to do more testing later but I had issue getting the plugin to trigger within a docker environment that only has ash shell (alpine). Does the plugin make certain assumption about the shell environment? I had a bash script that had a shebang pointing to the bash installed inside docker but it wasn't launched from bash.
Well its pretty self explanatory. If i do a normal deploy serverless deploy
, then it works ok, but if i deploy only the function like so serverless deploy function -f appsync
, nothing happens
I tried with the lifecycle methods that are listed in the serverless docs
https://serverless.com/framework/docs/providers/aws/guide/plugins/
I use these two plugins:
plugins:
- serverless-appsync-plugin
- serverless-webpack
Tried with different order and it was the same, commands from this plugin were never triggered.
When the runCommand
exits with a non-zero exit code, an Exception occurs. This exception is not caught, resulting in a long stacktrace in the console, that only points to this plugin itself.
I think the error resulting from execSync
should be caught and a simple message Command <command>
should be printed. Then the serverless process that triggered the hook should be stopped.
Use case: linting automatically before a deploy/package
This is more of a question than a bug.
I'm using AWS app-sync with Serverless. Can we change the content of template file before the package is generated for deployment. Cahnge should not be in the original file but in the package generated only.
For Example: I want to use some code from a json file in template file. I'll add a placeholder for it. Druing deployment, before pacakage is generated, I want the placeholder to be replaced with the actual code in the generated file.
In the .serverless/lambdaname.zip file it is always have node_modules/sharp/buidl/Release/sharp-darwin-x64.node
I know if I can run the following command it will enforce it to install the sharp-linux version. What is the right setting to run this before zip happens?
npm install --arch=x64 --platform=linux sharp
Thanks Lot
Cheers
Gary
Getting this warning on Serverless 1.41.1:
WARNING: Plugin Scriptable uses deprecated hook after:deploy:createDeploymentArtifacts, use package:createDeploymentArtifacts hook instead
(thanks for the great plugin!)
I'm using the serverless-stack-output plugin which is using after:deploy:deploy
and I still can't get serverless-scriptable-plugin
to fire AFTER it, whether I use after:deploy:finalize
or after:deploy:deploy
I love using this plugin. I've found that when I specify a build script to run when deploying my serverless service, if the build script fails, the serverless framework doesn't seem to emit an error code. This causes the CI job to report a success instead of failure.
Have you seen this issue before and do you know if it's a setting in the serverless framework, or in this plugin?
Thanks!
This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.
These updates have all been created already. Click a checkbox below to force a retry/rebase of any.
chai
, eslint
, mocha
, nyc
, semantic-release
, tmp
).github/workflows/build.yml
actions/checkout v4
actions/setup-node v4
actions/checkout v4
actions/setup-node v4
.github/workflows/stale.yml
actions/stale v9.0.0
package.json
bluebird 3.7.2
chai 4.4.1
color-support 1.1.3
commitizen 4.3.0
cz-conventional-changelog 3.3.0
eslint 8.56.0
eslint-config-airbnb-base 15.0.0
eslint-plugin-import 2.29.1
mocha 10.3.0
nyc 15.1.0
semantic-release 23.0.2
tmp 0.2.1
minimist 1.2.8
Describe the bug
Since version 1.2 serverless variables (eg. ${self:stage.provider}
) aren't being resolved to their values anymore.
To Reproduce
Environment:
Bitbucket Pipeline CI with Docker image node:14.15.0
Versions:
"serverless": "^2.38.0",
"serverless-scriptable-plugin": "^1.2.1",
Relevant serverless.yml sections:
provider:
name: aws
runtime: nodejs14.x
stage: ${opt:stage, 'nonprod'}
plugins:
- serverless-scriptable-plugin
custom:
scriptHooks:
after:package:initialize: STAGE=${self:provider.stage} npm run build:views && STAGE=${self:provider.stage} npm run build:editor
Running a serverless package
results in:
Running command: STAGE=${self:provider.stage} npm run build:views && STAGE=${self:provider.stage} npm run build:editor
/bin/sh: 1: Bad substitution
Expected behavior
It used to properly parse them. Pipeline run from ~24 hours ago:
Running command: STAGE=nonprod npm run build:views && STAGE=nonprod npm run build:editor
Additional context
It also seems to be happening when running locally on my macOS Catalina.
Hi,
i have used your plugin and it is a good help for my project.
But the scriptable plugin is only limited to execute javascript files.
Could it be a good extension to allow any kind of scripts?
The code that could handle that:
const execSync = require('child_process').execSync;
function exec(description, command) {
console.log(`Package: ${description} : ${command}`);
var output = execSync(command).toString('utf8');
if (output) {
console.log(output);
}
}
And the configuration in the serverless.yml could look like
custom:
scriptHooks:
before:deploy:createDeploymentArtifacts: make deploy
This would increase the reusability in many different projects programming language independent.
In our case we want to execute python scripts that are execute before some kind of deployment
I'm trying to execute a command after serverless-offline
is started. I found a place with hooks in the source and try to do:
custom:
scriptHooks:
offline:start:end: echo "Hello world!"
Do I understand the logic correctly? Is serverless-scriptable
supposed to work with other serverless plugins?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.