{"action":"created","comment":{"url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/pulls/comments/42880993","id":42880993,"diff_hunk":"@@ -0,0 +1,432 @@\n+---\n+layout: post\n+title: \"Docker, Elastic Beanstalk and Git: a useful trinity for agile development? Part II\"\n+date: 2015-10-26 05:00\n+comments: true\n+author: Duncan Rutland\n+bio: Duncan Rutland is a Sr. Solution Architect at Rackspace within the Fanatical Support for AWS team.\n+published: true\n+categories:\n+- AWS\n+- Docker\n+- Git\n+- Elastic Beanstalk\n+authorIsRacker: true\n+---\n+\n+# Docker, Elastic Beanstalk and Git: a useful trinity for agile development? Part II\n+\n+By Duncan Rutland, Sr. Solution Architect, Rackspace 2015\n+\n+---\n+\n+## I - Introduction\n+\n+In [Part I](https://developer.rackspace.com/blog/trinity-article-I/) of this series we depicted a fictional scenario for agile development using a simple \"Hello World\" application composed of just a single UI layer. During this fanciful (albeit contrived) exposition, we glossed over many of the underlying details for the sake of brevity. In this article, we will take a little peek under the covers and explain in more depth how we achieved rapid automated deployments of of immutable application containers to remote test environments.\n+ \n+<!-- more -->\n+\n+**Disclaimer**: The demonstration code in the corresponding [repository] (https://github.com/djrut/trinity) is for illustrative purposes only, and may not be sufficiently robust for production use. Users should carefully inspect sample code before running in a production environment. Use at your own risk.\n+\n+**Disclosure**: The idea of a Makefile mechanism to automate container preparation, build, push etc. was inspired by [this](http://victorlin.me/posts/2014/11/26/running-docker-with-aws-elastic-beanstalk) excellent article by Victor Lin.\n+\n+## III - Workflow\n+\n+We will begin by outlining the workflow when working with Docker, EB and Git in this scenario. The high-level steps are as follows:\n+\n+1. Initial Git Steps\n+\t- Pull from remote repository\n+\t- Create feature/bug-fix branch\n+2. Create Elastic Beanstalk Environment\n+\t- Create new Elastic Beanstalk test\n+\t- Bind to branch\n+\t- Test initial deployment\n+3. Feature/bugfix Development\n+\t- Write code for new feature or bug-fix\n+\t- Commit changes to feature/bug-fix branch\n+4. Docker container build\n+\t- Build new Docker image\n+\t- Push to remote repository\n+5. Deploy to test EB Environment\n+\n+Let us now delve deeper into the inner-workings within each of these steps. \n+\n+## IV - Initial Git steps \n+\n+The first two steps involve pulling (or cloning if a fresh start is required) the repository, and creating a feature/bug-fix branch. Pretty straightforward stuff, and there are no surprises here so no need to expand further, _although_ I would like to take this opportunity to describe some of the Git-specific configuration required.\n+\n+### Git Configuration: .gitignore\n+\n+~~~bash .gitignore\n+*.swp\n+.bundle\n+Docker/*.tar\n+.DS_Store\n+\n+# Elastic Beanstalk Files\n+.elasticbeanstalk/*\n+!.elasticbeanstalk/*.cfg.yml\n+!.elasticbeanstalk/*.global.yml\n+~~~\n+\n+The pertinent line here is `Docker/*.tar` which instructs Git to ignore and of the tar balls created by `git archive` to be included in the Docker image in later steps, but _not_ to ignore the entire `Docker/` directory which contains configuration state in the form of one (or more) Dockerfile(s) that we would like to manage under revision control.\n+\n+**NOTE:** Additional configuration state contained in `.ebextensions/` directory will *not* be ignored since it resides at root of project.\n+\n+### Git Configuration: .gitattributes\n+\n+Some special merge behavior is required for a single file in the project: `Dockerrun.aws.json`. This file contains the configuration that Elastic Beanstalk uses to deploy containers, and contains branch-specific state (namely a pointer to specific Docker image for each environment). \n+\n+~~~\n+Dockerrun.aws.json merge=ours\n+~~~\n+\n+The raison d'etre of this little morsel of configuration is to prevent merge conflicts when we, for example, perform a `git merge master` inside our feature/big branch, which (as good CI citizens) we should be doing frequently to remain in sync with the mainline/trunk. Since each branch will have it's own version of `Dockerrun.aws.json`, we want any merge of master to retain the local branch version. \n+\n+**NOTE:** This configuration needs to be inserted into the project's `.git/config` file using the following:\n+\n+~~~bash\n+git config merge.ours.driver true\n+~~~ \n+\n+## Create Elastic Beanstalk Environment\n+\n+If this is a newly created branch, we will need to instruct Elastic Beanstalk to build a new environment and bind it to the branch.\n+\n+This is easily done using the `eb create [REPOSITORY]-[BRANCH] --branch_default` command as shown here:\n+\n+~~~bash\n+eb create trinity-bug-002 --branch_default\n+~~~\n+\n+This command kicks-off the `createEnvironment` workflow inside Elastic Beanstalk Service that:\n+\n+- Creates an initial application archive and uploads to S3\n+- Points the env config to S3\n+- Creates security groups\n+- Creates auto-scale groups and EC2 instances\n+- Creates CloudWatch alarms\n+- Pulls Docker images from remote repository onto the EC2 instances\n+- Launches containers\n+\n+One can check that the environment launch was successful by checking the Status and Health indicators using the `eb status` command:\n+\n+~~~bash\n+prompt> ~/trinity/bug-002: eb status\n+Environment details for: trinity-bug-002\n+  Application name: trinity\n+  Region: us-west-2\n+  Deployed Version: v1_1-15-gc685\n+  Environment ID: e-psxs3vh7t2\n+  Platform: 64bit Amazon Linux 2015.03 v2.0.2 running Docker 1.7.1\n+  Tier: WebServer-Standard\n+  CNAME: trinity-bug-002-rbp4qmz5i4.elasticbeanstalk.com\n+  Updated: 2015-10-15 01:34:05.054000+00:00\n+  Status: Ready\n+  Health: Green\n+~~~ \n+\n+Green is good! Note that this configuration is persisted in the `branch-defaults:` section of the `.elasticbeanstalk/config.yml` located in the project root. Here is an example:\n+\n+~~~bash\n+branch-defaults:\n+  bug-002:\n+    environment: trinity-bug-002\n+  issue-001:\n+    environment: trinity-test-001\n+  master:\n+    environment: trinity-prod\n+global:\n+  application_name: trinity\n+  default_ec2_keyname: null\n+  default_platform: Docker 1.7.1\n+  default_region: us-west-2\n+  profile: eb-cli\n+  sc: git\n+~~~ \n+## \n+\n+## Feature/Bugfix Development\n+\n+We will not go into much detail here, suffice to say that development of _some_ feature of bug fix takes places. The important thing to note is that a commit of the changes **MUST** take place before proceeding to create the new Docker image since (as we shall see) the make process uses `git archive` to roll-up the application for inclusion in the image. \n+\n+## Docker container build\n+\n+Now we get to the meat of the process. In [Part I](https://developer.rackspace.com/blog/trinity-article-I/) of this series we showed how two simple commands `make` and `eb deploy` were all that was required to create a brand new immutable Docker image and deploy to an external Elastic Beanstalk Environment. Let's now delve into the `make` component.\n+\n+Those that are familiar with C/C++ development in Unix/Linux will be familiar with the [make](https://www.gnu.org/software/make/) utility: as originally conceived in the 1970s, it was intended to standardize and simplify the process of compiling and linking large C projects with lots of interdependencies. Due to it's venerable status and tenure, the make utility is present by default in most Unix/Linux distributions.\n+\n+HOWEVER: for our purposes, it can also be used to provide a simple way to group shell commands and enforce a (very basic) workflow. This turns out to very handy when working with container builds a things can (and do) fail from time-to-time. \n+\n+Most of the magic happens in the [Makefile](https://www.gnu.org/software/make/manual/html_node/Makefiles.html), a simple text configuration file that resides in the project root. Here is the `Makefile` we used in this scenario:\n+\n+~~~\n+USER\t\t:= \"djrut\"\n+REPO\t\t:= \"trinity\"\n+BUILDDIR\t:= \"Docker\"\n+VERSION\t\t:= $(shell git describe --tags)\n+IMAGE\t\t:= $(USER)/$(REPO):$(VERSION)\n+\n+.PHONY: all prep build push commit clean\n+\n+all:\t| prep build push commit clean\n+\n+prep:\n+\t@echo \"+\\n++\\n+++ Building Git archive...\"\n+\t@git archive -o $(BUILDDIR)/$(REPO).tar HEAD\n+\n+build:\n+\t@echo \"+\\n++\\n+++ Performing build of Docker image...\"\n+\t@docker build -t $(IMAGE) --force-rm --rm $(BUILDDIR)\n+\n+push:\n+\t@echo \"+\\n++\\n+++ Pushing image to Dockerhub...\"\n+\t@docker push $(IMAGE)\n+\n+commit:\n+\t@echo \"+\\n++\\n+++ Committing updated Dockerrun.aws.json...\"\n+\t@Docker/build_dockerrun.sh > Dockerrun.aws.json\n+\t@git add Dockerrun.aws.json\n+\t@git commit --amend --no-edit\n+\n+clean:\n+\t@echo \"+\\n++\\n+++ Cleaning-up... \"\n+\t@rm -v $(BUILDDIR)/$(REPO).tar\n+~~~\n+\n+\n+Let's break this down section by section. First up: Variable definitions.\n+\n+### Makefile Variable Definitions\n+\n+~~~\n+USER        := \"djrut\"\n+REPO        := \"trinity\"\n+BUILDDIR    := \"Docker\"\n+VERSION     := $(shell git describe --tags)\n+IMAGE       := $(USER)/$(REPO):$(VERSION)\n+~~~\n+\n+This first block is where we set variables for use throughout the `Makefile`. This is a familiar syntax, one thing to note is the `:=` operator which implies \"[simple](https://www.gnu.org/software/make/manual/html_node/Setting.html#Setting)\" variable expansion: the left-hand operand (e.g. VERSION) is immediately set to the expanded result of the right-hand operand. This is in contrast with the recursive expansion `=` operator, where the value of the left-hand operand is not set until the time of reference.  \n+\n+- **USER:** This is the name of Git/DockerHub username, which in our case are identical\n+- **REPO:** The name of the Git and Dockerhub repository, again these are identical\n+- **BUILDDIR:** This identifies the directory path under project root that will contain the Dockerfile used to build the image, and also where the Git archive is dumped.\n+\t- **NOTE:** For this scenario it is necessary for a Dockerfile **not** to reside in project root otherwise EB create/deploy will build a fresh image each time using _that_ `Dockerfile` instead of simply referencing an existing image defined in the `Dockerrun.aws.json` configuration file (see below).\n+- **VERSION:** This variable contains the version tag to apply to the Docker image. In this case, we use the builtin `shell` command to run `git describe --tags`. This ensures that we have a consistent mapping between a version of the application in Git, Docker and ElasticBeanstalk. NOTE: Alternative naming strategies are possible also, including using the branch name.","path":"_posts/2015-10-26-trinity-article-II.md","position":216,"original_position":216,"commit_id":"dbe1f2906a8dfbb8ac267472d0a9812434cf798b","original_commit_id":"dbe1f2906a8dfbb8ac267472d0a9812434cf798b","user":{"login":"catlook","id":5709104,"avatar_url":"https://avatars.githubusercontent.com/u/5709104?v=3","gravatar_id":"","url":"https://api.github.com/users/catlook","html_url":"https://github.com/catlook","followers_url":"https://api.github.com/users/catlook/followers","following_url":"https://api.github.com/users/catlook/following{/other_user}","gists_url":"https://api.github.com/users/catlook/gists{/gist_id}","starred_url":"https://api.github.com/users/catlook/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/catlook/subscriptions","organizations_url":"https://api.github.com/users/catlook/orgs","repos_url":"https://api.github.com/users/catlook/repos","events_url":"https://api.github.com/users/catlook/events{/privacy}","received_events_url":"https://api.github.com/users/catlook/received_events","type":"User","site_admin":false},"body":"...  Docker, and ElasticBeanstalk. ...","created_at":"2015-10-23T15:50:03Z","updated_at":"2015-10-23T15:50:03Z","html_url":"https://github.com/rackerlabs/docs-developer-blog/pull/112#discussion_r42880993","pull_request_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/pulls/112","_links":{"self":{"href":"https://api.github.com/repos/rackerlabs/docs-developer-blog/pulls/comments/42880993"},"html":{"href":"https://github.com/rackerlabs/docs-developer-blog/pull/112#discussion_r42880993"},"pull_request":{"href":"https://api.github.com/repos/rackerlabs/docs-developer-blog/pulls/112"}}},"pull_request":{"url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/pulls/112","id":48378605,"html_url":"https://github.com/rackerlabs/docs-developer-blog/pull/112","diff_url":"https://github.com/rackerlabs/docs-developer-blog/pull/112.diff","patch_url":"https://github.com/rackerlabs/docs-developer-blog/pull/112.patch","issue_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/issues/112","number":112,"state":"open","locked":false,"title":"Trinity Article II - Initial commit","user":{"login":"djrut","id":13618091,"avatar_url":"https://avatars.githubusercontent.com/u/13618091?v=3","gravatar_id":"","url":"https://api.github.com/users/djrut","html_url":"https://github.com/djrut","followers_url":"https://api.github.com/users/djrut/followers","following_url":"https://api.github.com/users/djrut/following{/other_user}","gists_url":"https://api.github.com/users/djrut/gists{/gist_id}","starred_url":"https://api.github.com/users/djrut/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/djrut/subscriptions","organizations_url":"https://api.github.com/users/djrut/orgs","repos_url":"https://api.github.com/users/djrut/repos","events_url":"https://api.github.com/users/djrut/events{/privacy}","received_events_url":"https://api.github.com/users/djrut/received_events","type":"User","site_admin":false},"body":"- Author(s) mini bio, soft capped to 75 words: \"Duncan Rutland is a Sr. Solution Architect at Rackspace within the Fanatical Support for AWS team.\"\r\n- Author(s) social media contact info: None\r\n- ACCEPT redaction, editing or structure changes by technical writer staff\r\n- Desired date of publishing: 10/26/2015\r\n\r\n","created_at":"2015-10-21T19:48:52Z","updated_at":"2015-10-23T15:50:03Z","closed_at":null,"merged_at":null,"merge_commit_sha":"6a4663c238cb556227375c6f04c1e404ebe7aa34","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/pulls/112/commits","review_comments_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/pulls/112/comments","review_comment_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/pulls/comments{/number}","comments_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/issues/112/comments","statuses_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/statuses/dbe1f2906a8dfbb8ac267472d0a9812434cf798b","head":{"label":"djrut:trinity-article-II","ref":"trinity-article-II","sha":"dbe1f2906a8dfbb8ac267472d0a9812434cf798b","user":{"login":"djrut","id":13618091,"avatar_url":"https://avatars.githubusercontent.com/u/13618091?v=3","gravatar_id":"","url":"https://api.github.com/users/djrut","html_url":"https://github.com/djrut","followers_url":"https://api.github.com/users/djrut/followers","following_url":"https://api.github.com/users/djrut/following{/other_user}","gists_url":"https://api.github.com/users/djrut/gists{/gist_id}","starred_url":"https://api.github.com/users/djrut/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/djrut/subscriptions","organizations_url":"https://api.github.com/users/djrut/orgs","repos_url":"https://api.github.com/users/djrut/repos","events_url":"https://api.github.com/users/djrut/events{/privacy}","received_events_url":"https://api.github.com/users/djrut/received_events","type":"User","site_admin":false},"repo":{"id":44561894,"name":"docs-developer-blog","full_name":"djrut/docs-developer-blog","owner":{"login":"djrut","id":13618091,"avatar_url":"https://avatars.githubusercontent.com/u/13618091?v=3","gravatar_id":"","url":"https://api.github.com/users/djrut","html_url":"https://github.com/djrut","followers_url":"https://api.github.com/users/djrut/followers","following_url":"https://api.github.com/users/djrut/following{/other_user}","gists_url":"https://api.github.com/users/djrut/gists{/gist_id}","starred_url":"https://api.github.com/users/djrut/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/djrut/subscriptions","organizations_url":"https://api.github.com/users/djrut/orgs","repos_url":"https://api.github.com/users/djrut/repos","events_url":"https://api.github.com/users/djrut/events{/privacy}","received_events_url":"https://api.github.com/users/djrut/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/djrut/docs-developer-blog","description":"The developer.rackspace.com blog.","fork":true,"url":"https://api.github.com/repos/djrut/docs-developer-blog","forks_url":"https://api.github.com/repos/djrut/docs-developer-blog/forks","keys_url":"https://api.github.com/repos/djrut/docs-developer-blog/keys{/key_id}","collaborators_url":"https://api.github.com/repos/djrut/docs-developer-blog/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/djrut/docs-developer-blog/teams","hooks_url":"https://api.github.com/repos/djrut/docs-developer-blog/hooks","issue_events_url":"https://api.github.com/repos/djrut/docs-developer-blog/issues/events{/number}","events_url":"https://api.github.com/repos/djrut/docs-developer-blog/events","assignees_url":"https://api.github.com/repos/djrut/docs-developer-blog/assignees{/user}","branches_url":"https://api.github.com/repos/djrut/docs-developer-blog/branches{/branch}","tags_url":"https://api.github.com/repos/djrut/docs-developer-blog/tags","blobs_url":"https://api.github.com/repos/djrut/docs-developer-blog/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/djrut/docs-developer-blog/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/djrut/docs-developer-blog/git/refs{/sha}","trees_url":"https://api.github.com/repos/djrut/docs-developer-blog/git/trees{/sha}","statuses_url":"https://api.github.com/repos/djrut/docs-developer-blog/statuses/{sha}","languages_url":"https://api.github.com/repos/djrut/docs-developer-blog/languages","stargazers_url":"https://api.github.com/repos/djrut/docs-developer-blog/stargazers","contributors_url":"https://api.github.com/repos/djrut/docs-developer-blog/contributors","subscribers_url":"https://api.github.com/repos/djrut/docs-developer-blog/subscribers","subscription_url":"https://api.github.com/repos/djrut/docs-developer-blog/subscription","commits_url":"https://api.github.com/repos/djrut/docs-developer-blog/commits{/sha}","git_commits_url":"https://api.github.com/repos/djrut/docs-developer-blog/git/commits{/sha}","comments_url":"https://api.github.com/repos/djrut/docs-developer-blog/comments{/number}","issue_comment_url":"https://api.github.com/repos/djrut/docs-developer-blog/issues/comments{/number}","contents_url":"https://api.github.com/repos/djrut/docs-developer-blog/contents/{+path}","compare_url":"https://api.github.com/repos/djrut/docs-developer-blog/compare/{base}...{head}","merges_url":"https://api.github.com/repos/djrut/docs-developer-blog/merges","archive_url":"https://api.github.com/repos/djrut/docs-developer-blog/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/djrut/docs-developer-blog/downloads","issues_url":"https://api.github.com/repos/djrut/docs-developer-blog/issues{/number}","pulls_url":"https://api.github.com/repos/djrut/docs-developer-blog/pulls{/number}","milestones_url":"https://api.github.com/repos/djrut/docs-developer-blog/milestones{/number}","notifications_url":"https://api.github.com/repos/djrut/docs-developer-blog/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/djrut/docs-developer-blog/labels{/name}","releases_url":"https://api.github.com/repos/djrut/docs-developer-blog/releases{/id}","created_at":"2015-10-19T20:25:37Z","updated_at":"2015-10-19T20:25:41Z","pushed_at":"2015-10-21T19:45:56Z","git_url":"git://github.com/djrut/docs-developer-blog.git","ssh_url":"git@github.com:djrut/docs-developer-blog.git","clone_url":"https://github.com/djrut/docs-developer-blog.git","svn_url":"https://github.com/djrut/docs-developer-blog","homepage":null,"size":60734,"stargazers_count":0,"watchers_count":0,"language":"HTML","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"rackerlabs:master","ref":"master","sha":"47cadc85a991da928dda24b314828d155804558a","user":{"login":"rackerlabs","id":84293,"avatar_url":"https://avatars.githubusercontent.com/u/84293?v=3","gravatar_id":"","url":"https://api.github.com/users/rackerlabs","html_url":"https://github.com/rackerlabs","followers_url":"https://api.github.com/users/rackerlabs/followers","following_url":"https://api.github.com/users/rackerlabs/following{/other_user}","gists_url":"https://api.github.com/users/rackerlabs/gists{/gist_id}","starred_url":"https://api.github.com/users/rackerlabs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rackerlabs/subscriptions","organizations_url":"https://api.github.com/users/rackerlabs/orgs","repos_url":"https://api.github.com/users/rackerlabs/repos","events_url":"https://api.github.com/users/rackerlabs/events{/privacy}","received_events_url":"https://api.github.com/users/rackerlabs/received_events","type":"Organization","site_admin":false},"repo":{"id":36315867,"name":"docs-developer-blog","full_name":"rackerlabs/docs-developer-blog","owner":{"login":"rackerlabs","id":84293,"avatar_url":"https://avatars.githubusercontent.com/u/84293?v=3","gravatar_id":"","url":"https://api.github.com/users/rackerlabs","html_url":"https://github.com/rackerlabs","followers_url":"https://api.github.com/users/rackerlabs/followers","following_url":"https://api.github.com/users/rackerlabs/following{/other_user}","gists_url":"https://api.github.com/users/rackerlabs/gists{/gist_id}","starred_url":"https://api.github.com/users/rackerlabs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rackerlabs/subscriptions","organizations_url":"https://api.github.com/users/rackerlabs/orgs","repos_url":"https://api.github.com/users/rackerlabs/repos","events_url":"https://api.github.com/users/rackerlabs/events{/privacy}","received_events_url":"https://api.github.com/users/rackerlabs/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/rackerlabs/docs-developer-blog","description":"The developer.rackspace.com blog.","fork":false,"url":"https://api.github.com/repos/rackerlabs/docs-developer-blog","forks_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/forks","keys_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/keys{/key_id}","collaborators_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/teams","hooks_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/hooks","issue_events_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/issues/events{/number}","events_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/events","assignees_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/assignees{/user}","branches_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/branches{/branch}","tags_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/tags","blobs_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/git/refs{/sha}","trees_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/git/trees{/sha}","statuses_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/statuses/{sha}","languages_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/languages","stargazers_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/stargazers","contributors_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/contributors","subscribers_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/subscribers","subscription_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/subscription","commits_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/commits{/sha}","git_commits_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/git/commits{/sha}","comments_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/comments{/number}","issue_comment_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/issues/comments{/number}","contents_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/contents/{+path}","compare_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/compare/{base}...{head}","merges_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/merges","archive_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/downloads","issues_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/issues{/number}","pulls_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/pulls{/number}","milestones_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/milestones{/number}","notifications_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/labels{/name}","releases_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/releases{/id}","created_at":"2015-05-26T18:34:01Z","updated_at":"2015-07-14T20:57:56Z","pushed_at":"2015-10-23T15:38:58Z","git_url":"git://github.com/rackerlabs/docs-developer-blog.git","ssh_url":"git@github.com:rackerlabs/docs-developer-blog.git","clone_url":"https://github.com/rackerlabs/docs-developer-blog.git","svn_url":"https://github.com/rackerlabs/docs-developer-blog","homepage":null,"size":60734,"stargazers_count":6,"watchers_count":6,"language":"HTML","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":29,"mirror_url":null,"open_issues_count":11,"forks":29,"open_issues":11,"watchers":6,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/rackerlabs/docs-developer-blog/pulls/112"},"html":{"href":"https://github.com/rackerlabs/docs-developer-blog/pull/112"},"issue":{"href":"https://api.github.com/repos/rackerlabs/docs-developer-blog/issues/112"},"comments":{"href":"https://api.github.com/repos/rackerlabs/docs-developer-blog/issues/112/comments"},"review_comments":{"href":"https://api.github.com/repos/rackerlabs/docs-developer-blog/pulls/112/comments"},"review_comment":{"href":"https://api.github.com/repos/rackerlabs/docs-developer-blog/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/rackerlabs/docs-developer-blog/pulls/112/commits"},"statuses":{"href":"https://api.github.com/repos/rackerlabs/docs-developer-blog/statuses/dbe1f2906a8dfbb8ac267472d0a9812434cf798b"}}}}