Skip to content

Commit d03d35a

Browse files
authored
Merge pull request #293 from github/jm_env_vars
feat: extract environment variable handling
2 parents f8d8eef + c6ef210 commit d03d35a

6 files changed

+450
-79
lines changed

Diff for: env.py

+145
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
"""A module for managing environment variables used in GitHub metrics calculation.
2+
3+
This module defines a class for encapsulating environment variables
4+
and a function to retrieve these variables.
5+
6+
Functions:
7+
get_bool_env_var: Gets a boolean environment variable.
8+
"""
9+
10+
import os
11+
from os.path import dirname, join
12+
13+
from dotenv import load_dotenv
14+
15+
16+
class EnvVars:
17+
# pylint: disable=too-many-instance-attributes, too-few-public-methods
18+
"""
19+
Environment variables
20+
21+
Attributes:
22+
gh_app_id (int | None): The GitHub App ID to use for authentication
23+
gh_app_installation_id (int | None): The GitHub App Installation ID to use for
24+
authentication
25+
gh_app_private_key_bytes (bytes): The GitHub App Private Key as bytes to use for
26+
authentication
27+
gh_token (str | None): GitHub personal access token (PAT) for API authentication
28+
ghe (str): The GitHub Enterprise URL to use for authentication
29+
skip_empty_reports (bool): If true, Skips report creation when no stale
30+
repositories are identified
31+
"""
32+
33+
def __init__(
34+
self,
35+
gh_app_id: int | None,
36+
gh_app_installation_id: int | None,
37+
gh_app_private_key_bytes: bytes,
38+
gh_app_enterprise_only: bool,
39+
gh_token: str | None,
40+
ghe: str | None,
41+
skip_empty_reports: bool,
42+
):
43+
self.gh_app_id = gh_app_id
44+
self.gh_app_installation_id = gh_app_installation_id
45+
self.gh_app_private_key_bytes = gh_app_private_key_bytes
46+
self.gh_app_enterprise_only = gh_app_enterprise_only
47+
self.gh_token = gh_token
48+
self.ghe = ghe
49+
self.skip_empty_reports = skip_empty_reports
50+
51+
def __repr__(self):
52+
return (
53+
f"EnvVars("
54+
f"{self.gh_app_id},"
55+
f"{self.gh_app_installation_id},"
56+
f"{self.gh_app_private_key_bytes},"
57+
f"{self.gh_app_enterprise_only},"
58+
f"{self.gh_token},"
59+
f"{self.ghe},"
60+
f"{self.skip_empty_reports},"
61+
)
62+
63+
64+
def get_bool_env_var(env_var_name: str, default: bool = False) -> bool:
65+
"""Get a boolean environment variable.
66+
67+
Args:
68+
env_var_name: The name of the environment variable to retrieve.
69+
default: The default value to return if the environment variable is not set.
70+
71+
Returns:
72+
The value of the environment variable as a boolean.
73+
"""
74+
ev = os.environ.get(env_var_name, "")
75+
if ev == "" and default:
76+
return default
77+
return ev.strip().lower() == "true"
78+
79+
80+
def get_int_env_var(env_var_name: str) -> int | None:
81+
"""Get an integer environment variable.
82+
83+
Args:
84+
env_var_name: The name of the environment variable to retrieve.
85+
86+
Returns:
87+
The value of the environment variable as an integer or None.
88+
"""
89+
env_var = os.environ.get(env_var_name)
90+
if env_var is None or not env_var.strip():
91+
return None
92+
try:
93+
return int(env_var)
94+
except ValueError:
95+
return None
96+
97+
98+
def get_env_vars(
99+
test: bool = False,
100+
) -> EnvVars:
101+
"""
102+
get_env_vars: Gets the environment variables.
103+
104+
Args:
105+
test: True if this is a test run; False otherwise.
106+
107+
Returns:
108+
The environment variables.
109+
"""
110+
111+
if not test:
112+
# Load from .env file if it exists and not testing
113+
dotenv_path = join(dirname(__file__), ".env")
114+
load_dotenv(dotenv_path)
115+
116+
gh_token = os.getenv("GH_TOKEN", "")
117+
gh_app_id = get_int_env_var("GH_APP_ID")
118+
gh_app_installation_id = get_int_env_var("GH_APP_INSTALLATION_ID")
119+
gh_app_private_key_bytes = os.getenv("GH_APP_PRIVATE_KEY", "").encode("utf8")
120+
ghe = os.getenv("GH_ENTERPRISE_URL")
121+
gh_app_enterprise_only = get_bool_env_var("GITHUB_APP_ENTERPRISE_ONLY")
122+
skip_empty_reports = get_bool_env_var("SKIP_EMPTY_REPORTS", True)
123+
124+
if gh_app_id and (not gh_app_private_key_bytes or not gh_app_installation_id):
125+
raise ValueError(
126+
"GH_APP_ID set and GH_APP_INSTALLATION_ID or GH_APP_PRIVATE_KEY variable not set"
127+
)
128+
129+
if (
130+
not gh_app_id
131+
and not gh_app_private_key_bytes
132+
and not gh_app_installation_id
133+
and not gh_token
134+
):
135+
raise ValueError("GH_TOKEN environment variable not set")
136+
137+
return EnvVars(
138+
gh_app_id,
139+
gh_app_installation_id,
140+
gh_app_private_key_bytes,
141+
gh_app_enterprise_only,
142+
gh_token,
143+
ghe,
144+
skip_empty_reports,
145+
)

