Skip to content

Commit 7cdf4e8

Browse files
committed
fix: quantity being a float and not an int
The API doc is not consistent with the actual output from the api. The quantity is not an int, but a float.
1 parent f1b11e1 commit 7cdf4e8

File tree

4 files changed

+474
-0
lines changed

4 files changed

+474
-0
lines changed

github/billing.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,46 @@ type AdvancedSecurityCommittersBreakdown struct {
6363
LastPushedDate *string `json:"last_pushed_date,omitempty"`
6464
}
6565

66+
// UsageReportOptions specifies optional parameters for the enhanced billing platform usage report.
67+
type UsageReportOptions struct {
68+
// If specified, only return results for a single year. The value of year is an integer with four digits representing a year. For example, 2025.
69+
// Default value is the current year.
70+
Year *int `url:"year,omitempty"`
71+
72+
// If specified, only return results for a single month. The value of month is an integer between 1 and 12.
73+
// If no year is specified the default year is used.
74+
Month *int `url:"month,omitempty"`
75+
76+
// If specified, only return results for a single day. The value of day is an integer between 1 and 31.
77+
// If no year or month is specified, the default year and month are used.
78+
Day *int `url:"day,omitempty"`
79+
80+
// If specified, only return results for a single hour. The value of hour is an integer between 0 and 23.
81+
// If no year, month, or day is specified, the default year, month, and day are used.
82+
Hour *int `url:"hour,omitempty"`
83+
}
84+
85+
// UsageItem represents a single usage item in the enhanced billing platform report.
86+
type UsageItem struct {
87+
Date *string `json:"date"`
88+
Product *string `json:"product"`
89+
SKU *string `json:"sku"`
90+
Quantity *float64 `json:"quantity"`
91+
UnitType *string `json:"unitType"`
92+
PricePerUnit *float64 `json:"pricePerUnit"`
93+
GrossAmount *float64 `json:"grossAmount"`
94+
DiscountAmount *float64 `json:"discountAmount"`
95+
NetAmount *float64 `json:"netAmount"`
96+
RepositoryName *string `json:"repositoryName,omitempty"`
97+
// Organization name is only used for organization-level reports.
98+
OrganizationName *string `json:"organizationName,omitempty"`
99+
}
100+
101+
// UsageReport represents the enhanced billing platform usage report response.
102+
type UsageReport struct {
103+
UsageItems []*UsageItem `json:"usageItems,omitempty"`
104+
}
105+
66106
// GetActionsBillingOrg returns the summary of the free and paid GitHub Actions minutes used for an Org.
67107
//
68108
// GitHub API docs: https://docs.github.com/rest/billing/billing#get-github-actions-billing-for-an-organization

