{"action":"created","comment":{"url":"https://api.github.com/repos/alphagov/paas-billing/pulls/comments/215953460","pull_request_review_id":153305754,"id":215953460,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDIxNTk1MzQ2MA==","diff_hunk":"@@ -0,0 +1,359 @@\n+package eventstore_test\n+\n+import (\n+\t\"fmt\"\n+\t\"time\"\n+\n+\t\"github.com/alphagov/paas-billing/eventio\"\n+\t\"github.com/alphagov/paas-billing/eventstore\"\n+\t\"github.com/alphagov/paas-billing/testenv\"\n+\t. \"github.com/onsi/ginkgo\"\n+\t. \"github.com/onsi/gomega\"\n+)\n+\n+var _ = Describe(\"GetConsolidatedBillableEvents\", func() {\n+\tvar (\n+\t\tcfg      eventstore.Config\n+\t\tscenario *testenv.TestScenario\n+\t)\n+\n+\tBeforeEach(func() {\n+\t\tcfg = testenv.BasicConfig\n+\t\tscenario = testenv.NewTestScenario(\"2001-01-01T00:00\")\n+\t})\n+\n+\tIt(\"should match the output of GetBillableEvents for a complex scenario across multiple months\", func() {\n+\t\tscenario.AddComputePlan()\n+\n+\t\tcfg.AddVATRate(eventio.VATRate{\n+\t\t\tCode:      \"Standard\",\n+\t\t\tRate:      0,\n+\t\t\tValidFrom: \"2017-03-01\",\n+\t\t})\n+\t\tcfg.AddCurrencyRate(eventio.CurrencyRate{\n+\t\t\tCode:      \"GBP\",\n+\t\t\tRate:      2,\n+\t\t\tValidFrom: \"2017-02-01\",\n+\t\t})\n+\t\tcfg.AddCurrencyRate(eventio.CurrencyRate{\n+\t\t\tCode:      \"GBP\",\n+\t\t\tRate:      4,\n+\t\t\tValidFrom: \"2017-04-01\",\n+\t\t})\n+\n+\t\tscenario.AppLifeCycle(\"org1\", \"space1\", \"app1\",\n+\t\t\ttestenv.EventInfo{Delta: \"+0h\", State: \"STARTED\"},\n+\t\t\ttestenv.EventInfo{Delta: \"+3600h\", State: \"STOPPED\"},\n+\t\t)\n+\t\tscenario.AppLifeCycle(\"org2\", \"space2\", \"app2\",\n+\t\t\ttestenv.EventInfo{Delta: \"+12h\", State: \"STARTED\"},\n+\t\t\ttestenv.EventInfo{Delta: \"+3600h\", State: \"STOPPED\"},\n+\t\t)\n+\t\tscenario.AppLifeCycle(\"org2\", \"space2\", \"app3\",\n+\t\t\ttestenv.EventInfo{Delta: \"+24h\", State: \"STARTED\"},\n+\t\t\ttestenv.EventInfo{Delta: \"+36h\", State: \"STOPPED\"},\n+\t\t)\n+\n+\t\tdb, err := scenario.Open(cfg)\n+\t\tExpect(err).ToNot(HaveOccurred())\n+\t\tdefer db.Close()\n+\n+\t\tExpect(db.Schema.Refresh()).To(Succeed())\n+\n+\t\terr = db.Schema.Consolidate(eventio.EventFilter{\n+\t\t\tRangeStart: \"2001-01-01\",\n+\t\t\tRangeStop:  \"2001-02-01\",\n+\t\t})\n+\n+\t\tfor month := 1; month <= 4; month++ {\n+\t\t\tfilter := eventio.EventFilter{\n+\t\t\t\tRangeStart: fmt.Sprintf(\"2017-%02d-01\", month),\n+\t\t\t\tRangeStop:  fmt.Sprintf(\"2017-%02d-01\", month+1),\n+\t\t\t}\n+\t\t\terr = db.Schema.Consolidate(filter)\n+\t\t\tExpect(err).NotTo(HaveOccurred())\n+\n+\t\t\tallBillableEvents, err := db.Schema.GetBillableEvents(filter)\n+\t\t\tExpect(err).ToNot(HaveOccurred())\n+\t\t\tallConsolidatedBillableEvents, err := db.Schema.GetConsolidatedBillableEvents(filter)\n+\t\t\tExpect(err).ToNot(HaveOccurred())\n+\t\t\tExpect(allBillableEvents).To(Equal(allConsolidatedBillableEvents))\n+\n+\t\t\tfilter.OrgGUIDs = []string{scenario.GetOrgGUID(\"org1\")}\n+\t\t\tallOrg1BillableEvents, err := db.Schema.GetBillableEvents(filter)\n+\t\t\tExpect(err).ToNot(HaveOccurred())\n+\t\t\tallOrg1ConsolidatedBillableEvents, err := db.Schema.GetConsolidatedBillableEvents(filter)\n+\t\t\tExpect(err).ToNot(HaveOccurred())\n+\t\t\tExpect(allOrg1BillableEvents).To(Equal(allOrg1ConsolidatedBillableEvents))\n+\n+\t\t\tfilter.OrgGUIDs = []string{scenario.GetOrgGUID(\"org2\")}\n+\t\t\tallOrg2BillableEvents, err := db.Schema.GetBillableEvents(filter)\n+\t\t\tExpect(err).ToNot(HaveOccurred())\n+\t\t\tallOrg2ConsolidatedBillableEvents, err := db.Schema.GetConsolidatedBillableEvents(filter)\n+\t\t\tExpect(err).ToNot(HaveOccurred())\n+\t\t\tExpect(allOrg2BillableEvents).To(Equal(allOrg2ConsolidatedBillableEvents))\n+\t\t}\n+\t})\n+\n+\tIt(\"Should fail to GetBillableEvents if query range is not one month\", func() {\n+\t\tdb, err := scenario.Open(cfg)\n+\t\tExpect(err).ToNot(HaveOccurred())\n+\t\tdefer db.Close()\n+\n+\t\terr = db.Schema.Consolidate(eventio.EventFilter{\n+\t\t\tRangeStart: \"2001-01-01\",\n+\t\t\tRangeStop:  \"2001-02-01\",\n+\t\t})\n+\t\tExpect(err).ToNot(HaveOccurred())\n+\n+\t\t_, err = db.Schema.GetConsolidatedBillableEvents(eventio.EventFilter{\n+\t\t\tRangeStart: \"2001-02-01\",\n+\t\t\tRangeStop:  \"2001-02-02\",\n+\t\t})\n+\t\tExpect(err).To(MatchError(\"consolidation only works with ranges starting and ending on month boundaries\"))\n+\n+\t\t_, err = db.Schema.GetConsolidatedBillableEvents(eventio.EventFilter{\n+\t\t\tRangeStart: \"2001-01-15\",\n+\t\t\tRangeStop:  \"2001-02-15\",\n+\t\t})\n+\t\tExpect(err).To(MatchError(\"consolidation only works with ranges starting and ending on month boundaries\"))\n+\t})\n+})\n+\n+var _ = Describe(\"Consolidate\", func() {\n+\tvar (\n+\t\tcfg      eventstore.Config\n+\t\tscenario *testenv.TestScenario\n+\t)\n+\n+\tBeforeEach(func() {\n+\t\tcfg = testenv.BasicConfig\n+\t\tscenario = testenv.NewTestScenario(\"2001-01-01T00:00\")\n+\t})\n+\n+\tIt(\"Should fail to Consolidate if organisation filter provided\", func() {\n+\t\tdb, err := scenario.Open(cfg)\n+\t\tExpect(err).ToNot(HaveOccurred())\n+\t\tdefer db.Close()\n+\n+\t\terr = db.Schema.Consolidate(eventio.EventFilter{\n+\t\t\tRangeStart: \"2001-01-02\",\n+\t\t\tRangeStop:  \"2001-02-02\",\n+\t\t\tOrgGUIDs:   []string{\"banana\", \"pear\"},\n+\t\t})\n+\t\tExpect(err).To(MatchError(\n+\t\t\t\"consolidate must be called without an organisations filter (i.e. for all orgs)\",\n+\t\t))\n+\t})\n+\n+\tIt(\"Should fail to Consolidate if query range is not exactly one month\", func() {\n+\t\tdb, err := scenario.Open(cfg)\n+\t\tExpect(err).ToNot(HaveOccurred())\n+\t\tdefer db.Close()\n+\n+\t\terr = db.Schema.Consolidate(eventio.EventFilter{\n+\t\t\tRangeStart: \"2001-01-02\",\n+\t\t\tRangeStop:  \"2001-02-02\",\n+\t\t})\n+\t\tExpect(err).To(MatchError(\n+\t\t\tMatchRegexp(\"violates check constraint\"),\n+\t\t))\n+\n+\t\terr = db.Schema.Consolidate(eventio.EventFilter{\n+\t\t\tRangeStart: \"2001-01-01\",\n+\t\t\tRangeStop:  \"2001-07-01\",\n+\t\t})\n+\t\tExpect(err).To(MatchError(\n+\t\t\tMatchRegexp(\"violates check constraint\"),\n+\t\t))\n+\t})\n+\n+\tIt(\"Should fail if consolidate called twice for the same range\", func() {\n+\t\tdb, err := scenario.Open(cfg)\n+\t\tExpect(err).ToNot(HaveOccurred())\n+\t\tdefer db.Close()\n+\n+\t\terr = db.Schema.Consolidate(eventio.EventFilter{\n+\t\t\tRangeStart: \"2001-01-01\",\n+\t\t\tRangeStop:  \"2001-02-01\",\n+\t\t})\n+\t\tExpect(err).ToNot(HaveOccurred())\n+\t\terr = db.Schema.Consolidate(eventio.EventFilter{\n+\t\t\tRangeStart: \"2001-01-01\",\n+\t\t\tRangeStop:  \"2001-02-01\",\n+\t\t})\n+\t\tExpect(err).To(MatchError(MatchRegexp(\"duplicate key value violates unique constraint\")))\n+\t})\n+})\n+\n+var _ = Describe(\"IsRangeConsolidated\", func() {\n+\tvar (\n+\t\tcfg      eventstore.Config\n+\t\tscenario *testenv.TestScenario\n+\t)\n+\n+\tBeforeEach(func() {\n+\t\tcfg = testenv.BasicConfig\n+\t\tscenario = testenv.NewTestScenario(\"2001-01-01T00:00\")\n+\t})\n+\n+\tIt(\"Should return false if range has not been consolidated\", func() {\n+\t\tdb, err := scenario.Open(cfg)\n+\t\tExpect(err).ToNot(HaveOccurred())\n+\t\tdefer db.Close()\n+\n+\t\tresult, err := db.Schema.IsRangeConsolidated(eventio.EventFilter{\n+\t\t\tRangeStart: \"2001-01-01\",\n+\t\t\tRangeStop:  \"2001-02-01\",\n+\t\t})\n+\t\tExpect(err).NotTo(HaveOccurred())\n+\t\tExpect(result).To(BeFalse())\n+\t})\n+\n+\tIt(\"Should return true if range has been consolidated\", func() {\n+\t\tdb, err := scenario.Open(cfg)\n+\t\tExpect(err).ToNot(HaveOccurred())\n+\t\tdefer db.Close()\n+\n+\t\tfilter := eventio.EventFilter{\n+\t\t\tRangeStart: \"2001-01-01\",\n+\t\t\tRangeStop:  \"2001-02-01\",\n+\t\t}\n+\n+\t\tdb.Schema.Consolidate(filter)\n+\t\tresult, err := db.Schema.IsRangeConsolidated(filter)\n+\n+\t\tExpect(err).NotTo(HaveOccurred())\n+\t\tExpect(result).To(BeTrue())\n+\t})\n+\n+})\n+\n+var _ = Describe(\"ConsolidateFullMonths\", func() {\n+\tvar (\n+\t\tcfg      eventstore.Config\n+\t\tscenario *testenv.TestScenario\n+\t\tnow      string\n+\t)\n+\n+\tBeforeEach(func() {\n+\t\tcfg = testenv.BasicConfig\n+\t\tscenario = testenv.NewTestScenario(\"2018-01-01T00:00\")\n+\t\tnow = time.Now().Format(\"2006-01-02\")\n+\t})\n+\n+\tIt(\"Should not error when there are no time periods to consolidate\", func() {\n+\t\tdb, err := scenario.Open(cfg)\n+\t\tExpect(err).ToNot(HaveOccurred())\n+\t\tdefer db.Close()\n+\n+\t\terr = db.Schema.ConsolidateFullMonths(\"9001-01-01\", now)\n+\t\tExpect(err).NotTo(HaveOccurred())\n+\t})\n+\n+\tIt(\"Should consolidate events which have not been consolidated yet \", func() {\n+\t\tdb, err := scenario.Open(cfg)\n+\t\tExpect(err).ToNot(HaveOccurred())\n+\t\tdefer db.Close()\n+\n+\t\t// Consolidate everything since 2001\n+\t\tconsolidateSince := \"2017-01-01\"","path":"eventstore/store_consolidated_billable_events_test.go","position":260,"original_position":260,"commit_id":"c6e70593541ae845ebc094b8295b9a0070e4cda2","original_commit_id":"c6e70593541ae845ebc094b8295b9a0070e4cda2","user":{"login":"blairboy362","id":12373655,"node_id":"MDQ6VXNlcjEyMzczNjU1","avatar_url":"https://avatars2.githubusercontent.com/u/12373655?v=4","gravatar_id":"","url":"https://api.github.com/users/blairboy362","html_url":"https://github.com/blairboy362","followers_url":"https://api.github.com/users/blairboy362/followers","following_url":"https://api.github.com/users/blairboy362/following{/other_user}","gists_url":"https://api.github.com/users/blairboy362/gists{/gist_id}","starred_url":"https://api.github.com/users/blairboy362/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/blairboy362/subscriptions","organizations_url":"https://api.github.com/users/blairboy362/orgs","repos_url":"https://api.github.com/users/blairboy362/repos","events_url":"https://api.github.com/users/blairboy362/events{/privacy}","received_events_url":"https://api.github.com/users/blairboy362/received_events","type":"User","site_admin":false},"body":"The comment doesn't match what this line is doing. Please update whichever is correct so they match.","created_at":"2018-09-07T13:13:15Z","updated_at":"2018-09-07T13:33:09Z","html_url":"https://github.com/alphagov/paas-billing/pull/53#discussion_r215953460","pull_request_url":"https://api.github.com/repos/alphagov/paas-billing/pulls/53","author_association":"NONE","_links":{"self":{"href":"https://api.github.com/repos/alphagov/paas-billing/pulls/comments/215953460"},"html":{"href":"https://github.com/alphagov/paas-billing/pull/53#discussion_r215953460"},"pull_request":{"href":"https://api.github.com/repos/alphagov/paas-billing/pulls/53"}}},"pull_request":{"url":"https://api.github.com/repos/alphagov/paas-billing/pulls/53","id":213631077,"node_id":"MDExOlB1bGxSZXF1ZXN0MjEzNjMxMDc3","html_url":"https://github.com/alphagov/paas-billing/pull/53","diff_url":"https://github.com/alphagov/paas-billing/pull/53.diff","patch_url":"https://github.com/alphagov/paas-billing/pull/53.patch","issue_url":"https://api.github.com/repos/alphagov/paas-billing/issues/53","number":53,"state":"open","locked":false,"title":"[#159234320] Add consolidation of billable events by month","user":{"login":"keymon","id":280032,"node_id":"MDQ6VXNlcjI4MDAzMg==","avatar_url":"https://avatars0.githubusercontent.com/u/280032?v=4","gravatar_id":"","url":"https://api.github.com/users/keymon","html_url":"https://github.com/keymon","followers_url":"https://api.github.com/users/keymon/followers","following_url":"https://api.github.com/users/keymon/following{/other_user}","gists_url":"https://api.github.com/users/keymon/gists{/gist_id}","starred_url":"https://api.github.com/users/keymon/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/keymon/subscriptions","organizations_url":"https://api.github.com/users/keymon/orgs","repos_url":"https://api.github.com/users/keymon/repos","events_url":"https://api.github.com/users/keymon/events{/privacy}","received_events_url":"https://api.github.com/users/keymon/received_events","type":"User","site_admin":false},"body":"What\n----\n\nWe want to persist/freeze the billing statement data at the end of each\nmonth, so the bills do not change between months due whatever reason:\n - code changes\n - plan, currency changes\n - new events.\n\nWe also want performance querying a bill to improve.\n\nIn our implementation we decided to compute and store all the billable\nevents in a consolidated table, stored per full month.\n\nWe implemented in a way that can later be extended to:\n - Allow multiple consolidations to co-exist, so we can compare\n   between changes. (e.g. to emit credit notices).\n - Query the history.\n\n\nImplementation details:\n\n - We added two tables:\n    - `consolidation_history`: Ranges for which we have run\n      the consolidation and other data (currently only timestamp).\n    - `consoliidation_billable_events`: All the events computed for\n      the given consolidation.\n\n - We use the same query that generate the \"realtime\" billable events to\n   generate the consolidated events, storing the raw json `price` after\n   computation.\n\n - We consolidate FULL months (from 1st to 1st only).\n\n - Currently we consolidate all the full months from 2017-07-01\n   (when we started storing events) till the last month passed the 5th\n   of each month.\n\n - We do not consolidate until the 5th of the next month to ensure we\n   have retrieved all service events\n\n - Currently consolidation only runs once for each full month, and never\n   more. We did not implement logic to recompute the consolidation.\n\n - Currrently To recompute consolidated, you must delete the consolidate data.\n\n\n - We extend the `/billable_events` endpoint to split the range of\n   dates of the query, and check return the events of is  full month\n   that is consolidated\n\n\n\nHow to review\n-----\n\n - Code review\n - Run tests\n\nCompare with live data\n-----------------------\n\nWIP\n\nWho can review\n-----\n\nNot @keymon or @richardTowers","created_at":"2018-09-06T14:06:16Z","updated_at":"2018-09-07T13:33:09Z","closed_at":null,"merged_at":null,"merge_commit_sha":"3ed6243a2d2b77b6af07c7a6adcf4f2285df167f","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/alphagov/paas-billing/pulls/53/commits","review_comments_url":"https://api.github.com/repos/alphagov/paas-billing/pulls/53/comments","review_comment_url":"https://api.github.com/repos/alphagov/paas-billing/pulls/comments{/number}","comments_url":"https://api.github.com/repos/alphagov/paas-billing/issues/53/comments","statuses_url":"https://api.github.com/repos/alphagov/paas-billing/statuses/c6e70593541ae845ebc094b8295b9a0070e4cda2","head":{"label":"alphagov:persist_billing_statements_159234320","ref":"persist_billing_statements_159234320","sha":"c6e70593541ae845ebc094b8295b9a0070e4cda2","user":{"login":"alphagov","id":596977,"node_id":"MDEyOk9yZ2FuaXphdGlvbjU5Njk3Nw==","avatar_url":"https://avatars0.githubusercontent.com/u/596977?v=4","gravatar_id":"","url":"https://api.github.com/users/alphagov","html_url":"https://github.com/alphagov","followers_url":"https://api.github.com/users/alphagov/followers","following_url":"https://api.github.com/users/alphagov/following{/other_user}","gists_url":"https://api.github.com/users/alphagov/gists{/gist_id}","starred_url":"https://api.github.com/users/alphagov/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/alphagov/subscriptions","organizations_url":"https://api.github.com/users/alphagov/orgs","repos_url":"https://api.github.com/users/alphagov/repos","events_url":"https://api.github.com/users/alphagov/events{/privacy}","received_events_url":"https://api.github.com/users/alphagov/received_events","type":"Organization","site_admin":false},"repo":{"id":106835027,"node_id":"MDEwOlJlcG9zaXRvcnkxMDY4MzUwMjc=","name":"paas-billing","full_name":"alphagov/paas-billing","owner":{"login":"alphagov","id":596977,"node_id":"MDEyOk9yZ2FuaXphdGlvbjU5Njk3Nw==","avatar_url":"https://avatars0.githubusercontent.com/u/596977?v=4","gravatar_id":"","url":"https://api.github.com/users/alphagov","html_url":"https://github.com/alphagov","followers_url":"https://api.github.com/users/alphagov/followers","following_url":"https://api.github.com/users/alphagov/following{/other_user}","gists_url":"https://api.github.com/users/alphagov/gists{/gist_id}","starred_url":"https://api.github.com/users/alphagov/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/alphagov/subscriptions","organizations_url":"https://api.github.com/users/alphagov/orgs","repos_url":"https://api.github.com/users/alphagov/repos","events_url":"https://api.github.com/users/alphagov/events{/privacy}","received_events_url":"https://api.github.com/users/alphagov/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/alphagov/paas-billing","description":"A Go application for generating billing data from cloudfoundry events","fork":false,"url":"https://api.github.com/repos/alphagov/paas-billing","forks_url":"https://api.github.com/repos/alphagov/paas-billing/forks","keys_url":"https://api.github.com/repos/alphagov/paas-billing/keys{/key_id}","collaborators_url":"https://api.github.com/repos/alphagov/paas-billing/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/alphagov/paas-billing/teams","hooks_url":"https://api.github.com/repos/alphagov/paas-billing/hooks","issue_events_url":"https://api.github.com/repos/alphagov/paas-billing/issues/events{/number}","events_url":"https://api.github.com/repos/alphagov/paas-billing/events","assignees_url":"https://api.github.com/repos/alphagov/paas-billing/assignees{/user}","branches_url":"https://api.github.com/repos/alphagov/paas-billing/branches{/branch}","tags_url":"https://api.github.com/repos/alphagov/paas-billing/tags","blobs_url":"https://api.github.com/repos/alphagov/paas-billing/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/alphagov/paas-billing/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/alphagov/paas-billing/git/refs{/sha}","trees_url":"https://api.github.com/repos/alphagov/paas-billing/git/trees{/sha}","statuses_url":"https://api.github.com/repos/alphagov/paas-billing/statuses/{sha}","languages_url":"https://api.github.com/repos/alphagov/paas-billing/languages","stargazers_url":"https://api.github.com/repos/alphagov/paas-billing/stargazers","contributors_url":"https://api.github.com/repos/alphagov/paas-billing/contributors","subscribers_url":"https://api.github.com/repos/alphagov/paas-billing/subscribers","subscription_url":"https://api.github.com/repos/alphagov/paas-billing/subscription","commits_url":"https://api.github.com/repos/alphagov/paas-billing/commits{/sha}","git_commits_url":"https://api.github.com/repos/alphagov/paas-billing/git/commits{/sha}","comments_url":"https://api.github.com/repos/alphagov/paas-billing/comments{/number}","issue_comment_url":"https://api.github.com/repos/alphagov/paas-billing/issues/comments{/number}","contents_url":"https://api.github.com/repos/alphagov/paas-billing/contents/{+path}","compare_url":"https://api.github.com/repos/alphagov/paas-billing/compare/{base}...{head}","merges_url":"https://api.github.com/repos/alphagov/paas-billing/merges","archive_url":"https://api.github.com/repos/alphagov/paas-billing/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/alphagov/paas-billing/downloads","issues_url":"https://api.github.com/repos/alphagov/paas-billing/issues{/number}","pulls_url":"https://api.github.com/repos/alphagov/paas-billing/pulls{/number}","milestones_url":"https://api.github.com/repos/alphagov/paas-billing/milestones{/number}","notifications_url":"https://api.github.com/repos/alphagov/paas-billing/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/alphagov/paas-billing/labels{/name}","releases_url":"https://api.github.com/repos/alphagov/paas-billing/releases{/id}","deployments_url":"https://api.github.com/repos/alphagov/paas-billing/deployments","created_at":"2017-10-13T14:31:13Z","updated_at":"2018-09-06T08:37:13Z","pushed_at":"2018-09-07T13:05:18Z","git_url":"git://github.com/alphagov/paas-billing.git","ssh_url":"git@github.com:alphagov/paas-billing.git","clone_url":"https://github.com/alphagov/paas-billing.git","svn_url":"https://github.com/alphagov/paas-billing","homepage":"","size":12584,"stargazers_count":1,"watchers_count":1,"language":"Go","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":1,"mirror_url":null,"archived":false,"open_issues_count":5,"license":{"key":"mit","name":"MIT License","spdx_id":"MIT","url":"https://api.github.com/licenses/mit","node_id":"MDc6TGljZW5zZTEz"},"forks":1,"open_issues":5,"watchers":1,"default_branch":"master"}},"base":{"label":"alphagov:master","ref":"master","sha":"bcafc0c87bcd3343eb604cac2cd553c4813c64e7","user":{"login":"alphagov","id":596977,"node_id":"MDEyOk9yZ2FuaXphdGlvbjU5Njk3Nw==","avatar_url":"https://avatars0.githubusercontent.com/u/596977?v=4","gravatar_id":"","url":"https://api.github.com/users/alphagov","html_url":"https://github.com/alphagov","followers_url":"https://api.github.com/users/alphagov/followers","following_url":"https://api.github.com/users/alphagov/following{/other_user}","gists_url":"https://api.github.com/users/alphagov/gists{/gist_id}","starred_url":"https://api.github.com/users/alphagov/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/alphagov/subscriptions","organizations_url":"https://api.github.com/users/alphagov/orgs","repos_url":"https://api.github.com/users/alphagov/repos","events_url":"https://api.github.com/users/alphagov/events{/privacy}","received_events_url":"https://api.github.com/users/alphagov/received_events","type":"Organization","site_admin":false},"repo":{"id":106835027,"node_id":"MDEwOlJlcG9zaXRvcnkxMDY4MzUwMjc=","name":"paas-billing","full_name":"alphagov/paas-billing","owner":{"login":"alphagov","id":596977,"node_id":"MDEyOk9yZ2FuaXphdGlvbjU5Njk3Nw==","avatar_url":"https://avatars0.githubusercontent.com/u/596977?v=4","gravatar_id":"","url":"https://api.github.com/users/alphagov","html_url":"https://github.com/alphagov","followers_url":"https://api.github.com/users/alphagov/followers","following_url":"https://api.github.com/users/alphagov/following{/other_user}","gists_url":"https://api.github.com/users/alphagov/gists{/gist_id}","starred_url":"https://api.github.com/users/alphagov/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/alphagov/subscriptions","organizations_url":"https://api.github.com/users/alphagov/orgs","repos_url":"https://api.github.com/users/alphagov/repos","events_url":"https://api.github.com/users/alphagov/events{/privacy}","received_events_url":"https://api.github.com/users/alphagov/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/alphagov/paas-billing","description":"A Go application for generating billing data from cloudfoundry events","fork":false,"url":"https://api.github.com/repos/alphagov/paas-billing","forks_url":"https://api.github.com/repos/alphagov/paas-billing/forks","keys_url":"https://api.github.com/repos/alphagov/paas-billing/keys{/key_id}","collaborators_url":"https://api.github.com/repos/alphagov/paas-billing/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/alphagov/paas-billing/teams","hooks_url":"https://api.github.com/repos/alphagov/paas-billing/hooks","issue_events_url":"https://api.github.com/repos/alphagov/paas-billing/issues/events{/number}","events_url":"https://api.github.com/repos/alphagov/paas-billing/events","assignees_url":"https://api.github.com/repos/alphagov/paas-billing/assignees{/user}","branches_url":"https://api.github.com/repos/alphagov/paas-billing/branches{/branch}","tags_url":"https://api.github.com/repos/alphagov/paas-billing/tags","blobs_url":"https://api.github.com/repos/alphagov/paas-billing/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/alphagov/paas-billing/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/alphagov/paas-billing/git/refs{/sha}","trees_url":"https://api.github.com/repos/alphagov/paas-billing/git/trees{/sha}","statuses_url":"https://api.github.com/repos/alphagov/paas-billing/statuses/{sha}","languages_url":"https://api.github.com/repos/alphagov/paas-billing/languages","stargazers_url":"https://api.github.com/repos/alphagov/paas-billing/stargazers","contributors_url":"https://api.github.com/repos/alphagov/paas-billing/contributors","subscribers_url":"https://api.github.com/repos/alphagov/paas-billing/subscribers","subscription_url":"https://api.github.com/repos/alphagov/paas-billing/subscription","commits_url":"https://api.github.com/repos/alphagov/paas-billing/commits{/sha}","git_commits_url":"https://api.github.com/repos/alphagov/paas-billing/git/commits{/sha}","comments_url":"https://api.github.com/repos/alphagov/paas-billing/comments{/number}","issue_comment_url":"https://api.github.com/repos/alphagov/paas-billing/issues/comments{/number}","contents_url":"https://api.github.com/repos/alphagov/paas-billing/contents/{+path}","compare_url":"https://api.github.com/repos/alphagov/paas-billing/compare/{base}...{head}","merges_url":"https://api.github.com/repos/alphagov/paas-billing/merges","archive_url":"https://api.github.com/repos/alphagov/paas-billing/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/alphagov/paas-billing/downloads","issues_url":"https://api.github.com/repos/alphagov/paas-billing/issues{/number}","pulls_url":"https://api.github.com/repos/alphagov/paas-billing/pulls{/number}","milestones_url":"https://api.github.com/repos/alphagov/paas-billing/milestones{/number}","notifications_url":"https://api.github.com/repos/alphagov/paas-billing/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/alphagov/paas-billing/labels{/name}","releases_url":"https://api.github.com/repos/alphagov/paas-billing/releases{/id}","deployments_url":"https://api.github.com/repos/alphagov/paas-billing/deployments","created_at":"2017-10-13T14:31:13Z","updated_at":"2018-09-06T08:37:13Z","pushed_at":"2018-09-07T13:05:18Z","git_url":"git://github.com/alphagov/paas-billing.git","ssh_url":"git@github.com:alphagov/paas-billing.git","clone_url":"https://github.com/alphagov/paas-billing.git","svn_url":"https://github.com/alphagov/paas-billing","homepage":"","size":12584,"stargazers_count":1,"watchers_count":1,"language":"Go","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":1,"mirror_url":null,"archived":false,"open_issues_count":5,"license":{"key":"mit","name":"MIT License","spdx_id":"MIT","url":"https://api.github.com/licenses/mit","node_id":"MDc6TGljZW5zZTEz"},"forks":1,"open_issues":5,"watchers":1,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/alphagov/paas-billing/pulls/53"},"html":{"href":"https://github.com/alphagov/paas-billing/pull/53"},"issue":{"href":"https://api.github.com/repos/alphagov/paas-billing/issues/53"},"comments":{"href":"https://api.github.com/repos/alphagov/paas-billing/issues/53/comments"},"review_comments":{"href":"https://api.github.com/repos/alphagov/paas-billing/pulls/53/comments"},"review_comment":{"href":"https://api.github.com/repos/alphagov/paas-billing/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/alphagov/paas-billing/pulls/53/commits"},"statuses":{"href":"https://api.github.com/repos/alphagov/paas-billing/statuses/c6e70593541ae845ebc094b8295b9a0070e4cda2"}},"author_association":"CONTRIBUTOR"}}
{"actor":{"display_login":"blairboy362"}}