Awesome
NowFlow - Automate your Zeit Now Deployments ·
Out-of-the-box, Zeit now-CLI does not offer any opiniated way to organize your variables on a per environment basis (e.g. database credentials, keys, ...). As of version 9.2.5, bugs still exist to deploy to AWS lambdas, and no support is provided to make functions deployed to Google Cloud to react to other events than an HTTPS request (e.g. Google Cloud Functions can react to Pub/Sub topics (very usefull for event-driven architecture), Google Storage or Firebase database changes). NowFlow enables all those features by simply configuring your traditional now.json.
NowFlow offers a strategy to manage multiple environments for any type of nodejs projects. It works especially well when it is combined with Webfunc. Together, those 2 projects allow to deploy Express-like apps to the most popular serverless platforms (Zeit Now, AWS Lambdas, GCF) and will unlock apps that can react to Google Pub/Sub Topics and Google Storage changes (more info in the FAQ / What Problems Does NowFlow Solve).
Table of Contents
Install
Prerequisite
Zeit now-CLI must have been installed globally. The lastest stable version of now that works is @9.0.0. We're currently working on fixing the issues with more recent versions of now.
npm install now@9.0.0 -g
Install NowFlow
Embed it inside your project as a dev dependency to run it through npm (RECOMMENDED WAY):
npm install now-flow --save-dev
Or install it globally:
npm install now-flow -g
How To Use It?
Basics
Configure your now.json once, and then replace all the manual steps above with a single command similar to nowflow production
(or npm run deploy:prod
if you've configured that task in your package.json, which is the recommended way).
Example:
now.json
{
"env": {
"active": "default",
"default": {
"hostingType": "localhost"
},
"staging": {
"hostingType": "gcp",
"gcp": {
"functionName": "yourapp-test",
"memory": 128
}
},
"production": {
"hostingType": "now",
"scripts": {
"start": "NODE_ENV=production node index.js"
},
"alias": "yourapp-prod"
}
}
}
To deploy the production environment, simply run:
nowflow production
This will deploy to Zeit Now and make sure that:
- The package.json that is being deployed will contain the start script
"NODE_ENV=production node index.js"
. - The
env.active
property of the now.json is set toproduction
. - Once the deployment to Zeit Now is finished, it is automatically aliased to
yourapp-prod
.
On the contrary, to deploy the staging environment, simply run:
nowflow staging
This will deploy to Google Cloud Functions and make sure that:
- The
env.active
property of the now.json is set tostaging
. - The now.json contains a
gcp
property identical to the one defined in the staging configuration.
No more deployment then aliasing steps. No more worries that some environment variables have been properly deployed to the right environment.
Learn more details on how NowFlow works in the How Does NowFlow Work? under the FAQ section.
Deploying To Google Functions or AWS
IMPORTANT: Before deploying to Google Functions (GCP), YOU'LL HAVE TO ENABLE BILLING under the specific project hosting your function. Simply browse to your account (https://console.cloud.google.com/), click on the Cloud Functions, and then click on Enable Billing.
Before deploying to GCP or AWS, you'll have to login first using:
now gcp login
or
now aws login
After using one of the above command, you'll be prompt to select a project within your GCP or AWS account. Once selected, your function will be deployed withing that project.
To change to another project, re-rerun the commands above.
Google Cloud Functions for Pub/Sub or Storage Events
This is only possible when using the Webfunc project that allows to write Express-like apps to run everywhere. There are examples on that project documentation here.
The Most Minimal Setup
You must first create a now.json file in the root of your project's directory as follow:
{
"env": {
"production": {
"alias": "yourapp-prod"
},
"test": {
"alias": "yourapp-test"
}
}
}
Make sure there is at least one environment defined under the env property. Then simply run:
nowflow production
The above will:
- Deploy your project to Zeit using the production config defined in the now.json.
- Will alias that deployment using the alias defined in the production config defined in the now.json (i.e. 'yourapp-prod').
Skipping Aliasing
If you haven't defined an alias
property for a specific environment, then now aliasing will be perfomed after deployment to that environment if the hostingType
was now
. If on the other hand an alias
was defined, but you wish to prevent any aliasing, use the following:
nowflow production --noalias
Modifying The package.json's "scripts" property For Each Environment
As described in the intro, this is one of the key feature of now-flow. In the now.json, under each specific environment, you can add a "script" property that will completely override the one defined inside the package.json during the deployment. Once the deployment is completed, the package.json is restored to its original state.
now.json:
{
"env": {
"production": {
"scripts": {
"start": "NODE_ENV=production node index.js"
},
"alias": "yourapp-prod"
},
"test": {
"scripts": {
"start": "NODE_ENV=test node index.js"
},
"alias": "yourapp-test"
}
}
}
nowflow production
In the example above, we're making sure that the package.json contains a start script so that now can, for example, correctly start an express server.
If you're using the serverless web framework Webfunc, the above command will also make sure that the property env.active
of the now.json is also set to production
before deploying.
FAQ
What Problems Does NowFlow Solve?
TL;DR - It removes all the manual steps required before deploying to a specific environment (e.g. updating the start
task in the package.json, changing the config in the now.json) and it adds support for Google Cloud Functions reacting to other events than an HTTPS request.
Out-of-the-box, Zeit now-CLI does not offer any opiniated way to organize your variables on a per environment basis (e.g. database credentials, keys, ...). As of version 9.2.5, bugs still exist to deploy to AWS lambdas, and no support is provided to make functions deployed to Google Cloud to react to other events than an HTTPS request (e.g. Google Cloud Functions can react to Pub/Sub topics great for event-driven architecture, Google Storage or Firebase database changes). NowFlow enables all those features by simply configuring your traditional now.json. This is an opiniated design choice that contrast with maintaining multiple now.json files (e.g. now.dev.json, now.staging.json, now.prod.json, ...) mainly driven by the desire to make working on the localhost easier as well as complying to what the now infrastructure already understand. If your interested in multiple now.json per environment, check the awesome project created by Jesse Ditson called now-deploy.
To understand a bit more how NowFlow works, let's have a look at all the manual steps that would be required before being able to deploy to a specific environment (e.g. staging vs production) using the simple now
command line:
- Update the
start
script in the package.json specific to your environment if you deploy to Zeit Now (e.g. production:"start": "NODE_ENV=production node index.js"
, staging:"start": "NODE_ENV=staging node index.js"
, localhost:"start": "node-dev index.js"
). - If you're deploying to Google Cloud Functions, you might need to configure the
gcp
property in the now.json. - If you're using the Webfunc serverless web framework, then you also need to set up the
env.active
property to the target environment in the now.json. - Run the right command (e.g.
now
if deploying to Zeit Now, andnow gcp
if deploying to Google Cloud Functions). - Potentially alias your deployment if your're deploying to Zeit Now:
- Update the
alias
property of the now.json file to the alias name specific to your environment.- Run
now alias
This process is obviously proned to errors. It is also tedious if you're deploying often. This is why we created now-flow.
How Does NowFlow Work?
NowFlow makes sure that both your package.json and your now.json are configured properly based on the environment you're targeting. It does that in 2 steps:
- Create a temporary backup of your files in case something goes wrong. That's why you should see that during your deployment, the following 2 files are created: .package.backup.json, .now.backup.json. Those files will automatically deleted if the deployment is successful.
- Modify both your package.json and your now.json based on the environment configuration contained in the now.json.
- Invoke the
now
command (ornow <hostingType>
) to deploy. - If aliasing is required, then invoke
now alias
. - If the deployment is successful, or if an error but is is successfully intercepted and displayed to the terminal, then:
- Restore both the package.json and your now.json to their original state.
- Delete the backup files created in step #1.
This Is What We re Up To
We are Neap, an Australian Technology consultancy powering the startup ecosystem in Sydney. We simply love building Tech and also meeting new people, so don't hesitate to connect with us at https://neap.co.
Our other open-sourced projects:
Web Framework & Deployment Tools
- webfunc: Write code for serverless similar to Express once, deploy everywhere.
- now-flow: Automate your Zeit Now Deployments.
GraphQL
- graphql-serverless: GraphQL (incl. a GraphiQL interface) middleware for webfunc.
- schemaglue: Naturally breaks down your monolithic graphql schema into bits and pieces and then glue them back together.
- graphql-s2s: Add GraphQL Schema support for type inheritance, generic typing, metadata decoration. Transpile the enriched GraphQL string schema into the standard string schema understood by graphql.js and the Apollo server client.
- graphql-authorize: Authorization middleware for graphql-serverless. Add inline authorization straight into your GraphQl schema to restrict access to certain fields based on your user's rights.
React & React Native
- react-native-game-engine: A lightweight game engine for react native.
- react-native-game-engine-handbook: A React Native app showcasing some examples using react-native-game-engine.
Tools
- aws-cloudwatch-logger: Promise based logger for AWS CloudWatch LogStream.
License
Copyright (c) 2018, Neap Pty Ltd. All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
- Neither the name of Neap Pty Ltd nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NEAP PTY LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
<p align="center"><a href="https://neap.co" target="_blank"><img src="https://neap.co/img/neap_color_horizontal.png" alt="Neap Pty Ltd logo" title="Neap" height="89" width="200"/></a></p>