When I was building my drawing app I wanted to keep everything on a private git repository on bitbucket. I ran into an issue when I needed to deploy my build folder to production.
I decided to use github pages as my CDN which meant that I needed to deploy my production files to a github repository while being extremely careful that I never pushed source files that were not minified.
My basic file structure:
built files (minified on master, non minified on development)
source for js, html, scss files
server.js (node app)
The basic premise of the solution is to have the base folder which contains everything track bitbucket and the build folder track github. This is as simple as
cding into the build folder and calling
git init and setting it up as if it was any other github repository.
The interesting part is the actual build script that keeps everything connected. The build script also reads the version specified in my html file so that it can tag the commits in both repositories correctly and send version numbers to Rollbar for issue tracking.
Here is the deploy script in its entirety, I’ll break it apart after:
# STEP 1
branch=$(git symbolic-ref HEAD | sed -e 's,.*/\(.*\),\1,')
if [ "$branch" != "development" ] ; then
echo "You must be on the development branch"
# STEP 2
git checkout -b $buildBranch
# STEP 3
ver=$(sed -n -e 's/^.*ver="\([^\"]*\)".*$/\1/p' ./build/index.html)
# STEP 4
git add -A
git commit -a -m "Preparing for release."
git checkout master
git merge --no-ff $buildBranch -X theirs -m "Merge release branch into master"
git tag -a v$ver -m 'version $ver'
# STEP 5
curl https://api.rollbar.com/api/1/sourcemap \
-F access_token=$rollbarToken \
-F version=$ver \
# STEP 6
git add -A
git commit -a -m "Release version $ver"
# STEP 7
git checkout development
git branch -D $buildBranch
# STEP 8
echo "Deploy to Production? y/n"
if [ "$deploy" = "y" ] ; then
git push origin master:gh-pages
curl https://api.rollbar.com/api/1/deploy/ \
-F access_token=$rollbarToken \
-F environment=production \
-F revision=$ver \
- Step 1. We need to make sure we are on the development branch to keep silly errors from happening by accidentally starting on master. Note: We should probably also be checking that our working directory is clean.
- Step 2. We need to create a new branch to be able to build our production files on. In the Nvie branching article, these are like the release branches used to make all of the last minute changes. In my case, that is to only run
gruntto minify and clean my build directory.
- Step 4. Commit the built files to the build branch and merge it into master. The merge flags make sure that in case of a conflict, it should overwrite the things in master.
- Step 5. Send the sourcemap up to Rollbar and then delete it since we don’t want to deploy the sourcemap to github.
- Step 6. Go into the build folder which is the git repo we set up before to track github and commit all of the files.
- Step 7. Go back to the development branch and delete the build branch.
- Step 8. The script optionally deploys to github pages and will send Rollbar a notification that a new deploy happened. By waiting here for user input I have a chance to go and test the build and do last minute verifications.
This build and deploy pattern gives you repository pictures like this.
The graph for the main repository looks a bit silly because it is constantly switching between branches, however this is only because I was deploying after each commit as I fixed some last minute things. Normally the graph has a longer chain on the development branch and then has the two commits for release.
This script is definitely not perfect but it did work great for my needs. The biggest issue I have with how things are set up is that my build folder either contains development files or minified files depending on what branch you are in. That also means that every time someone commits on development they are also committing the built files. With a larger team I could definitely see that leading to constant merge conflicts.
I also want to have my release branches be called release-VERSION_NUM but the version number gets set on the HTML file during the grunt build step which needs to happen on that branch.