diff options
-rw-r--r-- | tools/default.nix | 1 | ||||
-rw-r--r-- | tools/gha-billing/default.nix | 35 | ||||
-rwxr-xr-x | tools/gha-billing/gha-billing.py | 40 |
3 files changed, 76 insertions, 0 deletions
diff --git a/tools/default.nix b/tools/default.nix index 7003b8a..93bc84e 100644 --- a/tools/default.nix +++ b/tools/default.nix @@ -5,6 +5,7 @@ pkgs.lib.makeScope pkgs.newScope (pkgs: { gerrit-hook = pkgs.callPackage ./gerrit-hook { }; ipconverter = pkgs.callPackage ./ipconverter { }; seqstat = pkgs.callPackage ./seqstat { }; + gha-billing = pkgs.callPackage ./gha-billing { }; git-blame-stats = pkgs.callPackage ./git-blame-stats { }; git-broom = pkgs.callPackage ./git-broom { }; sendsms = pkgs.callPackage ./sendsms { }; diff --git a/tools/gha-billing/default.nix b/tools/gha-billing/default.nix new file mode 100644 index 0000000..51f69f8 --- /dev/null +++ b/tools/gha-billing/default.nix @@ -0,0 +1,35 @@ +{ self, lib, stdenvNoCC, pkgs }: + +stdenvNoCC.mkDerivation rec { + pname = "gha-billing"; + src = ./gha-billing.py; + version = "0.1.0"; + + buildInputs = [ + (pkgs.python310.withPackages (ps: with ps; [ + requests + ])) + ]; + + propagatedBuildInputs = [ + (pkgs.python310.withPackages (ps: with ps; [ + requests + ])) + ]; + + dontUnpack = true; + dontBuild = true; + + installPhase = '' + mkdir -p $out/bin + cp $src $out/bin/${pname} + ''; + + + meta = with pkgs.lib; { + description = "CLI to get billing information for GHA."; + license = licenses.mit; + platforms = platforms.unix; + maintainers = [ ]; + }; +} diff --git a/tools/gha-billing/gha-billing.py b/tools/gha-billing/gha-billing.py new file mode 100755 index 0000000..c9c09ba --- /dev/null +++ b/tools/gha-billing/gha-billing.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python3 + +import argparse +import os +import sys + +import requests + +API_URL = "https://api.github.com" + + +def main(api_token: str, user: str) -> None: + s = requests.Session() + s.headers.update({"Authorization": f"token {api_token}"}) + s.headers.update({"Accept": "application/vnd.github.v3+json"}) + + res = s.get(f"{API_URL}/users/{user}/settings/billing/actions", timeout=5) + res.raise_for_status() + + billing = res.json() + + time_remaining = billing["included_minutes"] - billing["total_minutes_used"] + print( + f"this cycle, {billing['total_minutes_used']} minutes have been used, and {time_remaining} minutes are remaining" + ) + + +if __name__ == "__main__": + argp = argparse.ArgumentParser() + argp.add_argument("-t", "--token-file", nargs=1, type=argparse.FileType("r")) + argp.add_argument("-u", "--user", type=str, default="fcuny") + args = argp.parse_args() + + if args.token_file: + api_token = args.token_file[0].readline().strip() + else: + print("Must pass token file with -t/--token_file", file=sys.stderr) + sys.exit(os.EX_USAGE) + + main(api_token, args.user) |