Skip to content

Commit 739e20d

Browse files
committed
refactor: Update discussion labeler and JWT generation to use environment variables for keys
1 parent 159817b commit 739e20d

File tree

4 files changed

+142
-77
lines changed

4 files changed

+142
-77
lines changed

.github/workflows/discussion-labeler.yml

Lines changed: 0 additions & 39 deletions
This file was deleted.

.github/workflows/on-discussion-created.yml

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,14 @@ jobs:
2727
2828
- name: Run discussion labeler
2929
env:
30-
TOKEN: ${{ secrets.GITHUB_TOKEN }}
30+
TOKEN: ${{ secrets.TOKEN }}
3131
APP_ID: ${{ secrets.APP_ID }}
32-
APP_PRIVATE_KEY_PATH: ${{ secrets.APP_PRIVATE_KEY_PATH }}
32+
APP_PRIVATE_KEY: ${{ secrets.APP_PRIVATE_KEY }}
3333
APP_INSTALLATION_ID: ${{ secrets.APP_INSTALLATION_ID }}
34+
AZURE_OPENAI_API_VERSION: ${{ secrets.AZURE_OPENAI_API_VERSION }}
35+
AZURE_OPENAI_ENDPOINT: ${{ secrets.AZURE_OPENAI_ENDPOINT }}
36+
AZURE_OPENAI_KEY: ${{ secrets.AZURE_OPENAI_KEY }}
37+
SECRET_KEY: ${{ secrets.SECRET_KEY }}
3438
DEFAULT_REPO: ${{ github.repository }}
3539
run: |
36-
python test.py ${{ secrets.SECRET_KEY }}
40+
python basic.py

basic.py

Lines changed: 45 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -45,15 +45,24 @@
4545
json_tracer = PromptyTracer()
4646
Tracer.add("PromptyTracer", json_tracer.tracer)
4747

48-
# API settings - get token from environment variables
48+
# Global variables
4949
TOKEN = os.getenv("TOKEN")
5050
DEFAULT_REPO = os.getenv("DEFAULT_REPO", "golclinics/discussions")
5151
REQUEST_TIMEOUT = int(os.getenv("REQUEST_TIMEOUT", "30")) # Default 30 second timeout
5252

5353
# App settings
5454
APP_ID = os.getenv("APP_ID")
55-
APP_PRIVATE_KEY_PATH = os.getenv("APP_PRIVATE_KEY_PATH", "./azure-ai-foundry-discussions.2025-05-06.private-key.pem")
56-
GITHUB_APP_INSTALLATION_ID = os.getenv("GITHUB_APP_INSTALLATION_ID")
55+
APP_PRIVATE_KEY = os.getenv("APP_PRIVATE_KEY") # Direct key content instead of file path
56+
APP_PRIVATE_KEY_PATH = os.getenv("APP_PRIVATE_KEY_PATH") # Keep for backward compatibility
57+
APP_INSTALLATION_ID = os.getenv("APP_INSTALLATION_ID") # Removed GITHUB_ prefix
58+
59+
# Azure OpenAI settings
60+
AZURE_OPENAI_API_VERSION = os.getenv("AZURE_OPENAI_API_VERSION")
61+
AZURE_OPENAI_ENDPOINT = os.getenv("AZURE_OPENAI_ENDPOINT")
62+
AZURE_OPENAI_KEY = os.getenv("AZURE_OPENAI_KEY")
63+
64+
# Other settings
65+
SECRET_KEY = os.getenv("SECRET_KEY")
5766

5867
# GitHub API rate limiting constants
5968
MAX_RETRIES = 3
@@ -69,21 +78,21 @@ class GithubAppAuthError(Exception):
6978

7079
def validate_token() -> None:
7180
"""Validate that the GitHub token is available."""
72-
if not GITHUB_TOKEN:
81+
if not TOKEN:
7382
raise TokenMissingError(
7483
"GitHub token not found in environment variables. "
75-
"Please set the GITHUB_TOKEN environment variable."
84+
"Please set the TOKEN environment variable."
7685
)
7786

