Fix: Resolve syntax error in workflow and improve label checker error handling#4739
Fix: Resolve syntax error in workflow and improve label checker error handling#4739
Conversation
|
|
WalkthroughThis PR enhances error handling in the GitHub Actions label checker script and fixes a syntax error in the resolution label notifier workflow. The label checker now includes preliminary validation, robust try/except wrapping, and more flexible version extraction logic. The resolution notifier fix resolves a missing quote in a conditional string check. Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Tip Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs). Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Pull request overview
This PR fixes a GitHub Actions workflow YAML syntax error that prevented the “resolution label” automation from running, and updates the issue label checker script to be more resilient to missing/variant issue template content.
Changes:
- Fix malformed string quoting in
resolution_label_notifier.ymlso the workflow can execute. - Add error handling and more flexible parsing in
label_checker.pyfor extracting component/version from issue bodies.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
.github/workflows/resolution_label_notifier.yml |
Fixes a broken contains(...) condition by correcting a missing closing quote. |
.github/workflows/label_checker.py |
Adds guarded parsing + fallback behavior for component/version extraction to prevent runtime crashes. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| i = issue_body.index("### Affected Component") | ||
| j = issue_body.index("### Version") | ||
| component = issue_body[i+25:j].strip() |
There was a problem hiding this comment.
component = issue_body[i+25:j].strip() relies on a hard-coded offset that can truncate the first character of the component depending on whether the issue body uses \n\n vs \r\n\r\n after the header. Safer approach is to slice from i + len('### Affected Component') and then trim leading whitespace/newlines (or parse the section by splitting on headers / using a regex).
| i = issue_body.index("### Affected Component") | |
| j = issue_body.index("### Version") | |
| component = issue_body[i+25:j].strip() | |
| affected_header = "### Affected Component" | |
| i = issue_body.index(affected_header) | |
| j = issue_body.index("### Version") | |
| component = issue_body[i + len(affected_header):j].strip() |
| version_start = j + 13 | ||
| version_text = issue_body[version_start:].strip() |
There was a problem hiding this comment.
The version_start = j + 13 offset is still hard-coded to a specific header+newline layout. This can break with different newline conventions or template formatting. Consider deriving the start index from len('### Version') and then skipping any following whitespace/newlines before extracting the value (or reuse the same section-parsing helper as for the component).
| version_start = j + 13 | |
| version_text = issue_body[version_start:].strip() | |
| header = "### Version" | |
| header_len = len(header) | |
| version_start = j + header_len | |
| # Skip any whitespace/newlines immediately after the header | |
| while version_start < len(issue_body) and issue_body[version_start] in (" ", "\t", "\r", "\n"): | |
| version_start += 1 | |
| version_text = issue_body[version_start:] |
| if not issue_body: | ||
| print("Missing/Component") | ||
| sys.exit(0) | ||
|
|
||
| # Get affected component | ||
| if "### Affected Component" not in issue_body or "### Version" not in issue_body: | ||
| print("Missing/Component") | ||
| sys.exit(0) |
There was a problem hiding this comment.
The fallback print('Missing/Component') bypasses the existing-label check and will make gh issue edit --add-label $labels fail if that label doesn’t already exist in the repo. Either verify Missing/Component is in all_existing_labels before printing it, or print an empty string and have the workflow skip --add-label when no valid labels were found.
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
.github/workflows/label_checker.py (1)
56-59: Remove unused exception variable.The exception variable
eis assigned but never used. Replace with_to indicate intentional discard, or log it for debugging purposes.🧹 Proposed fix
-except Exception as e: +except Exception: # If any error occurs, default to Missing/Component label print("Missing/Component") sys.exit(0)Alternatively, if you want to preserve error info for debugging in workflow logs:
-except Exception as e: +except Exception as e: # If any error occurs, default to Missing/Component label + print(f"Error processing issue body: {e}", file=sys.stderr) print("Missing/Component") sys.exit(0)🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/workflows/label_checker.py around lines 56 - 59, The except block currently declares an unused exception variable `e` in `except Exception as e:`; remove or use it: either change the clause to `except Exception:` (or `except Exception as _:`) to indicate the exception is intentionally discarded, or capture and log it (e.g., via `print(e)` or `logging.exception`) before the existing `print("Missing/Component")` and `sys.exit(0)` so the error info is preserved for debugging.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.github/workflows/label_checker.py:
- Around line 27-32: The current logic that slices issue_body using index("###
Affected Component") fails because GitHub form output is plain text; replace
that slicing with a regex search against issue_body (e.g., a multiline regex
that finds the plain "Affected Component" label and captures the user-provided
value on the same line or the following line) to set component and
component_label and append to labels only if it matches all_existing_labels;
also remove the unused variable e and change the broad except Exception handler
to catch specific errors (e.g., ValueError/IndexError from parsing or re-related
exceptions) so parsing failures fall back to adding "Missing/Component" without
hiding other bugs.
---
Nitpick comments:
In @.github/workflows/label_checker.py:
- Around line 56-59: The except block currently declares an unused exception
variable `e` in `except Exception as e:`; remove or use it: either change the
clause to `except Exception:` (or `except Exception as _:`) to indicate the
exception is intentionally discarded, or capture and log it (e.g., via
`print(e)` or `logging.exception`) before the existing
`print("Missing/Component")` and `sys.exit(0)` so the error info is preserved
for debugging.
| i = issue_body.index("### Affected Component") | ||
| j = issue_body.index("### Version") | ||
| component = issue_body[i+25:j].strip() | ||
| component_label = "Component/" + component | ||
| if component_label in all_existing_labels: | ||
| labels.append(component_label) |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# Find the label_checker.py file and examine its content
find . -name "label_checker.py" -type fRepository: wso2/api-manager
Length of output: 96
🏁 Script executed:
# List files in .github directory to understand structure
ls -la .github/ | head -20Repository: wso2/api-manager
Length of output: 359
🏁 Script executed:
# Search for issue template files
find .github -type f \( -name "*.md" -o -name "*.yml" -o -name "*.yaml" \) | grep -i templateRepository: wso2/api-manager
Length of output: 328
🏁 Script executed:
# Read the label_checker.py file to see the implementation
cat -n .github/workflows/label_checker.pyRepository: wso2/api-manager
Length of output: 2416
🏁 Script executed:
# Check one of the issue template files to see the actual format
cat .github/ISSUE_TEMPLATE/bug.ymlRepository: wso2/api-manager
Length of output: 1039
🏁 Script executed:
# Check another issue template to see if format is consistent
cat .github/ISSUE_TEMPLATE/new-feature.ymlRepository: wso2/api-manager
Length of output: 895
🏁 Script executed:
# Search for "Affected Component" in the codebase to see if it's defined anywhere
rg -i "affected component" --type md --type yml --type yamlRepository: wso2/api-manager
Length of output: 87
🏁 Script executed:
# Check if there are any other references to this in the repository
rg -i "affected component" -type pyRepository: wso2/api-manager
Length of output: 87
🏁 Script executed:
# Let's check all issue templates to see which ones might have these fields
for file in .github/ISSUE_TEMPLATE/*.yml; do echo "=== $file ===" && cat "$file"; doneRepository: wso2/api-manager
Length of output: 5198
🏁 Script executed:
# Let's check the git history to see if these templates were recently changed
git log --oneline .github/ISSUE_TEMPLATE/ | head -20Repository: wso2/api-manager
Length of output: 149
🏁 Script executed:
# Check if there are any other references to "Affected Component" in the codebase
rg "Affected Component"Repository: wso2/api-manager
Length of output: 42
🏁 Script executed:
# Let's verify how GitHub renders issue form bodies by checking any documentation or examples
rg "### Affected" -A 3 -B 3Repository: wso2/api-manager
Length of output: 42
🏁 Script executed:
# Check when the label_checker.py was last modified and what the commit message says
git log --oneline .github/workflows/label_checker.py | head -10Repository: wso2/api-manager
Length of output: 149
🏁 Script executed:
# Check the git diff for the recent commit to understand what changed
git show 7eb7524 --statRepository: wso2/api-manager
Length of output: 1201
🏁 Script executed:
# See the full diff of the recent commit
git show 7eb7524Repository: wso2/api-manager
Length of output: 27211
🏁 Script executed:
# Check if there are any workflow files that reference ISSUE_BODY
rg "ISSUE_BODY"Repository: wso2/api-manager
Length of output: 42
🏁 Script executed:
# Let's verify how GitHub renders the issue body from these YAML form templates
# by checking if there's any example or documentation about the format
python3 << 'EOF'
# Simulate what GitHub would render from the question_form.yml template
# When a user fills out a GitHub issue form, the rendered body looks like:
# FieldLabel
# user_input
#
# Not as:
# ### FieldLabel
# user_input
template_example = """Description
Example question
Affected Component
APIM
Version
3.2.0"""
print("Example rendered issue body from GitHub form:")
print(template_example)
print("\nSearching for '### Affected Component' in this body:")
try:
index = template_example.index("### Affected Component")
print(f"Found at index {index}")
except ValueError:
print("NOT FOUND - ValueError would be raised")
print("\nThe code would fail at line 27 with ValueError")
print("This exception is caught by the broad except block")
print("Script always outputs: 'Missing/Component'")
EOFRepository: wso2/api-manager
Length of output: 409
Critical issue: Code expects markdown headers that GitHub issue forms don't produce.
The script searches for "### Affected Component" in the issue body (line 27), but GitHub's YAML form templates don't render field labels as markdown headers. The actual rendered issue body uses plain text format (e.g., Affected Component followed by the user input). This means index() will always raise ValueError, caught by the broad exception handler on line 56, causing the script to always output "Missing/Component" regardless of input.
The script is fundamentally incompatible with the current issue templates and needs to be rewritten to parse the correct plain-text format produced by GitHub forms. Additionally, remove the unused variable e on line 56 and replace the broad except Exception with specific exception handling.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.github/workflows/label_checker.py around lines 27 - 32, The current logic
that slices issue_body using index("### Affected Component") fails because
GitHub form output is plain text; replace that slicing with a regex search
against issue_body (e.g., a multiline regex that finds the plain "Affected
Component" label and captures the user-provided value on the same line or the
following line) to set component and component_label and append to labels only
if it matches all_existing_labels; also remove the unused variable e and change
the broad except Exception handler to catch specific errors (e.g.,
ValueError/IndexError from parsing or re-related exceptions) so parsing failures
fall back to adding "Missing/Component" without hiding other bugs.
Description
Hi! I found some bugs in the GitHub Actions workflows that were causing automation failures, so I went ahead and fixed them.
What I Fixed
1. Missing Quote in resolution_label_notifier.yml (Line 18)
There was a missing closing quote on
'Resolution/Done'that would break the entire workflow. The GitHub Action wouldn't even start running because of this syntax error, which meant issues weren't being validated properly when closed. I added the missing quote to fix it.2. Several Problems in label_checker.py
While reviewing the label checker script, I noticed a few issues:
The version extraction was too rigid - It was hardcoded to grab exactly 5 characters for the version number (
[j+13:j+18]), which breaks for versions like "4.3.0-beta" or anything that isn't exactly 5 characters long. I changed it to dynamically read until it hits a newline or the next section.No safety checks - The script would crash if the
ISSUE_BODYenvironment variable was missing or if someone submitted an issue without the required template headers. I added proper error handling so it fails gracefully instead.Wrong calculation - The component extraction was using an offset of 23 instead of 25 characters, which could cause it to miss the actual component name.
What I did:
Testing
I've verified that the YAML syntax is now valid, the Python script handles edge cases properly, and there are no linting errors in either file.
Summary by CodeRabbit