github/billing_test.go

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -510,3 +510,167 @@ func TestBillingService_GetAdvancedSecurityActiveCommittersOrg_invalidOrg(t *tes
510510
_, _, err := client.Billing.GetAdvancedSecurityActiveCommittersOrg(ctx, "%", nil)
511511
testURLParseError(t, err)
512512
}
513+
514+
func TestBillingService_GetUsageReportOrg(t *testing.T) {
515+
t.Parallel()
516+
client, mux, _ := setup(t)
517+
518+
mux.HandleFunc("/organizations/o/settings/billing/usage", func(w http.ResponseWriter, r *http.Request) {
519+
testMethod(t, r, "GET")
520+
testFormValues(t, r, values{
521+
"year": "2023",
522+
"month": "8",
523+
})
524+
fmt.Fprint(w, `{
525+
"usageItems": [
526+
{
527+
"date": "2023-08-01",
528+
"product": "Actions",
529+
"sku": "Actions Linux",
530+
"quantity": 100,
531+
"unitType": "minutes",
532+
"pricePerUnit": 0.008,
533+
"grossAmount": 0.8,
534+
"discountAmount": 0,
535+
"netAmount": 0.8,
536+
"organizationName": "GitHub",
537+
"repositoryName": "github/example"
538+
}
539+
]
540+
}`)
541+
})
542+
543+
ctx := context.Background()
544+
opts := &UsageReportOptions{
545+
Year: Ptr(2023),
546+
Month: Ptr(8),
547+
}
548+
report, _, err := client.Billing.GetUsageReportOrg(ctx, "o", opts)
549+
if err != nil {
550+
t.Errorf("Billing.GetUsageReportOrg returned error: %v", err)
551+
}
552+
553+
want := &UsageReport{
554+
UsageItems: []*UsageItem{
555+
{
556+
Date: Ptr("2023-08-01"),
557+
Product: Ptr("Actions"),
558+
SKU: Ptr("Actions Linux"),
559+
Quantity: Ptr(100.0),
560+
UnitType: Ptr("minutes"),
561+
PricePerUnit: Ptr(0.008),
562+
GrossAmount: Ptr(0.8),
563+
DiscountAmount: Ptr(0.0),
564+
NetAmount: Ptr(0.8),
565+
OrganizationName: Ptr("GitHub"),
566+
RepositoryName: Ptr("github/example"),
567+
},
568+
},
569+
}
570+
if !cmp.Equal(report, want) {
571+
t.Errorf("Billing.GetUsageReportOrg returned %+v, want %+v", report, want)
572+
}
573+
574+
const methodName = "GetUsageReportOrg"
575+
testBadOptions(t, methodName, func() (err error) {
576+
_, _, err = client.Billing.GetUsageReportOrg(ctx, "\n", opts)
577+
return err
578+
})
579+
580+
testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
581+
got, resp, err := client.Billing.GetUsageReportOrg(ctx, "o", nil)
582+
if got != nil {
583+
t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
584+
}
585+
return resp, err
586+
})
587+
}
588+
589+
func TestBillingService_GetUsageReportOrg_invalidOrg(t *testing.T) {
590+
t.Parallel()
591+
client, _, _ := setup(t)
592+
593+
ctx := context.Background()
594+
_, _, err := client.Billing.GetUsageReportOrg(ctx, "%", nil)
595+
testURLParseError(t, err)
596+
}
597+
598+
func TestBillingService_GetUsageReportUser(t *testing.T) {
599+
t.Parallel()
600+
client, mux, _ := setup(t)
601+
602+
mux.HandleFunc("/users/u/settings/billing/usage", func(w http.ResponseWriter, r *http.Request) {
603+
testMethod(t, r, "GET")
604+
testFormValues(t, r, values{
605+
"day": "15",
606+
})
607+
fmt.Fprint(w, `{
608+
"usageItems": [
609+
{
610+
"date": "2023-08-15",
611+
"product": "Codespaces",
612+
"sku": "Codespaces Linux",
613+
"quantity": 50,
614+
"unitType": "hours",
615+
"pricePerUnit": 0.18,
616+
"grossAmount": 9.0,
617+
"discountAmount": 1.0,
618+
"netAmount": 8.0,
619+
"repositoryName": "user/example"
620+
}
621+
]
622+
}`)
623+
})
624+
625+
ctx := context.Background()
626+
opts := &UsageReportOptions{
627+
Day: Ptr(15),
628+
}
629+
report, _, err := client.Billing.GetUsageReportUser(ctx, "u", opts)
630+
if err != nil {
631+
t.Errorf("Billing.GetUsageReportUser returned error: %v", err)
632+
}
633+
634+
want := &UsageReport{
635+
UsageItems: []*UsageItem{
636+
{
637+
Date: Ptr("2023-08-15"),
638+
Product: Ptr("Codespaces"),
639+
SKU: Ptr("Codespaces Linux"),
640+
Quantity: Ptr(50.0),
641+
UnitType: Ptr("hours"),
642+
PricePerUnit: Ptr(0.18),
643+
GrossAmount: Ptr(9.0),
644+
DiscountAmount: Ptr(1.0),
645+
NetAmount: Ptr(8.0),
646+
RepositoryName: Ptr("user/example"),
647+
},
648+
},
649+
}
650+
if !cmp.Equal(report, want) {
651+
t.Errorf("Billing.GetUsageReportUser returned %+v, want %+v", report, want)
652+
}
653+
654+
const methodName = "GetUsageReportUser"
655+
testBadOptions(t, methodName, func() (err error) {
656+
_, _, err = client.Billing.GetUsageReportUser(ctx, "\n", opts)
657+
return err
658+
})
659+
660+
testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
661+
got, resp, err := client.Billing.GetUsageReportUser(ctx, "u", nil)
662+
if got != nil {
663+
t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
664+
}
665+
return resp, err
666+
})
667+
}
668+
669+
func TestBillingService_GetUsageReportUser_invalidUser(t *testing.T) {
670+
t.Parallel()
671+
client, _, _ := setup(t)
672+
673+
ctx := context.Background()
674+
_, _, err := client.Billing.GetUsageReportUser(ctx, "%", nil)
675+
testURLParseError(t, err)
676+
}

github/github-accessors.go

Lines changed: 120 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)