Skip to content

♻️ Refine billing usage modeling and JSON output#104

Merged
stoe merged 5 commits intomainfrom
stoe/billing
Apr 1, 2026
Merged

♻️ Refine billing usage modeling and JSON output#104
stoe merged 5 commits intomainfrom
stoe/billing

Conversation

@stoe
Copy link
Copy Markdown
Owner

@stoe stoe commented Feb 23, 2026

Summary

  • Refactored billing structs to properly separate usage quantities from dollar costs
  • Fixed API field mappings to match GitHub's unified billing API response structure
  • Prevented scientific notation in JSON output for very small cost values
  • Enhanced documentation with comprehensive field descriptions and usage notes

Changes

Core Improvements (cmd/billing.go)

  • Enhanced API response structs: Added TimePeriod, renamed QuantityGrossQuantity/NetQuantity/DiscountQuantity to match API exactly
  • Separated concerns: Added distinct cost fields (GrossAmount, DiscountAmount, NetAmount) to ActionsBilling, PackagesBilling, and StorageBilling structs
  • Fixed aggregation logic: Updated functions to correctly aggregate quantities (minutes/GB) separately from costs (USD)
  • Custom JSON marshaler: Implemented MarshalJSON for BillingReportJSON to prevent scientific notation (e.g., 0.0000000450 instead of 1.35e-7)
  • Improved error handling: Enhanced error detection for 403, 404, 422, 500, 502, 503 status codes
  • API endpoint update: Changed from /usage to /usage/summary for unified billing platform
  • Git LFS support: Added handling for Git LFS storage in aggregation

Testing (cmd/billing_test.go)

  • Updated test fixtures to use new field names (GrossQuantity, NetQuantity, etc.)
  • Added cost validation assertions for both quantities and dollar amounts
  • Implemented tolerance-based floating-point comparison to prevent precision issues

JSON Utilities (internal/utils/json.go)

  • Added 2-space indentation for readable output
  • Disabled HTML escaping for cleaner JSON
  • Enhanced error handling with proper wrapping

Documentation (docs/report_billing.md)

  • Added comprehensive Output Fields section explaining all billing report types
  • Documented each field with units and when they appear (e.g., cost fields with --show-costs)
  • Added Notes section clarifying quantity vs cost field distinction
  • Explained JSON formatting behavior and precision handling

Testing

go test ./cmd/... -v
# All tests pass

./gh-report billing -o owner --actions --storage --json reports/report.json
# JSON output verified - no scientific notation

Impact

Before: Field names like TotalPaidMinutesUsed misleadingly stored dollar amounts instead of minutes, making code difficult to reason about.

After: Clear separation with quantity fields (minutes/GB/GB-hours) and cost fields (USD), properly matching the GitHub API structure.

This is a non-breaking change for end users as CSV/table output format remains the same. JSON structure is enhanced with additional cost breakdown fields when using --show-costs.

stoe added 4 commits February 23, 2026 14:08
- Updated UsageItem test fixtures to use GrossQuantity, NetQuantity,

  and DiscountQuantity fields instead of Quantity

- Added cost assertions (GrossAmount, DiscountAmount, NetAmount)

  to test aggregation functions validate both quantities and costs

- Added tolerance-based floating point comparison for NetAmount to

  prevent precision-related test failures

- Enhanced test coverage to verify separate tracking of gross, net,

  and discount values for actions, packages, and storage
- Enhanced BillingUsageResponse with TimePeriod metadata fields

- Renamed UsageItem.Quantity to GrossQuantity for API accuracy

- Added NetQuantity and DiscountQuantity fields to UsageItem

- Added cost fields (GrossAmount, DiscountAmount, NetAmount) to

  ActionsBilling, PackagesBilling, and StorageBilling structs

- Updated StorageBilling with granular cost tracking per product

- Added custom MarshalJSON to prevent scientific notation in JSON

- Fixed aggregation functions to use gross/net/discount quantities

- Updated aggregateStorageUsage to support Git LFS and Shared

  Storage products

- Improved error handling for 403, 404, 422, 500, 502, 503 codes

- Changed endpoint from usage to usage/summary for unified API

- Fixed buildBillingQueryParams to use month/year not month-only

- Updated display logic to show NetAmount instead of field names

  that previously mixed quantities with costs
- Added SetIndent with 2-space indentation for readable JSON output

- Disabled HTML escaping via SetEscapeHTML(false) for cleaner JSON

- Enhanced error handling to wrap and return encoding errors

- Changed return from 'return err' to 'return nil' on success to

  avoid returning uninitialized error variable
- Added Output Fields section explaining each billing report type

- Documented actions fields: minutes used, net cost, discount amount

- Documented packages fields: bandwidth used, net cost, discount

- Documented storage fields: total storage, actions/packages split,

  net cost with clarification on gigabyte-hours unit

- Documented advanced security field: active committers count

- Added Notes section distinguishing quantity vs cost fields

- Noted JSON uses fixed precision to avoid scientific notation

- Clarified storage includes Actions, Packages, and Git LFS data

- Fixed SEE ALSO section formatting from bullet to dash list
@stoe stoe self-assigned this Feb 23, 2026
@stoe stoe marked this pull request as ready for review April 1, 2026 16:16
@stoe stoe enabled auto-merge (squash) April 1, 2026 16:17
@stoe stoe disabled auto-merge April 1, 2026 16:17
@stoe stoe merged commit 1ee7de7 into main Apr 1, 2026
4 checks passed
@stoe stoe deleted the stoe/billing branch April 1, 2026 16:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant