about summary refs log tree commit diff
path: root/cmd/ghabilling/main.go
blob: 4865a4a7582f59f93419a2192a093d3079f3bf62 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
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))
}