{"action":"created","comment":{"url":"https://api.github.com/repos/backus/rubocop-rspec/pulls/comments/77937296","id":77937296,"diff_hunk":"@@ -0,0 +1,30 @@\n+#!/bin/bash\n+\n+if [[ $# -ne 2 ]] ; then\n+    echo \"build/docker-exec - run a rake command on a specified ruby version\"\n+    echo \"Usage:\"\n+    echo \"  build/docker-exec 2.2.5 spec\"\n+    exit 1\n+fi\n+\n+ruby_version=\"$1\"\n+rake_task=\"$2\"\n+\n+cp -r /app /src\n+cd /src/app || exit 1\n+\n+# Disable strict settings that break chruby\n+set +o nounset\n+set +o noglob\n+\n+source \"/usr/local/share/chruby/chruby.sh\"\n+\n+chruby \"$ruby_version\"\n+\n+# Reenable strict settings\n+set -o nounset","path":"build/docker-exec","position":25,"original_position":25,"commit_id":"2e8556c0a8f9d14ded9c570a69c33c5b4f1f4304","original_commit_id":"2e8556c0a8f9d14ded9c570a69c33c5b4f1f4304","user":{"login":"backus","id":2085622,"avatar_url":"https://avatars.githubusercontent.com/u/2085622?v=3","gravatar_id":"","url":"https://api.github.com/users/backus","html_url":"https://github.com/backus","followers_url":"https://api.github.com/users/backus/followers","following_url":"https://api.github.com/users/backus/following{/other_user}","gists_url":"https://api.github.com/users/backus/gists{/gist_id}","starred_url":"https://api.github.com/users/backus/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/backus/subscriptions","organizations_url":"https://api.github.com/users/backus/orgs","repos_url":"https://api.github.com/users/backus/repos","events_url":"https://api.github.com/users/backus/events{/privacy}","received_events_url":"https://api.github.com/users/backus/received_events","type":"User","site_admin":false},"body":"Yeah it doesn't work if you subshell:\r\n\r\n```\r\n$ git --no-pager diff\r\ndiff --git i/build/docker-exec w/build/docker-exec\r\nindex 7ea461d..45e8afc 100755\r\n--- i/build/docker-exec\r\n+++ w/build/docker-exec\r\n@@ -13,17 +13,15 @@ rake_task=\"$2\"\r\n cp -r /app /src\r\n cd /src/app || exit 1\r\n\r\n-# Disable strict settings that break chruby\r\n-set +o nounset\r\n-set +o noglob\r\n+(\r\n+  # Disable strict settings that break chruby\r\n+  set +o nounset\r\n+  set +o noglob\r\n\r\n-source \"/usr/local/share/chruby/chruby.sh\"\r\n+  source \"/usr/local/share/chruby/chruby.sh\"\r\n\r\n-chruby \"$ruby_version\"\r\n-\r\n-# Reenable strict settings\r\n-set -o nounset\r\n-set -o noglob\r\n+  chruby \"$ruby_version\"\r\n+)\r\n\r\n bundle install --jobs 8 --path /bundle\r\n\r\n$ build/run 2.2.5 spec\r\nbuild/docker-exec: line 26: bundle: command not found\r\n```","created_at":"2016-09-08T02:24:18Z","updated_at":"2016-09-08T02:24:18Z","html_url":"https://github.com/backus/rubocop-rspec/pull/205#discussion_r77937296","pull_request_url":"https://api.github.com/repos/backus/rubocop-rspec/pulls/205","_links":{"self":{"href":"https://api.github.com/repos/backus/rubocop-rspec/pulls/comments/77937296"},"html":{"href":"https://github.com/backus/rubocop-rspec/pull/205#discussion_r77937296"},"pull_request":{"href":"https://api.github.com/repos/backus/rubocop-rspec/pulls/205"}}},"pull_request":{"url":"https://api.github.com/repos/backus/rubocop-rspec/pulls/205","id":83939186,"html_url":"https://github.com/backus/rubocop-rspec/pull/205","diff_url":"https://github.com/backus/rubocop-rspec/pull/205.diff","patch_url":"https://github.com/backus/rubocop-rspec/pull/205.patch","issue_url":"https://api.github.com/repos/backus/rubocop-rspec/issues/205","number":205,"state":"open","locked":false,"title":"[Experiment] Use buildkite elastic CI + Docker for faster builds","user":{"login":"backus","id":2085622,"avatar_url":"https://avatars.githubusercontent.com/u/2085622?v=3","gravatar_id":"","url":"https://api.github.com/users/backus","html_url":"https://github.com/backus","followers_url":"https://api.github.com/users/backus/followers","following_url":"https://api.github.com/users/backus/following{/other_user}","gists_url":"https://api.github.com/users/backus/gists{/gist_id}","starred_url":"https://api.github.com/users/backus/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/backus/subscriptions","organizations_url":"https://api.github.com/users/backus/orgs","repos_url":"https://api.github.com/users/backus/repos","events_url":"https://api.github.com/users/backus/events{/privacy}","received_events_url":"https://api.github.com/users/backus/received_events","type":"User","site_admin":false},"body":"This PR adds\r\n\r\n1. A docker container for running builds in an isolated context with different\r\n   ruby versions\r\n\r\n2. A set of bash scripts for setting up this docker container and for easily\r\n   running rake tasks inside of the container\r\n\r\n3. Initial configuration for the build matrix docker container which mirror\r\n   the ruby versions currently tested on Travis\r\n\r\n4. Buildkite configuration (a pipeline definition and pre-command hook) that\r\n   replicates our build on buildkite\r\n\r\nUsing this setup should make it much quicker to test builds of rubocop-rspec.\r\nI currently have a Buildkite's [elastic-ci](https://github.com/buildkite/elastic-ci-stack-for-aws) hooked up to a personal AWS account of mine. This setup\r\nhas a single EC2 instance always online waiting for builds. If some build activity\r\npicks up then the elastic CI configuration will spin up as many as 10 instances\r\nin order to satisfy the demand for build instances.\r\n\r\nThis buildkite setup is *fast*! Take a look at the difference:\r\n\r\n![travis][travis-build]\r\n![buildkite][buildkite-build]\r\n\r\n[travis-build]: https://cloud.githubusercontent.com/assets/2085622/18332207/8fbbac96-7519-11e6-986e-86384902e632.png\r\n[buildkite-build]: https://cloud.githubusercontent.com/assets/2085622/18332231/c89bca96-7519-11e6-8570-6bb2a798872c.png\r\n\r\nIf it isn't obvious from the picture:\r\n\r\n* Travis CI: 3 minutes 15 seconds\r\n* Buildkite: 23 seconds\r\n\r\n\r\nSo roughly **8x faster** than Travis.\r\n\r\nTravis runs one ruby build at a time per ruby version. Buildkite can afford to\r\nrun each step in parallel. This means I can scale up the supported rubies (or\r\nthe independent build steps) and incur almost not additional cost in build time.\r\n\r\n---\r\n\r\nThat was the motivation for this PR. Here is what makes it tough:\r\n\r\nBy default each build step runs directly on the AWS instance. Therefore, if this\r\nbuildkite setup is open to outside contributors (which I would like it to be), someone\r\ncould make a PR like this\r\n\r\n```ruby\r\n# anywhere in the codebase that is exercised by tests\r\nsystem('rm -rf /')\r\n```\r\n\r\nor any other arbitrary command and this would affect the CI server permanently. This\r\nis only one issue of course and there are plenty other malicious things people could\r\ndo. This is where the docker container comes in. Each build step is run like so:\r\n\r\n```sh\r\n$ build/run 2.2.5 spec\r\n```\r\n\r\nInside the Docker container this is setting the ruby version to 2.2.5 and running\r\n`rake spec`. The project directory is mounted inside of the docker container as a\r\nread only filesystem (so the code running inside the container is not able to modify\r\nthe outside world) so the code executing inside cannot make changes to the CI server.\r\n\r\nThese commands are specified in the `.buildkite/pipeline.yml` file like so:\r\n\r\n```yaml\r\nsteps:\r\n  - command: \"build/run 2.2.5 spec\"\r\n    label: \":rspec: RSpec (2.2)\"\r\n    agents:\r\n      - queue=elastic\r\n\r\n  - command: \"build/run 2.3.1 spec\"\r\n    label: \":rspec: RSpec (2.3)\"\r\n    agents:\r\n      - queue=elastic\r\n\r\n  - command: \"build/run 2.2.5 internal_investigation\"\r\n    label: \":rubocop: RuboCop (2.2)\"\r\n    agents:\r\n      - queue=elastic\r\n\r\n  - command: \"build/run 2.3.1 internal_investigation\"\r\n    label: \":rubocop: RubCop (2.3)\"\r\n    agents:\r\n      - queue=elastic\r\n\r\n  - command: \"build/run 2.3.1 confirm_config\"\r\n    label: \":scroll: Configuration\"\r\n    agents:\r\n      - queue=elastic\r\n```\r\n\r\nThis docker isolation is nice and all but that alone doesn't secure the build\r\nprocess. Any third party collaborator could just edit the `pipeline.yml` file and\r\nadd a step that does `rm -rf /` or whatever. Same for any of the scripts or the\r\ndockerfile itself. To work around this, the buildkite pipeline is also configured\r\nvia the dashboard (which only I can control right now) and the first build step\r\nis this:\r\n\r\n```sh\r\ngpg --keyserver pgp.mit.edu --recv 1B3C10C4\r\n\r\ngit_signature=$(git --no-pager show --quiet --pretty='%G?: %GS %GK' HEAD)\r\nexpected_signature=\"U: John Backus <johncbackus@gmail.com> 9A91898D0B0B2FBE\"\r\n\r\nif [[ \"$git_signature\" != \"$expected_signature\" ]]; then\r\n  echo \"Expected signature: $expected_signature\"\r\n  echo \"Actual signature:   $git_signature\"\r\n  echo\r\n\r\n  git diff --exit-code origin/master -- build .buildkite\r\nfi\r\n```\r\n\r\nThis is doing the following:\r\n\r\n1. Download the PGP key I use to sign commits\r\n2. Check the signature of the current `HEAD` commit\r\n3. If the current head commit is not signed by me then fail the build if any\r\n   files were changed in the `build/` or `.buildkite` directories\r\n\r\nThe buildkite settings then halts the build early if a commit not issued by\r\nme altered the build steps.\r\n\r\nWith this leading check I am confident enough that a build for a 3rd party\r\nPR can't just arbitrarily hijack an AWS box of mine :)","created_at":"2016-09-05T00:40:07Z","updated_at":"2016-09-08T02:24:18Z","closed_at":null,"merged_at":null,"merge_commit_sha":"78fb4ef407554d2bbe283bed049454af0728893f","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/backus/rubocop-rspec/pulls/205/commits","review_comments_url":"https://api.github.com/repos/backus/rubocop-rspec/pulls/205/comments","review_comment_url":"https://api.github.com/repos/backus/rubocop-rspec/pulls/comments{/number}","comments_url":"https://api.github.com/repos/backus/rubocop-rspec/issues/205/comments","statuses_url":"https://api.github.com/repos/backus/rubocop-rspec/statuses/2e8556c0a8f9d14ded9c570a69c33c5b4f1f4304","head":{"label":"backus:feature/Docker-buildkite","ref":"feature/Docker-buildkite","sha":"2e8556c0a8f9d14ded9c570a69c33c5b4f1f4304","user":{"login":"backus","id":2085622,"avatar_url":"https://avatars.githubusercontent.com/u/2085622?v=3","gravatar_id":"","url":"https://api.github.com/users/backus","html_url":"https://github.com/backus","followers_url":"https://api.github.com/users/backus/followers","following_url":"https://api.github.com/users/backus/following{/other_user}","gists_url":"https://api.github.com/users/backus/gists{/gist_id}","starred_url":"https://api.github.com/users/backus/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/backus/subscriptions","organizations_url":"https://api.github.com/users/backus/orgs","repos_url":"https://api.github.com/users/backus/repos","events_url":"https://api.github.com/users/backus/events{/privacy}","received_events_url":"https://api.github.com/users/backus/received_events","type":"User","site_admin":false},"repo":{"id":16263354,"name":"rubocop-rspec","full_name":"backus/rubocop-rspec","owner":{"login":"backus","id":2085622,"avatar_url":"https://avatars.githubusercontent.com/u/2085622?v=3","gravatar_id":"","url":"https://api.github.com/users/backus","html_url":"https://github.com/backus","followers_url":"https://api.github.com/users/backus/followers","following_url":"https://api.github.com/users/backus/following{/other_user}","gists_url":"https://api.github.com/users/backus/gists{/gist_id}","starred_url":"https://api.github.com/users/backus/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/backus/subscriptions","organizations_url":"https://api.github.com/users/backus/orgs","repos_url":"https://api.github.com/users/backus/repos","events_url":"https://api.github.com/users/backus/events{/privacy}","received_events_url":"https://api.github.com/users/backus/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/backus/rubocop-rspec","description":"Code style checking for RSpec files","fork":false,"url":"https://api.github.com/repos/backus/rubocop-rspec","forks_url":"https://api.github.com/repos/backus/rubocop-rspec/forks","keys_url":"https://api.github.com/repos/backus/rubocop-rspec/keys{/key_id}","collaborators_url":"https://api.github.com/repos/backus/rubocop-rspec/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/backus/rubocop-rspec/teams","hooks_url":"https://api.github.com/repos/backus/rubocop-rspec/hooks","issue_events_url":"https://api.github.com/repos/backus/rubocop-rspec/issues/events{/number}","events_url":"https://api.github.com/repos/backus/rubocop-rspec/events","assignees_url":"https://api.github.com/repos/backus/rubocop-rspec/assignees{/user}","branches_url":"https://api.github.com/repos/backus/rubocop-rspec/branches{/branch}","tags_url":"https://api.github.com/repos/backus/rubocop-rspec/tags","blobs_url":"https://api.github.com/repos/backus/rubocop-rspec/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/backus/rubocop-rspec/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/backus/rubocop-rspec/git/refs{/sha}","trees_url":"https://api.github.com/repos/backus/rubocop-rspec/git/trees{/sha}","statuses_url":"https://api.github.com/repos/backus/rubocop-rspec/statuses/{sha}","languages_url":"https://api.github.com/repos/backus/rubocop-rspec/languages","stargazers_url":"https://api.github.com/repos/backus/rubocop-rspec/stargazers","contributors_url":"https://api.github.com/repos/backus/rubocop-rspec/contributors","subscribers_url":"https://api.github.com/repos/backus/rubocop-rspec/subscribers","subscription_url":"https://api.github.com/repos/backus/rubocop-rspec/subscription","commits_url":"https://api.github.com/repos/backus/rubocop-rspec/commits{/sha}","git_commits_url":"https://api.github.com/repos/backus/rubocop-rspec/git/commits{/sha}","comments_url":"https://api.github.com/repos/backus/rubocop-rspec/comments{/number}","issue_comment_url":"https://api.github.com/repos/backus/rubocop-rspec/issues/comments{/number}","contents_url":"https://api.github.com/repos/backus/rubocop-rspec/contents/{+path}","compare_url":"https://api.github.com/repos/backus/rubocop-rspec/compare/{base}...{head}","merges_url":"https://api.github.com/repos/backus/rubocop-rspec/merges","archive_url":"https://api.github.com/repos/backus/rubocop-rspec/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/backus/rubocop-rspec/downloads","issues_url":"https://api.github.com/repos/backus/rubocop-rspec/issues{/number}","pulls_url":"https://api.github.com/repos/backus/rubocop-rspec/pulls{/number}","milestones_url":"https://api.github.com/repos/backus/rubocop-rspec/milestones{/number}","notifications_url":"https://api.github.com/repos/backus/rubocop-rspec/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/backus/rubocop-rspec/labels{/name}","releases_url":"https://api.github.com/repos/backus/rubocop-rspec/releases{/id}","deployments_url":"https://api.github.com/repos/backus/rubocop-rspec/deployments","created_at":"2014-01-26T22:31:26Z","updated_at":"2016-09-08T01:09:51Z","pushed_at":"2016-09-08T01:37:40Z","git_url":"git://github.com/backus/rubocop-rspec.git","ssh_url":"git@github.com:backus/rubocop-rspec.git","clone_url":"https://github.com/backus/rubocop-rspec.git","svn_url":"https://github.com/backus/rubocop-rspec","homepage":null,"size":492,"stargazers_count":147,"watchers_count":147,"language":"Ruby","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":52,"mirror_url":null,"open_issues_count":15,"forks":52,"open_issues":15,"watchers":147,"default_branch":"master"}},"base":{"label":"backus:master","ref":"master","sha":"e706d23e6ea12dc37ea369542d6929dd42a0a30d","user":{"login":"backus","id":2085622,"avatar_url":"https://avatars.githubusercontent.com/u/2085622?v=3","gravatar_id":"","url":"https://api.github.com/users/backus","html_url":"https://github.com/backus","followers_url":"https://api.github.com/users/backus/followers","following_url":"https://api.github.com/users/backus/following{/other_user}","gists_url":"https://api.github.com/users/backus/gists{/gist_id}","starred_url":"https://api.github.com/users/backus/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/backus/subscriptions","organizations_url":"https://api.github.com/users/backus/orgs","repos_url":"https://api.github.com/users/backus/repos","events_url":"https://api.github.com/users/backus/events{/privacy}","received_events_url":"https://api.github.com/users/backus/received_events","type":"User","site_admin":false},"repo":{"id":16263354,"name":"rubocop-rspec","full_name":"backus/rubocop-rspec","owner":{"login":"backus","id":2085622,"avatar_url":"https://avatars.githubusercontent.com/u/2085622?v=3","gravatar_id":"","url":"https://api.github.com/users/backus","html_url":"https://github.com/backus","followers_url":"https://api.github.com/users/backus/followers","following_url":"https://api.github.com/users/backus/following{/other_user}","gists_url":"https://api.github.com/users/backus/gists{/gist_id}","starred_url":"https://api.github.com/users/backus/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/backus/subscriptions","organizations_url":"https://api.github.com/users/backus/orgs","repos_url":"https://api.github.com/users/backus/repos","events_url":"https://api.github.com/users/backus/events{/privacy}","received_events_url":"https://api.github.com/users/backus/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/backus/rubocop-rspec","description":"Code style checking for RSpec files","fork":false,"url":"https://api.github.com/repos/backus/rubocop-rspec","forks_url":"https://api.github.com/repos/backus/rubocop-rspec/forks","keys_url":"https://api.github.com/repos/backus/rubocop-rspec/keys{/key_id}","collaborators_url":"https://api.github.com/repos/backus/rubocop-rspec/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/backus/rubocop-rspec/teams","hooks_url":"https://api.github.com/repos/backus/rubocop-rspec/hooks","issue_events_url":"https://api.github.com/repos/backus/rubocop-rspec/issues/events{/number}","events_url":"https://api.github.com/repos/backus/rubocop-rspec/events","assignees_url":"https://api.github.com/repos/backus/rubocop-rspec/assignees{/user}","branches_url":"https://api.github.com/repos/backus/rubocop-rspec/branches{/branch}","tags_url":"https://api.github.com/repos/backus/rubocop-rspec/tags","blobs_url":"https://api.github.com/repos/backus/rubocop-rspec/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/backus/rubocop-rspec/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/backus/rubocop-rspec/git/refs{/sha}","trees_url":"https://api.github.com/repos/backus/rubocop-rspec/git/trees{/sha}","statuses_url":"https://api.github.com/repos/backus/rubocop-rspec/statuses/{sha}","languages_url":"https://api.github.com/repos/backus/rubocop-rspec/languages","stargazers_url":"https://api.github.com/repos/backus/rubocop-rspec/stargazers","contributors_url":"https://api.github.com/repos/backus/rubocop-rspec/contributors","subscribers_url":"https://api.github.com/repos/backus/rubocop-rspec/subscribers","subscription_url":"https://api.github.com/repos/backus/rubocop-rspec/subscription","commits_url":"https://api.github.com/repos/backus/rubocop-rspec/commits{/sha}","git_commits_url":"https://api.github.com/repos/backus/rubocop-rspec/git/commits{/sha}","comments_url":"https://api.github.com/repos/backus/rubocop-rspec/comments{/number}","issue_comment_url":"https://api.github.com/repos/backus/rubocop-rspec/issues/comments{/number}","contents_url":"https://api.github.com/repos/backus/rubocop-rspec/contents/{+path}","compare_url":"https://api.github.com/repos/backus/rubocop-rspec/compare/{base}...{head}","merges_url":"https://api.github.com/repos/backus/rubocop-rspec/merges","archive_url":"https://api.github.com/repos/backus/rubocop-rspec/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/backus/rubocop-rspec/downloads","issues_url":"https://api.github.com/repos/backus/rubocop-rspec/issues{/number}","pulls_url":"https://api.github.com/repos/backus/rubocop-rspec/pulls{/number}","milestones_url":"https://api.github.com/repos/backus/rubocop-rspec/milestones{/number}","notifications_url":"https://api.github.com/repos/backus/rubocop-rspec/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/backus/rubocop-rspec/labels{/name}","releases_url":"https://api.github.com/repos/backus/rubocop-rspec/releases{/id}","deployments_url":"https://api.github.com/repos/backus/rubocop-rspec/deployments","created_at":"2014-01-26T22:31:26Z","updated_at":"2016-09-08T01:09:51Z","pushed_at":"2016-09-08T01:37:40Z","git_url":"git://github.com/backus/rubocop-rspec.git","ssh_url":"git@github.com:backus/rubocop-rspec.git","clone_url":"https://github.com/backus/rubocop-rspec.git","svn_url":"https://github.com/backus/rubocop-rspec","homepage":null,"size":492,"stargazers_count":147,"watchers_count":147,"language":"Ruby","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":52,"mirror_url":null,"open_issues_count":15,"forks":52,"open_issues":15,"watchers":147,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/backus/rubocop-rspec/pulls/205"},"html":{"href":"https://github.com/backus/rubocop-rspec/pull/205"},"issue":{"href":"https://api.github.com/repos/backus/rubocop-rspec/issues/205"},"comments":{"href":"https://api.github.com/repos/backus/rubocop-rspec/issues/205/comments"},"review_comments":{"href":"https://api.github.com/repos/backus/rubocop-rspec/pulls/205/comments"},"review_comment":{"href":"https://api.github.com/repos/backus/rubocop-rspec/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/backus/rubocop-rspec/pulls/205/commits"},"statuses":{"href":"https://api.github.com/repos/backus/rubocop-rspec/statuses/2e8556c0a8f9d14ded9c570a69c33c5b4f1f4304"}}}}
{"actor":{"display_login":"backus"}}