package main import ( "context" "encoding/json" "flag" "fmt" "net/http" "os" "time" "github.com/fcuny/world/internal/version" ) const API_URL = "https://api.github.com" const usage = `Usage: gha-billing -t [TOKEN] Options: -t, --token GitHub API's token -v, --version Print version information -h, --help Print this message ` // https://docs.github.com/en/rest/billing/billing?apiVersion=2022-11-28#get-github-actions-billing-for-an-organization type githubActionBilling struct { TotalMinutesUsed float64 `json:"total_minutes_used"` TotalPaidMinutesUsed float64 `json:"total_paid_minutes_used"` IncludedMinutes float64 `json:"included_minutes"` MinutesUsedBreakdown map[string]int `json:"minutes_used_breakdown"` } func main() { flag.Usage = func() { fmt.Fprintf(os.Stderr, "%s\n", usage) } var ( tokenFlag string userFlag string versionFlag bool ) flag.StringVar(&tokenFlag, "token", "", "GitHub API token") flag.StringVar(&tokenFlag, "t", "", "GitHub API token") flag.StringVar(&userFlag, "user", "fcuny", "GitHub API token") flag.StringVar(&userFlag, "u", "fcuny", "GitHub API token") flag.BoolVar(&versionFlag, "version", false, "Print version information") flag.BoolVar(&versionFlag, "v", false, "Print version information") flag.Parse() if versionFlag { information := version.VersionAndBuildInfo() fmt.Println(information) return } if tokenFlag == "" { fmt.Fprintf(os.Stderr, "The API token is not set\n") os.Exit(1) } ctx := context.TODO() url := fmt.Sprintf("%s/users/%s/settings/billing/actions", API_URL, userFlag) req, err := http.NewRequestWithContext(ctx, "GET", url, nil) if err != nil { fmt.Fprintf(os.Stderr, "could not create a request: %v\n", err) os.Exit(1) } req.Header.Set("Authorization", fmt.Sprintf("token %s", tokenFlag)) req.Header.Set("Accept", "application/vnd.github.v3+json") client := http.Client{ Timeout: 30 * time.Second, } res, err := client.Do(req) if err != nil { fmt.Fprintf(os.Stderr, "error making http request: %s\n", err) os.Exit(1) } var b githubActionBilling if err := json.NewDecoder(res.Body).Decode(&b); err != nil { fmt.Fprintf(os.Stderr, "error parsing the JSON response: %v\n", err) os.Exit(1) } timeRemaining := b.IncludedMinutes - b.TotalMinutesUsed fmt.Printf("this cycle, %d minutes have been used, and %d minutes are remaining\n", int(b.TotalMinutesUsed), int(timeRemaining)) }