weixu365 / serverless-scriptable-plugin

Adding script support to Serverless 1.x which enables you to customize Serverless behavior without writing a plugin.
MIT License
111 stars 11 forks source link

post processing cloudformation outputs #8

Closed tommedema closed 6 years ago

tommedema commented 6 years ago

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?

weixu365 commented 6 years ago

Personally, I prefer to use command line to get the serviceEndpoint:

node_modules/.bin/serverless info --verbose | grep 'ServiceEndpoint' | sed s/ServiceEndpoint\:\ //g

Some benefits are:

Then the code will be

/* global serverless */

console.log('Compile-web: compiling web package with cloudformation outputs')

const shell = require('shelljs')

const region = serverless.service.provider.region
const apiRoot = shell.exec('node_modules/.bin/serverless info --verbose | grep 'ServiceEndpoint' | sed s/ServiceEndpoint\:\ //g').stdout

console.log(`Gathered cloudformation outputs:\n
  region: ${region}\n
  apiRoot: ${apiRoot}`)

if (shell.exec(`
    REACT_APP_AWS_REGION=${serverless.service.provider.region}
    REACT_APP_API_ROOT=${apiRoot} \
    npm run build`).code !== 0
  ) {
  shell.echo('Error: we build failed with exit code !== 0')
  shell.exit(1)
}
tommedema commented 6 years ago

Thanks for the input. Well, if these are the 2 "cleanest" options, I will accept that I was not totally off in my approach.

I'm still getting used to serverless, but sometimes feel like it does require a bit of hacking to get a production stack working.