Coordinating Deployments With Firebase, AngularJS, Git, And GitHub
At work, we're on our way towards a "continuos deployment" workflow; but, we're not quite there just yet. As such, each deployment to production requires a cross-team, coordinated effort of testing and verifying to make sure that the new code didn't make the staging or the production environment go Boom! Managing this coordination in a Slack channel is messy and confusing. So, I wanted to see if I could parle this into a learning opportunity and come up with a stop-gap solution that helps the operations team while, at the same time, teaching me a bit more about AngularJS and Firebase, a powerful Backend-as-a-Service (BaaS).
Run this demo in my Git Deployment Checklist project on GitHub.
View my Git Deployment Checklist project on GitHub
Ultimately, each deployment starts with a list of git commits that gives the team a heads-up as to what is about to go live. And, since each git commit should be meaningful (interactive rebase all the things, immediately!), I think it's fair to say that each commit roughly equates to a feature or a bug fix. So, I wanted to create a little application that takes the list of git commits and provides a testing and verification toggle for each commit in each environment (staging and production).
Of course, the testing and verification of commits isn't all that helpful if the cross-team efforts are not kept in sync. So, I wanted to use Firebase to make sure that commits verified by one user were immediately synchronized to every other user involved in the deployment.
Since this application operates entirely on the client-side, I'm using Firebase as a true Backend-as-a-Service (BaaS) provider. As such, access permissions have to live in my private Firebase configuration. Since this AngularJS application does not require any authentication, I had to allow unauthenticated access to each deployment. But, the address of the deployment is a long, pseudo-random string. And, using the Firebase security rules, I've disabled the ability for people to listen for arbitrary data changes. As such, you have to have a direct link to the deployment page in order to be able to see it:
{
// By default, lock down all reads and writes to the entire data store. This means that
// all access will have to be explicitly opened up to child nodes.
"rules": {
".read": false,
".write": false,
// Open up writes on the deployments subtree since anyone should be able to start
// a new deployment and store it in the deployments collection. However, since
// reads are locked down, people can't "listen" for arbitrary data changes at this
// level (such as "value" and "child_added" events).
"deployments": {
".write": true,
// Open reads and writes to any individual deployment since anyone with a link to
// the deployment URL can access it. These are pseudo-random, complex end-points and
// are secured through obfuscation.
"$deployment": {
".write": true,
// NOTE: Allowing a read on non-existent data so that the UI can be notified when
// the deployment has been nullified (ie, deleted).
".read": "! data.exists() || data.child( 'createdAt' ).val() >= ( now - ( 12 * 60 * 60 * 1000 ) )",
// Since we are locking the read access based on time deltas, we have to ensure
// that all new deployments have a createdAt timestamp.
".validate": "newData.hasChildren( [ 'createdAt' ] ) && newData.child( 'createdAt' ).isNumber()"
}
}
}
}
I don't know too much about the breadth of Firebase security features just yet; but, at first look, it seems pretty cool. And, it offers a complete authentication and user management system as well. Definitely something I'll be looking into in the future.
A year ago, when I first looked at using Firebase in AngularJS, I thought that it was a bit of leaky abstraction. Meaning, at least in the way that I organized the code, the application had to know too much about Firebase as a data-storage implementation. But, this time, I felt like I was able to keep a lot of the code separate.
The part of the application that listens for data changes, however, is still highly coupled to Firebase and the concept of value events and data snapshots. But, I have a sneaking suspicion that using more of a Flux-based architecture with "data stores" and "change events" will completely remove that coupling. Unfortunately, at this time, I don't really understand Flux architecture. Hopefully, I can take this project and evolve it into something that uses Redux (or similar) in order to figure out how to truly encapsulate the Firebase implementation.
Anyway, this was just a fun exploration of AngularJS and Firebase. One of the best parts about using Firebase is that I can completely host little applications, like this one, on GitHub Pages.
Want to use code from this post? Check out the license.
Reader Comments