7887
def validate_github_app_config() -> None:
7988
"""Validate that the GitHub App configuration is available."""
8089
missing = []
81-
if not GITHUB_APP_ID:
82-
missing.append("GITHUB_APP_ID")
83-
if not GITHUB_APP_PRIVATE_KEY_PATH:
84-
missing.append("GITHUB_APP_PRIVATE_KEY_PATH")
85-
if not GITHUB_APP_INSTALLATION_ID:
86-
missing.append("GITHUB_APP_INSTALLATION_ID")
90+
if not APP_ID:
91+
missing.append("APP_ID")
92+
if not APP_PRIVATE_KEY and not APP_PRIVATE_KEY_PATH:
93+
missing.append("APP_PRIVATE_KEY or APP_PRIVATE_KEY_PATH")
94+
if not APP_INSTALLATION_ID:
95+
missing.append("APP_INSTALLATION_ID")
8796

8897
if missing:
8998
raise GithubAppAuthError(
@@ -111,22 +120,32 @@ def generate_jwt() -> str:
111120
payload = {
112121
'iat': now, # Issued at time
113122
'exp': expiration, # Expiration time
114-
'iss': GITHUB_APP_ID # GitHub App ID
123+
'iss': APP_ID # GitHub App ID
115124
}
116125

117-
# Read private key from file path
118-
try:
119-
key_path = Path(GITHUB_APP_PRIVATE_KEY_PATH)
120-
if (key_path.exists()):
121-
with open(key_path, "r") as key_file:
122-
private_key = key_file.read()
123-
logger.info(f"Successfully loaded private key from file: {GITHUB_APP_PRIVATE_KEY_PATH}")
124-
else:
125-
logger.error(f"Private key file not found at: {GITHUB_APP_PRIVATE_KEY_PATH}")
126-
raise FileNotFoundError(f"Private key file not found: {GITHUB_APP_PRIVATE_KEY_PATH}")
127-
except Exception as e:
128-
logger.error(f"Error reading private key file: {str(e)}")
129-
raise
126+
# Get the private key - either directly from env var or from file
127+
private_key = None
128+
129+
# First try to use the direct key from environment variable
130+
if APP_PRIVATE_KEY:
131+
private_key = APP_PRIVATE_KEY
132+
logger.info("Using private key directly from environment variable")
133+
# Fallback to loading from file path
134+
elif APP_PRIVATE_KEY_PATH:
135+
try:
136+
key_path = Path(APP_PRIVATE_KEY_PATH)
137+
if key_path.exists():
138+
with open(key_path, "r") as key_file:
139+
private_key = key_file.read()
140+
logger.info(f"Successfully loaded private key from file: {APP_PRIVATE_KEY_PATH}")
141+
else:
142+
logger.error(f"Private key file not found at: {APP_PRIVATE_KEY_PATH}")
143+
raise FileNotFoundError(f"Private key file not found: {APP_PRIVATE_KEY_PATH}")
144+
except Exception as e:
145+
logger.error(f"Error reading private key file: {str(e)}")
146+
raise
147+
else:
148+
raise GithubAppAuthError("No private key available. Set APP_PRIVATE_KEY or APP_PRIVATE_KEY_PATH")
130149

131150
# Generate the JWT
132151
token = jwt.encode(
@@ -161,7 +180,7 @@ def get_installation_token() -> str:
161180
jwt_token = generate_jwt()
162181

163182
# API endpoint for getting an installation token
164-
url = f"https://api.github.com/app/installations/{GITHUB_APP_INSTALLATION_ID}/access_tokens"
183+
url = f"https://api.github.com/app/installations/{APP_INSTALLATION_ID}/access_tokens"
165184

166185
headers = {
167186
"Authorization": f"Bearer {jwt_token}",

test.py

Lines changed: 90 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,97 @@
11
import sys
2+
import os
3+
import logging
4+
import time
5+
import jwt
26

3-
APP_PRIVATE_KEY = None
4-
5-
# get private key from args
7+
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
8+
logger = logging.getLogger("test-jwt")
69

10+
# First try to get private key from args
11+
APP_PRIVATE_KEY = None
712
if len(sys.argv) > 1:
813
APP_PRIVATE_KEY = str(sys.argv[1])
914

15+
# If not provided as arg, try to get from environment variable
1016
if APP_PRIVATE_KEY is None:
11-
print("Please provide the path to the private key file as an argument.")
12-
sys.exit(1)
13-
else:
14-
# Print only the first few characters as confirmation, not the entire key
15-
masked_key = APP_PRIVATE_KEY[:5] + "..." if len(APP_PRIVATE_KEY) > 5 else "..."
16-
print(f"Private key loaded successfully (begins with: {masked_key})")
17+
APP_PRIVATE_KEY = os.getenv("APP_PRIVATE_KEY")
18+
19+
# Also check if we have a file path available
20+
APP_PRIVATE_KEY_PATH = os.getenv("APP_PRIVATE_KEY_PATH")
21+
APP_ID = os.getenv("APP_ID")
22+
23+
def test_jwt_generation():
24+
"""Test JWT generation with the private key"""
25+
if not APP_ID:
26+
logger.error("APP_ID environment variable is not set")
27+
return False
28+
29+
if not APP_PRIVATE_KEY and not APP_PRIVATE_KEY_PATH:
30+
logger.error("Neither APP_PRIVATE_KEY nor APP_PRIVATE_KEY_PATH is available")
31+
return False
32+
33+
try:
34+
# Use direct key if available
35+
private_key = APP_PRIVATE_KEY
36+
37+
# Otherwise try to load from file
38+
if not private_key and APP_PRIVATE_KEY_PATH:
39+
try:
40+
with open(APP_PRIVATE_KEY_PATH, "r") as key_file:
41+
private_key = key_file.read()
42+
logger.info(f"Successfully loaded private key from file: {APP_PRIVATE_KEY_PATH}")
43+
except Exception as e:
44+
logger.error(f"Error reading private key file: {str(e)}")
45+
return False
46+
47+
# JWT generation parameters
48+
now = int(time.time())
49+
expiration = now + (10 * 60) # 10 minutes
50+
51+
payload = {
52+
'iat': now,
53+
'exp': expiration,
54+
'iss': APP_ID
55+
}
56+
57+
# Generate the JWT
58+
token = jwt.encode(
59+
payload,
60+
private_key,
61+
algorithm='RS256'
62+
)
63+
64+
# If successful, print confirmation
65+
logger.info("JWT generation successful!")
66+
67+
# For security, only print the first few characters of the token
68+
if isinstance(token, bytes):
69+
token = token.decode('utf-8')
70+
masked_token = token[:10] + "..." if len(token) > 10 else "..."
71+
logger.info(f"Generated JWT token (begins with): {masked_token}")
72+
73+
return True
74+
75+
except Exception as e:
76+
logger.error(f"JWT generation failed: {str(e)}")
77+
return False
78+
79+
if __name__ == "__main__":
80+
if APP_PRIVATE_KEY is None and APP_PRIVATE_KEY_PATH is None:
81+
logger.error("Please provide a private key as an argument or set APP_PRIVATE_KEY/APP_PRIVATE_KEY_PATH environment variable.")
82+
sys.exit(1)
83+
else:
84+
# Mask key for security in logs
85+
if APP_PRIVATE_KEY:
86+
masked_key = APP_PRIVATE_KEY[:5] + "..." if len(APP_PRIVATE_KEY) > 5 else "..."
87+
logger.info(f"Private key available (begins with: {masked_key})")
88+
elif APP_PRIVATE_KEY_PATH:
89+
logger.info(f"Private key path available: {APP_PRIVATE_KEY_PATH}")
90+
91+
# Test JWT generation
92+
if test_jwt_generation():
93+
logger.info("JWT test successful")
94+
sys.exit(0)
95+
else:
96+
logger.error("JWT test failed")
97+
sys.exit(1)

0 commit comments

Comments
 (0)