Diff for: stale_repos.py

+11-35
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,10 @@
55
import json
66
import os
77
from datetime import datetime, timezone
8-
from os.path import dirname, join
98

109
import github3
1110
from dateutil.parser import parse
12-
from dotenv import load_dotenv
11+
from env import get_env_vars
1312

1413
import auth
1514

@@ -31,26 +30,21 @@ def main(): # pragma: no cover
3130
"""
3231
print("Starting stale repo search...")
3332

34-
# Load env variables from file
35-
dotenv_path = join(dirname(__file__), ".env")
36-
load_dotenv(dotenv_path)
37-
38-
token = os.getenv("GH_TOKEN")
39-
gh_app_id = os.getenv("GH_APP_ID")
40-
gh_app_installation_id = os.getenv("GH_APP_INSTALLATION_ID")
41-
gh_app_private_key = os.getenv("GH_APP_PRIVATE_KEY").encode("utf8")
42-
ghe = os.getenv("GH_ENTERPRISE_URL")
43-
gh_app_enterprise_only = os.getenv("GITHUB_APP_ENTERPRISE_ONLY")
44-
skip_empty_reports = (
45-
False if os.getenv("SKIP_EMPTY_REPORTS").lower() == "false" else True
46-
)
33+
env_vars = get_env_vars()
34+
token = env_vars.gh_token
35+
gh_app_id = env_vars.gh_app_id
36+
gh_app_installation_id = env_vars.gh_app_installation_id
37+
gh_app_private_key_bytes = env_vars.gh_app_private_key_bytes
38+
ghe = env_vars.ghe
39+
gh_app_enterprise_only = env_vars.gh_app_enterprise_only
40+
skip_empty_reports = env_vars.skip_empty_reports
4741

4842
# Auth to GitHub.com or GHE
4943
github_connection = auth.auth_to_github(
5044
token,
5145
gh_app_id,
5246
gh_app_installation_id,
53-
gh_app_private_key,
47+
gh_app_private_key_bytes,
5448
ghe,
5549
gh_app_enterprise_only,
5650
)
@@ -221,7 +215,7 @@ def get_active_date(repo):
221215
commit = repo.branch(repo.default_branch).commit
222216
active_date = parse(commit.commit.as_dict()["committer"]["date"])
223217
elif activity_method == "pushed":
224-
last_push_str = repo.pushed_at # type: ignored
218+
last_push_str = repo.pushed_at # type: ignore
225219
if last_push_str is None:
226220
return None
227221
active_date = parse(last_push_str)
@@ -348,24 +342,6 @@ def output_to_json(inactive_repos, file=None):
348342
return inactive_repos_json
349343

350344

351-
def get_int_env_var(env_var_name):
352-
"""Get an integer environment variable.
353-
354-
Args:
355-
env_var_name: The name of the environment variable to retrieve.
356-
357-
Returns:
358-
The value of the environment variable as an integer or None.
359-
"""
360-
env_var = os.environ.get(env_var_name)
361-
if env_var is None or not env_var.strip():
362-
return None
363-
try:
364-
return int(env_var)
365-
except ValueError:
366-
return None
367-
368-
369345
def set_repo_data(
370346
repo, days_inactive, active_date_disp, visibility, additional_metrics
371347
):

0 commit comments

Comments
 (0)