{"action":"created","comment":{"url":"https://api.github.com/repos/convox/rack/pulls/comments/69740615","id":69740615,"diff_hunk":"@@ -0,0 +1,199 @@\n+package manifest\n+\n+import (\n+\t\"crypto/sha256\"\n+\t\"encoding/base32\"\n+\t\"fmt\"\n+\t\"html/template\"\n+\t\"os\"\n+\t\"strconv\"\n+\t\"strings\"\n+)\n+\n+type ManifestPort struct {\n+\tBalancer  string\n+\tContainer string\n+\tPublic    bool\n+}\n+\n+type ManifestBalancer struct {\n+\tEntry  Service\n+\tPublic bool\n+}\n+\n+func (m Manifest) Balancers() []ManifestBalancer {\n+\tbalancers := []ManifestBalancer{}\n+\n+\tfor _, entry := range m.Services {\n+\t\tif len(entry.Ports) > 0 {\n+\t\t\tbalancers = append(balancers, ManifestBalancer{\n+\t\t\t\tEntry:  entry,\n+\t\t\t\tPublic: len(entry.InternalPorts()) == 0,\n+\t\t\t})\n+\t\t}\n+\t}\n+\n+\treturn balancers\n+}\n+\n+func (m Manifest) Formation() (string, error) {\n+\tdata, err := buildTemplate(\"app\", \"app\", m)\n+\n+\tif err != nil {\n+\t\treturn \"\", err\n+\t}\n+\n+\tpretty, err := prettyJson(string(data))\n+\n+\tif err != nil {\n+\t\treturn \"\", err\n+\t}\n+\n+\treturn pretty, nil\n+}\n+\n+func (m Manifest) GetBalancer(name string) *ManifestBalancer {\n+\tfor _, mb := range m.Balancers() {\n+\t\tif mb.Entry.Name == name {\n+\t\t\treturn &mb\n+\t\t}\n+\t}\n+\n+\treturn nil\n+}\n+\n+func (m Manifest) HasExternalPorts() bool {\n+\tif len(m.Services) == 0 {\n+\t\treturn true // special case to pre-initialize ELB at app create\n+\t}\n+\n+\tfor _, me := range m.Services {\n+\t\tif len(me.ExternalPorts()) > 0 {\n+\t\t\treturn true\n+\t\t}\n+\t}\n+\n+\treturn false\n+}\n+\n+func (m Manifest) HasProcesses() bool {\n+\treturn len(m.Services) > 0\n+}\n+\n+func (mb ManifestBalancer) ExternalPorts() []Port {\n+\treturn mb.Entry.ExternalPorts()\n+}\n+\n+func (mb ManifestBalancer) FirstPort() string {\n+\tif ports := mb.PortMappings(); len(ports) > 0 {\n+\t\treturn strconv.Itoa(ports[0].Balancer)\n+\t}\n+\n+\treturn \"\"\n+}\n+\n+func (mb ManifestBalancer) LoadBalancerName(bound bool, appName string) template.HTML {\n+\t// Bound apps do not use the StackName directly and ignore Entry.primary\n+\t// and use AppName-EntryName-RackAppEntryHash format\n+\tif bound {\n+\t\thash := sha256.Sum256([]byte(fmt.Sprintf(\"%s:%s:%s\", os.Getenv(\"RACK\"), appName, mb.Entry.Name)))\n+\t\tprefix := fmt.Sprintf(\"%s-%s\", appName, mb.Entry.Name)\n+\t\tsuffix := \"-\" + base32.StdEncoding.EncodeToString(hash[:])[:7]\n+\t\tif !mb.Public {\n+\t\t\tsuffix += \"-i\"\n+\t\t}\n+\t\t// ELB name must be 32 chars or less\n+\t\tif len(prefix) > 32-len(suffix) {\n+\t\t\tprefix = prefix[:32-len(suffix)]\n+\t\t}\n+\t\treturn template.HTML(`\"` + prefix + suffix + `\"`)\n+\t}\n+\n+\t// Unbound apps use legacy StackName or StackName-ProcessName format\n+\t//TODO\n+\t// if mb.Entry.primary {\n+\t// \treturn template.HTML(`{ \"Ref\": \"AWS::StackName\" }`)\n+\t// }\n+\n+\tif mb.Public {\n+\t\treturn template.HTML(fmt.Sprintf(`{ \"Fn::Join\": [ \"-\", [ { \"Ref\": \"AWS::StackName\" }, \"%s\" ] ] }`, mb.ProcessName()))\n+\t}\n+\n+\treturn template.HTML(fmt.Sprintf(`{ \"Fn::Join\": [ \"-\", [ { \"Ref\": \"AWS::StackName\" }, \"%s\", \"i\" ] ] }`, mb.ProcessName()))\n+}\n+\n+func (mb ManifestBalancer) InternalPorts() []Port {\n+\tfmt.Printf(\"mb.Entry.InternalPorts(): %+v\\n\", mb.Entry.InternalPorts())\n+\treturn mb.Entry.InternalPorts()\n+}\n+\n+func (mb ManifestBalancer) Ports() []string {\n+\tpp := mb.Entry.Ports\n+\tsp := make([]string, len(pp))\n+\n+\tfor _, p := range pp {\n+\t\tsp = append(sp, strconv.Itoa(p.Balancer))\n+\t}\n+\n+\treturn sp\n+}\n+\n+func (mb ManifestBalancer) ProcessName() string {\n+\treturn mb.Entry.Name\n+}\n+\n+func (mb ManifestBalancer) ResourceName() string {\n+\t// unbound apps special case the balancer name for the primary proces\n+\t//TODO work out what this means\n+\t// if mb.Entry.primary {\n+\t// \tif mb.Entry.app == nil || !mb.Entry.app.IsBound() {\n+\t// \t\treturn \"Balancer\"\n+\t// \t}\n+\t// }\n+\n+\tvar suffix string\n+\tif !mb.Public {\n+\t\tsuffix = \"Internal\"\n+\t}\n+\n+\treturn \"Balancer\" + UpperName(mb.Entry.Name) + suffix\n+}\n+\n+func (mb ManifestBalancer) PortMappings() []Port {\n+\treturn mb.Entry.Ports\n+}\n+\n+func (mb ManifestBalancer) Scheme() string {\n+\tif mb.Public {\n+\t\treturn \"internet-facing\"\n+\t}\n+\n+\treturn \"internal\"\n+}\n+\n+func UpperName(name string) string {","path":"manifest/balanacer.go","position":174,"original_position":174,"commit_id":"1636ec603cd1ba1b8af3721efbe4f84b4b58e8be","original_commit_id":"1636ec603cd1ba1b8af3721efbe4f84b4b58e8be","user":{"login":"houndci-bot","id":6697940,"avatar_url":"https://avatars.githubusercontent.com/u/6697940?v=3","gravatar_id":"","url":"https://api.github.com/users/houndci-bot","html_url":"https://github.com/houndci-bot","followers_url":"https://api.github.com/users/houndci-bot/followers","following_url":"https://api.github.com/users/houndci-bot/following{/other_user}","gists_url":"https://api.github.com/users/houndci-bot/gists{/gist_id}","starred_url":"https://api.github.com/users/houndci-bot/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/houndci-bot/subscriptions","organizations_url":"https://api.github.com/users/houndci-bot/orgs","repos_url":"https://api.github.com/users/houndci-bot/repos","events_url":"https://api.github.com/users/houndci-bot/events{/privacy}","received_events_url":"https://api.github.com/users/houndci-bot/received_events","type":"User","site_admin":false},"body":"exported function UpperName should have comment or be unexported","created_at":"2016-07-06T14:28:01Z","updated_at":"2016-07-06T14:28:01Z","html_url":"https://github.com/convox/rack/pull/845#discussion_r69740615","pull_request_url":"https://api.github.com/repos/convox/rack/pulls/845","_links":{"self":{"href":"https://api.github.com/repos/convox/rack/pulls/comments/69740615"},"html":{"href":"https://github.com/convox/rack/pull/845#discussion_r69740615"},"pull_request":{"href":"https://api.github.com/repos/convox/rack/pulls/845"}}},"pull_request":{"url":"https://api.github.com/repos/convox/rack/pulls/845","id":76441446,"html_url":"https://github.com/convox/rack/pull/845","diff_url":"https://github.com/convox/rack/pull/845.diff","patch_url":"https://github.com/convox/rack/pull/845.patch","issue_url":"https://api.github.com/repos/convox/rack/issues/845","number":845,"state":"open","locked":false,"title":"One manifest to rule them all","user":{"login":"awsmsrc","id":994907,"avatar_url":"https://avatars.githubusercontent.com/u/994907?v=3","gravatar_id":"","url":"https://api.github.com/users/awsmsrc","html_url":"https://github.com/awsmsrc","followers_url":"https://api.github.com/users/awsmsrc/followers","following_url":"https://api.github.com/users/awsmsrc/following{/other_user}","gists_url":"https://api.github.com/users/awsmsrc/gists{/gist_id}","starred_url":"https://api.github.com/users/awsmsrc/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/awsmsrc/subscriptions","organizations_url":"https://api.github.com/users/awsmsrc/orgs","repos_url":"https://api.github.com/users/awsmsrc/repos","events_url":"https://api.github.com/users/awsmsrc/events{/privacy}","received_events_url":"https://api.github.com/users/awsmsrc/received_events","type":"User","site_admin":false},"body":"## Release Playbook\r\n- [ ] Rebase against master\r\n- [ ] Release branch ()\r\n- [ ] Pass CI ()\r\n- [ ] Code review\r\n- [ ] Merge into master\r\n- [ ] Release master ()\r\n- [ ] Pass CI ()\r\n- [ ] Update staging rack\r\n- [ ] Edit [Rack release record](https://github.com/convox/rack/releases) and/or update [docs](https://github.com/convox/convox.github.io)\r\n- [ ] Publish release\r\n- [ ] Release CLI\r\n","created_at":"2016-07-06T14:27:44Z","updated_at":"2016-07-06T14:28:01Z","closed_at":null,"merged_at":null,"merge_commit_sha":"8e4f08f09ffb0f67d4ad72c87261fa9cb5a05729","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/convox/rack/pulls/845/commits","review_comments_url":"https://api.github.com/repos/convox/rack/pulls/845/comments","review_comment_url":"https://api.github.com/repos/convox/rack/pulls/comments{/number}","comments_url":"https://api.github.com/repos/convox/rack/issues/845/comments","statuses_url":"https://api.github.com/repos/convox/rack/statuses/1636ec603cd1ba1b8af3721efbe4f84b4b58e8be","head":{"label":"convox:one_manifest_to_rule_them_all","ref":"one_manifest_to_rule_them_all","sha":"1636ec603cd1ba1b8af3721efbe4f84b4b58e8be","user":{"login":"convox","id":10547780,"avatar_url":"https://avatars.githubusercontent.com/u/10547780?v=3","gravatar_id":"","url":"https://api.github.com/users/convox","html_url":"https://github.com/convox","followers_url":"https://api.github.com/users/convox/followers","following_url":"https://api.github.com/users/convox/following{/other_user}","gists_url":"https://api.github.com/users/convox/gists{/gist_id}","starred_url":"https://api.github.com/users/convox/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/convox/subscriptions","organizations_url":"https://api.github.com/users/convox/orgs","repos_url":"https://api.github.com/users/convox/repos","events_url":"https://api.github.com/users/convox/events{/privacy}","received_events_url":"https://api.github.com/users/convox/received_events","type":"Organization","site_admin":false},"repo":{"id":42454540,"name":"rack","full_name":"convox/rack","owner":{"login":"convox","id":10547780,"avatar_url":"https://avatars.githubusercontent.com/u/10547780?v=3","gravatar_id":"","url":"https://api.github.com/users/convox","html_url":"https://github.com/convox","followers_url":"https://api.github.com/users/convox/followers","following_url":"https://api.github.com/users/convox/following{/other_user}","gists_url":"https://api.github.com/users/convox/gists{/gist_id}","starred_url":"https://api.github.com/users/convox/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/convox/subscriptions","organizations_url":"https://api.github.com/users/convox/orgs","repos_url":"https://api.github.com/users/convox/repos","events_url":"https://api.github.com/users/convox/events{/privacy}","received_events_url":"https://api.github.com/users/convox/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/convox/rack","description":"Open-source PaaS on AWS","fork":false,"url":"https://api.github.com/repos/convox/rack","forks_url":"https://api.github.com/repos/convox/rack/forks","keys_url":"https://api.github.com/repos/convox/rack/keys{/key_id}","collaborators_url":"https://api.github.com/repos/convox/rack/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/convox/rack/teams","hooks_url":"https://api.github.com/repos/convox/rack/hooks","issue_events_url":"https://api.github.com/repos/convox/rack/issues/events{/number}","events_url":"https://api.github.com/repos/convox/rack/events","assignees_url":"https://api.github.com/repos/convox/rack/assignees{/user}","branches_url":"https://api.github.com/repos/convox/rack/branches{/branch}","tags_url":"https://api.github.com/repos/convox/rack/tags","blobs_url":"https://api.github.com/repos/convox/rack/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/convox/rack/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/convox/rack/git/refs{/sha}","trees_url":"https://api.github.com/repos/convox/rack/git/trees{/sha}","statuses_url":"https://api.github.com/repos/convox/rack/statuses/{sha}","languages_url":"https://api.github.com/repos/convox/rack/languages","stargazers_url":"https://api.github.com/repos/convox/rack/stargazers","contributors_url":"https://api.github.com/repos/convox/rack/contributors","subscribers_url":"https://api.github.com/repos/convox/rack/subscribers","subscription_url":"https://api.github.com/repos/convox/rack/subscription","commits_url":"https://api.github.com/repos/convox/rack/commits{/sha}","git_commits_url":"https://api.github.com/repos/convox/rack/git/commits{/sha}","comments_url":"https://api.github.com/repos/convox/rack/comments{/number}","issue_comment_url":"https://api.github.com/repos/convox/rack/issues/comments{/number}","contents_url":"https://api.github.com/repos/convox/rack/contents/{+path}","compare_url":"https://api.github.com/repos/convox/rack/compare/{base}...{head}","merges_url":"https://api.github.com/repos/convox/rack/merges","archive_url":"https://api.github.com/repos/convox/rack/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/convox/rack/downloads","issues_url":"https://api.github.com/repos/convox/rack/issues{/number}","pulls_url":"https://api.github.com/repos/convox/rack/pulls{/number}","milestones_url":"https://api.github.com/repos/convox/rack/milestones{/number}","notifications_url":"https://api.github.com/repos/convox/rack/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/convox/rack/labels{/name}","releases_url":"https://api.github.com/repos/convox/rack/releases{/id}","deployments_url":"https://api.github.com/repos/convox/rack/deployments","created_at":"2015-09-14T14:41:30Z","updated_at":"2016-07-06T12:32:43Z","pushed_at":"2016-07-06T14:27:44Z","git_url":"git://github.com/convox/rack.git","ssh_url":"git@github.com:convox/rack.git","clone_url":"https://github.com/convox/rack.git","svn_url":"https://github.com/convox/rack","homepage":"https://convox.com","size":52858,"stargazers_count":1212,"watchers_count":1212,"language":"Go","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":80,"mirror_url":null,"open_issues_count":118,"forks":80,"open_issues":118,"watchers":1212,"default_branch":"master"}},"base":{"label":"convox:start-refactor","ref":"start-refactor","sha":"1db0aab7052d380bb6064df67b73e18b6b12f453","user":{"login":"convox","id":10547780,"avatar_url":"https://avatars.githubusercontent.com/u/10547780?v=3","gravatar_id":"","url":"https://api.github.com/users/convox","html_url":"https://github.com/convox","followers_url":"https://api.github.com/users/convox/followers","following_url":"https://api.github.com/users/convox/following{/other_user}","gists_url":"https://api.github.com/users/convox/gists{/gist_id}","starred_url":"https://api.github.com/users/convox/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/convox/subscriptions","organizations_url":"https://api.github.com/users/convox/orgs","repos_url":"https://api.github.com/users/convox/repos","events_url":"https://api.github.com/users/convox/events{/privacy}","received_events_url":"https://api.github.com/users/convox/received_events","type":"Organization","site_admin":false},"repo":{"id":42454540,"name":"rack","full_name":"convox/rack","owner":{"login":"convox","id":10547780,"avatar_url":"https://avatars.githubusercontent.com/u/10547780?v=3","gravatar_id":"","url":"https://api.github.com/users/convox","html_url":"https://github.com/convox","followers_url":"https://api.github.com/users/convox/followers","following_url":"https://api.github.com/users/convox/following{/other_user}","gists_url":"https://api.github.com/users/convox/gists{/gist_id}","starred_url":"https://api.github.com/users/convox/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/convox/subscriptions","organizations_url":"https://api.github.com/users/convox/orgs","repos_url":"https://api.github.com/users/convox/repos","events_url":"https://api.github.com/users/convox/events{/privacy}","received_events_url":"https://api.github.com/users/convox/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/convox/rack","description":"Open-source PaaS on AWS","fork":false,"url":"https://api.github.com/repos/convox/rack","forks_url":"https://api.github.com/repos/convox/rack/forks","keys_url":"https://api.github.com/repos/convox/rack/keys{/key_id}","collaborators_url":"https://api.github.com/repos/convox/rack/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/convox/rack/teams","hooks_url":"https://api.github.com/repos/convox/rack/hooks","issue_events_url":"https://api.github.com/repos/convox/rack/issues/events{/number}","events_url":"https://api.github.com/repos/convox/rack/events","assignees_url":"https://api.github.com/repos/convox/rack/assignees{/user}","branches_url":"https://api.github.com/repos/convox/rack/branches{/branch}","tags_url":"https://api.github.com/repos/convox/rack/tags","blobs_url":"https://api.github.com/repos/convox/rack/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/convox/rack/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/convox/rack/git/refs{/sha}","trees_url":"https://api.github.com/repos/convox/rack/git/trees{/sha}","statuses_url":"https://api.github.com/repos/convox/rack/statuses/{sha}","languages_url":"https://api.github.com/repos/convox/rack/languages","stargazers_url":"https://api.github.com/repos/convox/rack/stargazers","contributors_url":"https://api.github.com/repos/convox/rack/contributors","subscribers_url":"https://api.github.com/repos/convox/rack/subscribers","subscription_url":"https://api.github.com/repos/convox/rack/subscription","commits_url":"https://api.github.com/repos/convox/rack/commits{/sha}","git_commits_url":"https://api.github.com/repos/convox/rack/git/commits{/sha}","comments_url":"https://api.github.com/repos/convox/rack/comments{/number}","issue_comment_url":"https://api.github.com/repos/convox/rack/issues/comments{/number}","contents_url":"https://api.github.com/repos/convox/rack/contents/{+path}","compare_url":"https://api.github.com/repos/convox/rack/compare/{base}...{head}","merges_url":"https://api.github.com/repos/convox/rack/merges","archive_url":"https://api.github.com/repos/convox/rack/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/convox/rack/downloads","issues_url":"https://api.github.com/repos/convox/rack/issues{/number}","pulls_url":"https://api.github.com/repos/convox/rack/pulls{/number}","milestones_url":"https://api.github.com/repos/convox/rack/milestones{/number}","notifications_url":"https://api.github.com/repos/convox/rack/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/convox/rack/labels{/name}","releases_url":"https://api.github.com/repos/convox/rack/releases{/id}","deployments_url":"https://api.github.com/repos/convox/rack/deployments","created_at":"2015-09-14T14:41:30Z","updated_at":"2016-07-06T12:32:43Z","pushed_at":"2016-07-06T14:27:44Z","git_url":"git://github.com/convox/rack.git","ssh_url":"git@github.com:convox/rack.git","clone_url":"https://github.com/convox/rack.git","svn_url":"https://github.com/convox/rack","homepage":"https://convox.com","size":52858,"stargazers_count":1212,"watchers_count":1212,"language":"Go","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":80,"mirror_url":null,"open_issues_count":118,"forks":80,"open_issues":118,"watchers":1212,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/convox/rack/pulls/845"},"html":{"href":"https://github.com/convox/rack/pull/845"},"issue":{"href":"https://api.github.com/repos/convox/rack/issues/845"},"comments":{"href":"https://api.github.com/repos/convox/rack/issues/845/comments"},"review_comments":{"href":"https://api.github.com/repos/convox/rack/pulls/845/comments"},"review_comment":{"href":"https://api.github.com/repos/convox/rack/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/convox/rack/pulls/845/commits"},"statuses":{"href":"https://api.github.com/repos/convox/rack/statuses/1636ec603cd1ba1b8af3721efbe4f84b4b58e8be"}}}}
{"actor":{"display_login":"houndci-bot"}}