From 93687ab5c1f905f04b5e96239e6e34ee42916d31 Mon Sep 17 00:00:00 2001 From: Ebony Louis Date: Fri, 29 Aug 2025 10:55:05 -0400 Subject: [PATCH] fixing api error --- .github/scripts/send_key.py | 102 +++++------------- .github/workflows/send-api-key.yml | 4 +- .../recipes/data/recipes/test-recipe.yaml | 59 ---------- 3 files changed, 31 insertions(+), 134 deletions(-) delete mode 100644 documentation/src/pages/recipes/data/recipes/test-recipe.yaml diff --git a/.github/scripts/send_key.py b/.github/scripts/send_key.py index 39fba93704ad..87cff2d8a772 100644 --- a/.github/scripts/send_key.py +++ b/.github/scripts/send_key.py @@ -20,29 +20,19 @@ def fetch_pr_body(pr_url, github_token): return pr_resp.json() def extract_email_from_text(text): - """Extract email from text using various patterns""" - # Try PR template format: "**Email**: email@example.com" email_match = re.search(r"\*\*Email\*\*:\s*([A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,})", text) if email_match: return email_match.group(1) - - # Try other common email patterns email_match = re.search(r"[Ee]mail:\s*([A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,})", text) if email_match: return email_match.group(1) - - # Try general email pattern email_match = re.search(r"\b([A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,})\b", text) if email_match: return email_match.group(1) - return None def fetch_pr_comments(pr_url, github_token): - """Fetch all comments on the PR""" - # Convert PR URL to comments URL comments_url = pr_url.replace("/pulls/", "/issues/") + "/comments" - try: comments_resp = requests.get( comments_url, @@ -55,9 +45,7 @@ def fetch_pr_comments(pr_url, github_token): return [] def validate_email_address(email): - """Validate email address format and deliverability""" try: - # Validate and get normalized email valid_email = email_validator.validate_email(email) normalized_email = valid_email.email print(f"✅ Email validation passed: {normalized_email}") @@ -67,10 +55,7 @@ def validate_email_address(email): return None def extract_email(pr_body, pr_url, github_token): - """Extract and validate email from PR body and comments""" print("🔍 Searching for email in PR body...") - - # First check PR body email = extract_email_from_text(pr_body) if email: print(f"📧 Found email in PR body: {email}") @@ -79,10 +64,8 @@ def extract_email(pr_body, pr_url, github_token): return validated_email else: print("⚠️ Email in PR body is invalid, checking comments...") - + print("🔍 No valid email found in PR body, checking comments...") - - # Check PR comments comments = fetch_pr_comments(pr_url, github_token) for comment in comments: comment_body = comment.get("body", "") @@ -94,10 +77,9 @@ def extract_email(pr_body, pr_url, github_token): return validated_email else: print("⚠️ Email in comment is invalid, continuing search...") - - # No valid email found anywhere + print("❌ No valid email found in PR body or comments. Skipping key issuance.") - exit(0) + exit(2) def provision_api_key(provisioning_api_key): print("🔐 Creating OpenRouter key...") @@ -118,11 +100,14 @@ def provision_api_key(provisioning_api_key): except requests.exceptions.RequestException as e: print("❌ Failed to provision API key:", str(e)) raise - return key_resp.json()["key"] + key = key_resp.json().get("key") + if not key: + print("❌ API response did not include a key.") + exit(2) + return key def send_email(email, api_key, sendgrid_api_key): print("📤 Sending email via SendGrid...") - try: sg = SendGridAPIClient(sendgrid_api_key) from_email = "Goose Team " @@ -139,43 +124,17 @@ def send_email(email, api_key, sendgrid_api_key): subject=subject, html_content=html_content ) - response = sg.send(message) print(f"✅ Email sent successfully! Status code: {response.status_code}") - - # Check for potential issues even on "success" if response.status_code >= 300: print(f"⚠️ Warning: Unexpected status code {response.status_code}") print(f"Response body: {response.body}") return False - return True - + except HTTPError as e: - # Specific SendGrid HTTP errors - status_code = e.status_code - error_body = e.body - - if status_code == 401: - print("❌ SendGrid authentication failed - invalid API key") - elif status_code == 403: - print("❌ SendGrid authorization failed - API key lacks permissions") - elif status_code == 429: - print("❌ SendGrid rate limit exceeded - too many requests") - elif status_code == 400: - print(f"❌ SendGrid bad request - invalid email data: {error_body}") - elif status_code >= 500: - print(f"❌ SendGrid server error ({status_code}) - try again later") - else: - print(f"❌ SendGrid HTTP error {status_code}: {error_body}") - - print(f"Full error details: {e}") - return False - - except ValueError as e: - print(f"❌ Invalid email format or API key: {e}") + print(f"❌ SendGrid HTTP error {e.status_code}: {e.body}") return False - except Exception as e: print(f"❌ Unexpected error sending email: {type(e).__name__}: {e}") return False @@ -201,7 +160,13 @@ def comment_on_pr(github_token, repo_full_name, pr_number, email): raise def main(): - # Load environment variables + # ✅ Environment variable validation + required_envs = ["GITHUB_TOKEN", "GITHUB_API_URL", "PROVISIONING_API_KEY", "EMAIL_API_KEY"] + missing = [env for env in required_envs if env not in os.environ] + if missing: + print(f"❌ Missing environment variables: {', '.join(missing)}") + exit(2) + GITHUB_TOKEN = os.environ["GITHUB_TOKEN"] PR_URL = os.environ["GITHUB_API_URL"] PROVISIONING_API_KEY = os.environ["PROVISIONING_API_KEY"] @@ -209,35 +174,19 @@ def main(): pr_data = fetch_pr_body(PR_URL, GITHUB_TOKEN) pr_body = pr_data.get("body", "") - - # Handle cases where pr_data might be missing expected fields pr_number = pr_data.get("number") + if not pr_number: print("❌ Unable to get PR number from GitHub API response") - print(f"Available keys in response: {list(pr_data.keys())}") - # Try to extract number from URL if available - if "html_url" in pr_data: - import re - match = re.search(r'/pull/(\d+)', pr_data["html_url"]) - if match: - pr_number = int(match.group(1)) - print(f"✅ Extracted PR number from URL: {pr_number}") - else: - print("❌ Could not extract PR number from URL either") - exit(1) - else: - print("❌ No html_url available to extract PR number") - exit(1) - - # Get repo info + exit(2) + if "base" in pr_data and "repo" in pr_data["base"]: repo_full_name = pr_data["base"]["repo"]["full_name"] elif "repository" in pr_data: repo_full_name = pr_data["repository"]["full_name"] else: print("❌ Unable to get repository name from GitHub API response") - print(f"Available keys in response: {list(pr_data.keys())}") - exit(1) + exit(2) email = extract_email(pr_body, PR_URL, GITHUB_TOKEN) print(f"📬 Found email: {email}") @@ -246,10 +195,15 @@ def main(): api_key = provision_api_key(PROVISIONING_API_KEY) print("✅ API key generated!") - if send_email(email, api_key, SENDGRID_API_KEY): - comment_on_pr(GITHUB_TOKEN, repo_full_name, pr_number, email) + if not send_email(email, api_key, SENDGRID_API_KEY): + print("❌ Email failed to send. Exiting without PR comment.") + exit(2) + + comment_on_pr(GITHUB_TOKEN, repo_full_name, pr_number, email) + except Exception as err: print(f"❌ An error occurred: {err}") + exit(2) if __name__ == "__main__": main() diff --git a/.github/workflows/send-api-key.yml b/.github/workflows/send-api-key.yml index 2df8c460d38f..bb3fa86379e8 100644 --- a/.github/workflows/send-api-key.yml +++ b/.github/workflows/send-api-key.yml @@ -24,9 +24,11 @@ jobs: - name: Install dependencies and run email script env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - GITHUB_API_URL: ${{ github.event.pull_request.url }} + PR_NUMBER: ${{ github.event.pull_request.number }} + REPO_NAME: ${{ github.repository }} PROVISIONING_API_KEY: ${{ secrets.PROVISIONING_API_KEY }} EMAIL_API_KEY: ${{ secrets.SENDGRID_API_KEY }} run: | pip install requests sendgrid email-validator python .github/scripts/send_key.py + diff --git a/documentation/src/pages/recipes/data/recipes/test-recipe.yaml b/documentation/src/pages/recipes/data/recipes/test-recipe.yaml deleted file mode 100644 index b2aa876a1569..000000000000 --- a/documentation/src/pages/recipes/data/recipes/test-recipe.yaml +++ /dev/null @@ -1,59 +0,0 @@ -version: 1.0.0 -title: Test Recipe -author: - contact: EbonyLouis -description: Analyzes code files for syntax and layout issues using available linting tools -instructions: You are a code quality expert that helps identify syntax and layout issues in code files -activities: - - Detect file type and programming language - - Check for available linting tools in the project - - Run appropriate linters for syntax and layout checking - - Provide recommendations if no linters are found -parameters: - - key: file_path - input_type: string - requirement: required - description: Path to the file you want to lint -extensions: - - type: builtin - name: developer - display_name: Developer - timeout: 300 - bundled: true -prompt: | - I need you to lint the file at {{ file_path }} for syntax and layout issues only. Do not modify the file - just report any problems you find. - Here's what to do step by step: - 1. **Verify the file exists and determine its type:** - - Check if {{ file_path }} exists - - Examine the file extension and content to determine the programming language/file type - - Focus on: Python (.py), JavaScript (.js, .jsx, .ts, .tsx), YAML (.yaml, .yml), HTML (.html, .htm), and CSS (.css) - 2. **Check for available linting tools in the project:** - - Look for common linting tools and configurations in the current project: - - Python: flake8, pylint, black, ruff, pycodestyle, autopep8 - - JavaScript/TypeScript: eslint, prettier, jshint, tslint - - YAML: yamllint, yq - - HTML: htmlhint, tidy - - CSS: stylelint, csslint - - Check for configuration files like .eslintrc, .flake8, pyproject.toml, .yamllint, etc. - - Look in package.json, requirements.txt, or other dependency files - 3. **Run appropriate linting tools:** - - If linting tools are found, run them only on the specified file - - Use syntax-only or layout-only flags where available (e.g., `flake8 --select=E,W` for Python) - - Capture and report the output clearly - 4. **If no linters are found, provide recommendations:** - - For Python files: Suggest flake8, black, or ruff - - For JavaScript/TypeScript: Suggest ESLint and Prettier - - For YAML: Suggest yamllint - - For HTML: Suggest htmlhint or W3C validator - - For CSS: Suggest stylelint - - Provide installation commands and basic usage examples - 5. **Report results:** - - Clearly summarize any syntax or layout issues found - - If no issues are found, confirm the file appears to be clean - - If linting tools weren't available, explain what you checked manually and provide tool recommendations - Remember: - - Only check for syntax and layout issues, don't suggest code changes - - Do not change the file on behalf of the user - - Use tools that are already available in the project when possible - - Be helpful by suggesting appropriate tools if none are found - - Focus on the file types specified: Python, JavaScript, YAML, HTML, and CSS \ No newline at end of file