{"action":"created","comment":{"url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/pulls/comments/25595714","id":25595714,"diff_hunk":"@@ -0,0 +1,176 @@\n+import os from 'os';\n+import fs from 'mz/fs';\n+import URL from 'url';\n+import { exec } from 'mz/child_process';\n+import request from 'superagent';\n+import fsPath from 'path';\n+import eventToPromise from 'event-to-promise';\n+\n+import dockerOpts from 'dockerode-options';\n+import Docker from 'dockerode-promise'\n+import Debug from 'debug';\n+\n+const debug = Debug('compose');\n+\n+// Compose binary name...\n+export const COMPOSE_VERSION = '1.1.0';\n+const COMPOSE_BASE_URL = 'https://github.com/docker/compose/releases/download';\n+const COMPOSE_INSTALL_ROOT = fsPath.join(__dirname, '.compose');\n+\n+async function execDebug(...args) {\n+  let cmd = args[0];\n+  debug('exec', cmd)\n+  return await exec.apply(this, args);\n+}\n+\n+function composeLocationConfig() {\n+  // urls are formatted as Darwin/Linux/etc..\n+  let platform = os.platform();\n+  platform = `${platform[0].toUpperCase()}${platform.slice(1)}`\n+\n+  let arch;\n+  switch (os.arch()) {\n+    case 'x64':\n+      arch = 'x86_64';\n+      break;\n+    default:\n+      arch = os.arch();\n+  }\n+\n+  let url = `${COMPOSE_BASE_URL}/${COMPOSE_VERSION}/docker-compose-${platform}-${arch}`;\n+  let slug = `${COMPOSE_VERSION}-${platform}-${arch}`;\n+  return { url, slug };\n+}\n+\n+/**\n+Docker compose related utilities...\n+*/\n+\n+class Compose {\n+  constructor(composeBin) {\n+    let dockerConf = dockerOpts();\n+\n+    if (dockerConf.host) {\n+      let parsedHost = URL.parse(dockerConf.host);\n+      this.host = parsedHost.host;\n+    } else {\n+      this.host = 'localhost';\n+    }\n+\n+    // Use remote host if given otherwise assume localhost...\n+    this.bin = composeBin;\n+    this.docker = new Docker(dockerConf);\n+    debug('compose initialized', { bin: composeBin, host: this.host });\n+  }\n+\n+  /**\n+  Bring a docker-compose yaml stack online...\n+  */\n+  async up(cwd) {\n+    return execDebug(`${this.bin} up -d --no-recreate`, { cwd });\n+  }\n+\n+  async killAll(cwd) {\n+    return execDebug(`${this.bin} kill`, { cwd });\n+  }\n+\n+  /**\n+  Start running a single instance of a given service.\n+  */\n+  async run(cwd, service) {\n+    let [service] = await execDebug(`${this.bin} run -d --service-ports ${service}`, {\n+      cwd\n+    });\n+\n+    return service.trim();\n+  }\n+\n+  async portByName(cwd, service, port) {\n+    let [result] = await execDebug(`${this.bin} port ${service} ${port}`, {\n+      cwd\n+    });\n+\n+    let [host, port] = result.trim().split(':');\n+    if (port) {\n+      return parseInt(port, 10);\n+    }\n+    throw new Error(`Unknown port ${port} for service ${service}`);\n+  }\n+\n+  async portById(containerId, port) {\n+    let inspect = await this.inspect(containerId);\n+    let ports = inspect.NetworkSettings.Ports;\n+    let port = ports[`${port}/tcp`];\n+\n+    if (!port) {\n+      throw new Error(`Unknown port ${port} for container ${containerId}`);\n+    }\n+    return parseInt(port[0].HostPort, 10);\n+  }\n+\n+  /**\n+  Ensure container is both killed and removed.\n+  */\n+  async destroy(containerId) {\n+    let container = this.docker.getContainer(containerId);\n+    await container.kill({});\n+    await container.remove({});\n+  }\n+\n+  async ps(cwd) {\n+    let [stdout] = await execDebug(`${this.bin} ps -q`, {\n+      cwd\n+    });\n+\n+    return stdout.trim().split('\\n').map((v) => {\n+      return v.trim();\n+    });\n+  }\n+\n+  /**\n+  Inspect a container given it's container id (note you can get this via ps)\n+  */\n+  async inspect(containerId) {\n+    let container = this.docker.getContainer(containerId);\n+    return await container.inspect();\n+  }\n+\n+  async version() {\n+    let [version] = await execDebug(`${this.bin} --version`);\n+    let [, number] = version.trim().split(' ');\n+    return number;\n+  }\n+}\n+\n+/**\n+Download and install docker-compose.\n+\n+@param {String} [installPath] install path for compose binaries.\n+*/\n+export async function install(installPath = COMPOSE_INSTALL_ROOT) {\n+  let { url, slug } = composeLocationConfig();\n+  debug('compose install', { url, slug });\n+\n+  // Ensure compose install root exists...\n+  if (!await fs.exists(installPath)) {\n+    await fs.mkdir(installPath);\n+  }\n+\n+  let composeBin = fsPath.join(installPath, slug);\n+\n+  // Check for an existing install ..\n+  if (await fs.exists(composeBin)) {\n+    debug('compose already installed...');\n+    return new Compose(composeBin);\n+  }","path":"test/compose.js","position":165,"original_position":165,"commit_id":"f4292e711f011504d8ff0604da7ebd8761d28dbc","original_commit_id":"f4292e711f011504d8ff0604da7ebd8761d28dbc","user":{"login":"rail","id":42865,"avatar_url":"https://avatars.githubusercontent.com/u/42865?v=3","gravatar_id":"","url":"https://api.github.com/users/rail","html_url":"https://github.com/rail","followers_url":"https://api.github.com/users/rail/followers","following_url":"https://api.github.com/users/rail/following{/other_user}","gists_url":"https://api.github.com/users/rail/gists{/gist_id}","starred_url":"https://api.github.com/users/rail/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rail/subscriptions","organizations_url":"https://api.github.com/users/rail/orgs","repos_url":"https://api.github.com/users/rail/repos","events_url":"https://api.github.com/users/rail/events{/privacy}","received_events_url":"https://api.github.com/users/rail/received_events","type":"User","site_admin":false},"body":"I think this block can be moved before the one with fs.mkdir().","created_at":"2015-03-02T12:48:36Z","updated_at":"2015-03-02T12:48:36Z","html_url":"https://github.com/taskcluster/mozilla-taskcluster/pull/3#discussion_r25595714","pull_request_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/pulls/3","_links":{"self":{"href":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/pulls/comments/25595714"},"html":{"href":"https://github.com/taskcluster/mozilla-taskcluster/pull/3#discussion_r25595714"},"pull_request":{"href":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/pulls/3"}}},"pull_request":{"url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/pulls/3","id":30228665,"html_url":"https://github.com/taskcluster/mozilla-taskcluster/pull/3","diff_url":"https://github.com/taskcluster/mozilla-taskcluster/pull/3.diff","patch_url":"https://github.com/taskcluster/mozilla-taskcluster/pull/3.patch","issue_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/issues/3","number":3,"state":"open","locked":false,"title":"[WIP] Use real hg pushlog / fig -> docker-compose","user":{"login":"lightsofapollo","id":322957,"avatar_url":"https://avatars.githubusercontent.com/u/322957?v=3","gravatar_id":"","url":"https://api.github.com/users/lightsofapollo","html_url":"https://github.com/lightsofapollo","followers_url":"https://api.github.com/users/lightsofapollo/followers","following_url":"https://api.github.com/users/lightsofapollo/following{/other_user}","gists_url":"https://api.github.com/users/lightsofapollo/gists{/gist_id}","starred_url":"https://api.github.com/users/lightsofapollo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lightsofapollo/subscriptions","organizations_url":"https://api.github.com/users/lightsofapollo/orgs","repos_url":"https://api.github.com/users/lightsofapollo/repos","events_url":"https://api.github.com/users/lightsofapollo/events{/privacy}","received_events_url":"https://api.github.com/users/lightsofapollo/received_events","type":"User","site_admin":false},"body":"","created_at":"2015-02-28T18:45:54Z","updated_at":"2015-03-02T12:48:36Z","closed_at":null,"merged_at":null,"merge_commit_sha":"247df2927743008149b0b639b6b0fd8802baf82c","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/pulls/3/commits","review_comments_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/pulls/3/comments","review_comment_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/pulls/comments{/number}","comments_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/issues/3/comments","statuses_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/statuses/f4292e711f011504d8ff0604da7ebd8761d28dbc","head":{"label":"taskcluster:use-real-hg-pushlog","ref":"use-real-hg-pushlog","sha":"f4292e711f011504d8ff0604da7ebd8761d28dbc","user":{"login":"taskcluster","id":6257436,"avatar_url":"https://avatars.githubusercontent.com/u/6257436?v=3","gravatar_id":"","url":"https://api.github.com/users/taskcluster","html_url":"https://github.com/taskcluster","followers_url":"https://api.github.com/users/taskcluster/followers","following_url":"https://api.github.com/users/taskcluster/following{/other_user}","gists_url":"https://api.github.com/users/taskcluster/gists{/gist_id}","starred_url":"https://api.github.com/users/taskcluster/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/taskcluster/subscriptions","organizations_url":"https://api.github.com/users/taskcluster/orgs","repos_url":"https://api.github.com/users/taskcluster/repos","events_url":"https://api.github.com/users/taskcluster/events{/privacy}","received_events_url":"https://api.github.com/users/taskcluster/received_events","type":"Organization","site_admin":false},"repo":{"id":28359646,"name":"mozilla-taskcluster","full_name":"taskcluster/mozilla-taskcluster","owner":{"login":"taskcluster","id":6257436,"avatar_url":"https://avatars.githubusercontent.com/u/6257436?v=3","gravatar_id":"","url":"https://api.github.com/users/taskcluster","html_url":"https://github.com/taskcluster","followers_url":"https://api.github.com/users/taskcluster/followers","following_url":"https://api.github.com/users/taskcluster/following{/other_user}","gists_url":"https://api.github.com/users/taskcluster/gists{/gist_id}","starred_url":"https://api.github.com/users/taskcluster/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/taskcluster/subscriptions","organizations_url":"https://api.github.com/users/taskcluster/orgs","repos_url":"https://api.github.com/users/taskcluster/repos","events_url":"https://api.github.com/users/taskcluster/events{/privacy}","received_events_url":"https://api.github.com/users/taskcluster/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/taskcluster/mozilla-taskcluster","description":"Mozilla + Taskcluster handles integratations between mozilla components (hg/pushlog/treeherder) and taskcluster","fork":false,"url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster","forks_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/forks","keys_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/keys{/key_id}","collaborators_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/teams","hooks_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/hooks","issue_events_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/issues/events{/number}","events_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/events","assignees_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/assignees{/user}","branches_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/branches{/branch}","tags_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/tags","blobs_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/git/refs{/sha}","trees_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/git/trees{/sha}","statuses_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/statuses/{sha}","languages_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/languages","stargazers_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/stargazers","contributors_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/contributors","subscribers_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/subscribers","subscription_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/subscription","commits_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/commits{/sha}","git_commits_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/git/commits{/sha}","comments_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/comments{/number}","issue_comment_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/issues/comments{/number}","contents_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/contents/{+path}","compare_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/compare/{base}...{head}","merges_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/merges","archive_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/downloads","issues_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/issues{/number}","pulls_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/pulls{/number}","milestones_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/milestones{/number}","notifications_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/labels{/name}","releases_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/releases{/id}","created_at":"2014-12-22T21:14:49Z","updated_at":"2015-02-25T17:17:43Z","pushed_at":"2015-02-28T20:44:44Z","git_url":"git://github.com/taskcluster/mozilla-taskcluster.git","ssh_url":"git@github.com:taskcluster/mozilla-taskcluster.git","clone_url":"https://github.com/taskcluster/mozilla-taskcluster.git","svn_url":"https://github.com/taskcluster/mozilla-taskcluster","homepage":"","size":696,"stargazers_count":0,"watchers_count":0,"language":"JavaScript","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":1,"mirror_url":null,"open_issues_count":1,"forks":1,"open_issues":1,"watchers":0,"default_branch":"master"}},"base":{"label":"taskcluster:master","ref":"master","sha":"4fcc1dc1c4129e36684d87ba542f183b9e84dad1","user":{"login":"taskcluster","id":6257436,"avatar_url":"https://avatars.githubusercontent.com/u/6257436?v=3","gravatar_id":"","url":"https://api.github.com/users/taskcluster","html_url":"https://github.com/taskcluster","followers_url":"https://api.github.com/users/taskcluster/followers","following_url":"https://api.github.com/users/taskcluster/following{/other_user}","gists_url":"https://api.github.com/users/taskcluster/gists{/gist_id}","starred_url":"https://api.github.com/users/taskcluster/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/taskcluster/subscriptions","organizations_url":"https://api.github.com/users/taskcluster/orgs","repos_url":"https://api.github.com/users/taskcluster/repos","events_url":"https://api.github.com/users/taskcluster/events{/privacy}","received_events_url":"https://api.github.com/users/taskcluster/received_events","type":"Organization","site_admin":false},"repo":{"id":28359646,"name":"mozilla-taskcluster","full_name":"taskcluster/mozilla-taskcluster","owner":{"login":"taskcluster","id":6257436,"avatar_url":"https://avatars.githubusercontent.com/u/6257436?v=3","gravatar_id":"","url":"https://api.github.com/users/taskcluster","html_url":"https://github.com/taskcluster","followers_url":"https://api.github.com/users/taskcluster/followers","following_url":"https://api.github.com/users/taskcluster/following{/other_user}","gists_url":"https://api.github.com/users/taskcluster/gists{/gist_id}","starred_url":"https://api.github.com/users/taskcluster/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/taskcluster/subscriptions","organizations_url":"https://api.github.com/users/taskcluster/orgs","repos_url":"https://api.github.com/users/taskcluster/repos","events_url":"https://api.github.com/users/taskcluster/events{/privacy}","received_events_url":"https://api.github.com/users/taskcluster/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/taskcluster/mozilla-taskcluster","description":"Mozilla + Taskcluster handles integratations between mozilla components (hg/pushlog/treeherder) and taskcluster","fork":false,"url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster","forks_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/forks","keys_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/keys{/key_id}","collaborators_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/teams","hooks_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/hooks","issue_events_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/issues/events{/number}","events_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/events","assignees_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/assignees{/user}","branches_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/branches{/branch}","tags_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/tags","blobs_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/git/refs{/sha}","trees_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/git/trees{/sha}","statuses_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/statuses/{sha}","languages_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/languages","stargazers_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/stargazers","contributors_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/contributors","subscribers_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/subscribers","subscription_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/subscription","commits_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/commits{/sha}","git_commits_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/git/commits{/sha}","comments_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/comments{/number}","issue_comment_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/issues/comments{/number}","contents_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/contents/{+path}","compare_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/compare/{base}...{head}","merges_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/merges","archive_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/downloads","issues_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/issues{/number}","pulls_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/pulls{/number}","milestones_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/milestones{/number}","notifications_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/labels{/name}","releases_url":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/releases{/id}","created_at":"2014-12-22T21:14:49Z","updated_at":"2015-02-25T17:17:43Z","pushed_at":"2015-02-28T20:44:44Z","git_url":"git://github.com/taskcluster/mozilla-taskcluster.git","ssh_url":"git@github.com:taskcluster/mozilla-taskcluster.git","clone_url":"https://github.com/taskcluster/mozilla-taskcluster.git","svn_url":"https://github.com/taskcluster/mozilla-taskcluster","homepage":"","size":696,"stargazers_count":0,"watchers_count":0,"language":"JavaScript","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":1,"mirror_url":null,"open_issues_count":1,"forks":1,"open_issues":1,"watchers":0,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/pulls/3"},"html":{"href":"https://github.com/taskcluster/mozilla-taskcluster/pull/3"},"issue":{"href":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/issues/3"},"comments":{"href":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/issues/3/comments"},"review_comments":{"href":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/pulls/3/comments"},"review_comment":{"href":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/pulls/3/commits"},"statuses":{"href":"https://api.github.com/repos/taskcluster/mozilla-taskcluster/statuses/f4292e711f011504d8ff0604da7ebd8761d28dbc"}}}}