About two weeks ago, I met Mike McNeill at an event. We started chatting about JavaScript frameworks and his own brainchild, SailsJS. "Wouldn't it be cool if you could just run a simple command and the app would be automatically deployed to the Internets?" Yes, that would be cool. So we got together, ordered some Pizza and built exactly that: Pull Request #2663 enables sails deploy
, which automatically creates a new Azure Website with the locally developed sails app running.
Talking to Azure
Sails makes heavy use of Node Machines, an open standard for JavaScript functions. They are essentially meta data wrappers for APIs, allowing other applications to consume the packages in a standardized way. We started by building a Machine Pack for Azure, which is capable of setting up the local Azure account, creating and updating websites and uploading files (amongst other website-related thing). It is also able to upload scripts (Bash, Node, Python, Powershell), which are exposed via REST API. This is important: We're able to locally create a script, upload it to the website, and execute it on the website's machine by calling a protected REST API. It's the same concept I previously used to update Ghost instances running on Azure Websites. Let's check out the flow:
Do we need to create a website?
The command sails deploy
accepts a website name and deployment username/password, in which case we can skip thinking about whether or not the user has rights to create an Azure Website. If we're just going with sails deploy
and need to create a new website, we start by checking the local environment for an Azure account. Users that have the Node-powered Azure-CLI installed won't have to do anything, while users without it are asked to authenticate the local environment (they won't have to install the CLI though).
Once we're authenticated, we move forward to check if the website already exists in the current account. If so, we could just deploy to it - if not, we're creating one.
Package it up!
We're ready to ship things up, so we're zipping the local folder, excluding unnecessary things. We could have used Git to deploy, but Mike felt strongly that SailsJS shouldn't have a Git requirement. Once Node is done creating a ZIP package, we'll go ahead and upload it to a temporary folder on the website's virtual machine.
Remote Scripting
The next step is the cool one: We're uploading a local script containing commands to clean the site, unzip the package and run npm install
to Azure, where it is automatically assigned a REST api - allowing us to call the script, fetch its status and output. Once the script is uploaded, we simply call its API, pipe through the output to the local machine and watch as Azure is setting up the SailsJS website.
Moving forward
Since we can execute Bash and PowerShell scripts on the machine that is supposed to run the sails app, we can pretty much do whatever we want - and enable scenarios that are more powerful than what we have built so far. We could also easily enable the same scenario for Ember, Angular or various other environments. If you want to see some code, here are the respective repositories:
- SailsJS, a Realtime MVC Framework for Node.js
- machinepack-azure, the Node Machine able to talk to Azure Websites
- Kudu, the engine running Azure Websites