From d8602b2da625ea67856c56d70aa159c6142bd952 Mon Sep 17 00:00:00 2001 From: Franck Cuny Date: Mon, 6 May 2024 16:33:49 -0700 Subject: move ghabilling to python --- cmd/ghabilling/README.md | 15 -------- cmd/ghabilling/main.go | 92 ------------------------------------------------ pyproject.toml | 1 + src/cli/gha_billing.py | 44 +++++++++++++++++++++++ 4 files changed, 45 insertions(+), 107 deletions(-) delete mode 100644 cmd/ghabilling/README.md delete mode 100644 cmd/ghabilling/main.go create mode 100644 src/cli/gha_billing.py diff --git a/cmd/ghabilling/README.md b/cmd/ghabilling/README.md deleted file mode 100644 index 2aa08ce..0000000 --- a/cmd/ghabilling/README.md +++ /dev/null @@ -1,15 +0,0 @@ -# `gha-billing` - -Print information about how many free minutes of GitHub actions are left for this cycle. - -The API for this is documented [here](https://docs.github.com/en/rest/billing/billing?apiVersion=2022-11-28#get-github-actions-billing-for-an-organization). - -For this you need a [token](https://github.com/settings/personal-access-tokens) with the following permissions: -- [plan](https://docs.github.com/en/rest/authentication/permissions-required-for-fine-grained-personal-access-tokens?apiVersion=2022-11-28#user-permissions-for-plan) - -## usage - -```sh -➜ world git:(main) ✗ go run ./cmd/ghabilling -t github_pat_ -this cycle, 14 minutes have been used, and 1986 minutes are remaining -``` diff --git a/cmd/ghabilling/main.go b/cmd/ghabilling/main.go deleted file mode 100644 index 4865a4a..0000000 --- a/cmd/ghabilling/main.go +++ /dev/null @@ -1,92 +0,0 @@ -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)) -} diff --git a/pyproject.toml b/pyproject.toml index 4400828..e0ff2f4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -65,6 +65,7 @@ combine-as-imports = true known-first-party = ["rbx_nomad"] [project.scripts] +gha_billing = "cli.gha_billing:cli" hashi_env = "cli.hash_env:cli" int2ip = "cli.ipconverter:int2ip" ip2int = "cli.ipconverter:ip2int" diff --git a/src/cli/gha_billing.py b/src/cli/gha_billing.py new file mode 100644 index 0000000..00dd5e3 --- /dev/null +++ b/src/cli/gha_billing.py @@ -0,0 +1,44 @@ +""" +Print information about how many free minutes of GitHub actions are left for this cycle. + +The API for this is documented [here](https://docs.github.com/en/rest/billing/billing?apiVersion=2022-11-28#get-github-actions-billing-for-an-organization). + +For this you need a [token](https://github.com/settings/personal-access-tokens) with the following permissions: +- [plan](https://docs.github.com/en/rest/authentication/permissions-required-for-fine-grained-personal-access-tokens?apiVersion=2022-11-28#user-permissions-for-plan) +""" +import sys + +import click +import requests + +API_URL = "https://api.github.com" + + +@click.command() +@click.option("-t", "--token", required=True, help="GitHub API token") +@click.option("-u", "--user", default="fcuny", help="GitHub username") +def cli(token, user): + # https://docs.github.com/en/rest/billing/billing?apiVersion=2022-11-28#get-github-actions-billing-for-an-organization + url = f"{API_URL}/users/{user}/settings/billing/actions" + headers = {"Authorization": f"token {token}", "Accept": "application/vnd.github.v3+json"} + try: + response = requests.get(url, headers=headers, timeout=30) + response.raise_for_status() + except requests.exceptions.RequestException as err: + click.echo(f"Error making HTTP request: {err}", err=True) + sys.exit(1) + + try: + billing_info = response.json() + except ValueError as err: + click.echo(f"Error parsing the JSON response: {err}", err=True) + sys.exit(1) + + time_remaining = billing_info["included_minutes"] - billing_info["total_minutes_used"] + click.echo( + f"This cycle, {int(billing_info['total_minutes_used'])} minutes have been used, and {int(time_remaining)} minutes are remaining" + ) + + +if __name__ == "__main__": + cli() -- cgit 1.4.1