At the end of the SDLC workflow, tag the owner of the workflow on the PR for review - #336
Conversation
Captures the user who initiated the SDLC workflow (added the egg-sdlc label) and stores it in the contract. When the PR is finalized, this user is added as a reviewer. Changes: - Add workflow_owner field to contract JSON schema and Pydantic model - Capture github.event.sender.login in init job and store in contract - Pass workflow_owner to finalize-pr job via job outputs - Add reviewer using gh pr edit --add-reviewer when PR is ready - Include @owner mention in PR body when reviewer is assigned - Add unit tests for workflow_owner field serialization Issue: #331
There was a problem hiding this comment.
No agent-mode design concerns.
This PR adds workflow infrastructure to track who initiated an SDLC workflow and assign them as a reviewer. It's straightforward workflow plumbing that:
- Captures lightweight metadata (single GitHub username)
- Uses direct API calls (
gh pr edit --add-reviewer) rather than post-processing - Has no impact on agent prompting or behavior
Clean implementation.
— Authored by egg
|
egg agent-mode-design completed. View run logs |
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Review Summary
This PR adds a workflow_owner field to track who initiated the SDLC workflow, then uses that to automatically add them as a PR reviewer when the implementation is finalized. The changes are clean and well-structured.
Verdict: Approve with minor suggestions
Security Analysis
✅ No Injection Vulnerabilities Found
The workflow_owner value comes from github.event.sender.login, which is controlled by GitHub and cannot be user-manipulated in a way that would enable injection. The value is properly quoted when constructing JSON and properly handled when used in GitHub CLI commands.
Issues Found
1. Missing workflow_owner Input Validation (Low Priority)
Location: .github/workflows/sdlc-pipeline.yml:151-155
The workflow owner is captured directly from EVENT_SENDER without validation. While GitHub login names have strict character restrictions (alphanumeric + hyphen only), it would be more defensive to validate this:
# Current
WORKFLOW_OWNER="${EVENT_SENDER:-}"
# Suggested (optional hardening)
WORKFLOW_OWNER="${EVENT_SENDER:-}"
if [[ -n "$WORKFLOW_OWNER" ]] && ! [[ "$WORKFLOW_OWNER" =~ ^[a-zA-Z0-9-]+$ ]]; then
echo "::warning::Invalid workflow owner format, skipping: ${WORKFLOW_OWNER}"
WORKFLOW_OWNER=""
fiThis is low priority since GitHub controls the input, but it's good defense-in-depth.
2. Contract JSON Construction Could Be Cleaner (Style, Non-blocking)
Location: .github/workflows/sdlc-pipeline.yml:147-177
The JSON construction using heredoc with embedded variables works but is fragile. Consider using jq consistently for JSON manipulation:
# Current approach (works but fragile):
if [[ -n "$WORKFLOW_OWNER" ]]; then
WORKFLOW_OWNER_JSON="\"${WORKFLOW_OWNER}\""
else
WORKFLOW_OWNER_JSON="null"
fi
cat > "$CONTRACT_PATH" << EOF
{
...
"workflow_owner": ${WORKFLOW_OWNER_JSON},
...
}
EOF
# Alternative (more robust):
jq -n \
--arg owner "${WORKFLOW_OWNER:-}" \
--arg title "$ISSUE_TITLE" \
--argjson num "$ISSUE_NUMBER" \
'{
schemaVersion: "1.0",
issue: {number: $num, title: $title, url: $url},
workflow_owner: (if $owner == "" then null else $owner end),
...
}' > "$CONTRACT_PATH"The current approach is fine for this simple case; just noting the pattern for future reference.
3. Schema Field Ordering (Non-blocking)
Location: .egg/schemas/contract.schema.json:71-75 and shared/egg_contracts/models.py:209-212
The workflow_owner field is placed between circuit_breaker and audit_log in the schema, but the initial contract JSON created in the workflow places it after circuit_breaker and before audit_log. While not incorrect (JSON object key order doesn't matter for validity), it's good practice to keep consistent ordering for readability.
Correctness Verification
✅ Schema Change Is Valid
- Type
["string", "null"]correctly allows both string and null values - Default
nullis appropriate for optional field - Description is clear and accurate
✅ Pydantic Model Matches Schema
str | Nonetype annotation matches JSON Schema["string", "null"]default=Nonematches schema default- Field is placed logically in the model
✅ Workflow Logic Is Sound
EVENT_SENDERcorrectly capturesgithub.event.sender.login- Job output propagation chain is correct:
init.outputs.workflow_owner→finalize-pr.env.WORKFLOW_OWNER - The
if: env.WORKFLOW_OWNER != ''condition correctly handles empty values - The
gh pr edit --add-reviewercommand correctly handles failures gracefully with a warning
✅ Tests Are Adequate
- Tests cover: field presence in minimal contract, explicit assignment, null assignment, JSON roundtrip
- Tests follow existing patterns in the test file
Edge Cases Considered
| Scenario | Handling | Status |
|---|---|---|
| Workflow triggered by bot | sender.login will be bot name; may fail to add as reviewer but gracefully warns |
✅ |
| Empty sender (shouldn't happen) | Falls back to empty string, skips reviewer addition | ✅ |
| User lacks reviewer permission | gh pr edit --add-reviewer fails gracefully with warning |
✅ |
| Contract already exists | workflow_owner won't be set for existing contracts (only on creation) |
Note on Existing Contracts
When the workflow resumes with an existing contract (line 141-144), the workflow_owner field won't be added if it wasn't present when the contract was created. This is expected behavior for this PR (the field is only set at creation time), but worth noting if you want to backfill for existing issues.
Summary
The implementation is correct, tests are adequate, and the approach is sound. The only suggestion I'd make is the optional input validation for defense-in-depth, but it's not required given GitHub controls the input.
— Authored by egg
|
egg review completed. View run logs |
This comment has been minimized.
This comment has been minimized.
Validates that workflow_owner matches expected GitHub username format (alphanumeric with hyphens only) before using. While GitHub controls this input, this provides additional safety. Authored-by: egg
|
Thanks for the thorough review. Addressed:
Acknowledged but not changed:
— Authored by egg |
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
No agent-mode design concerns with the new commit.
The added input validation for workflow_owner is straightforward defensive coding in workflow infrastructure - it has no impact on agent prompting, context handling, or flexibility.
— Authored by egg
|
egg agent-mode-design completed. View run logs |
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Re-Review Summary
This re-review covers the changes made since commit d7549e44056a6d7a11399b12f0eeff0852aedada, specifically commit dc485ab which adds workflow owner input validation.
Verdict: Approve
Previous Feedback Status
✅ Issue #1: Input Validation (Addressed)
The validation added at lines 121-126 of sdlc-pipeline.yml properly implements defense-in-depth:
if [[ -n "$WORKFLOW_OWNER" ]] && ! [[ "$WORKFLOW_OWNER" =~ ^[a-zA-Z0-9-]+$ ]]; then
echo "::warning::Invalid workflow owner format, skipping: ${WORKFLOW_OWNER}"
WORKFLOW_OWNER=""
fiThe regex ^[a-zA-Z0-9-]+$ correctly matches the GitHub username character set (alphanumeric + hyphens). While slightly more permissive than GitHub's actual rules (which also disallow consecutive hyphens and leading/trailing hyphens), this is appropriate for defense-in-depth since GitHub has already validated the username.
✅ Issues #2 and #3: Acknowledged
The author correctly noted that the JSON construction and schema field ordering suggestions were advisory and not blocking. The current implementation is correct.
New Code Review
Validation Logic Verification
The validation is correctly placed before the value is used anywhere:
- Line 119: Captures
EVENT_SENDERintoWORKFLOW_OWNER - Lines 121-126: Validates and sanitizes
- Line 128: Outputs to
GITHUB_OUTPUT - Lines 159-163: Uses in JSON construction
- Lines 713-714, 735: Uses in finalize-pr job
The control flow ensures the invalid input path clears the variable before any use.
Edge Cases
| Scenario | Handling | Status |
|---|---|---|
| Empty EVENT_SENDER | Falls back to empty string via ${EVENT_SENDER:-} |
✅ |
| Invalid characters | Clears variable with warning | ✅ |
Bot account names (e.g., dependabot[bot]) |
Rejected by regex (contains [ and ]), cleared with warning |
✅ (appropriate - bots shouldn't be reviewers) |
| Valid username | Passes through unchanged | ✅ |
Test Coverage
The tests added are adequate:
test_contract_with_workflow_owner- basic assignmenttest_contract_workflow_owner_null- null handlingtest_json_roundtrip_with_workflow_owner- serialization/deserializationtest_json_roundtrip_with_null_workflow_owner- null serialization
Summary
The feedback from the previous review has been properly addressed. The input validation provides appropriate defense-in-depth without over-engineering. The implementation is correct and ready for merge.
— Authored by egg
|
egg review completed. View run logs |
| egg is addressing review feedback... |
|
Reviewed the feedback on this PR. All actionable items have been addressed:
The re-review approved the implementation with "Verdict: Approve". No additional changes needed. — Authored by egg |
|
egg feedback addressed. View run logs |
|
@james-in-a-box remove the contract file from this pr and we can merge it |
|
Done. Removed The PR now only contains the implementation changes without the contract file. — Authored by egg |
|
egg agent-mode-design completed. View run logs |
There was a problem hiding this comment.
Re-Review Summary
This re-review covers the changes since commit dc485ab (my previous review).
Delta since last review: One commit (3eb4268) that removes .egg-state/contracts/331.json from the PR, as requested by the repo owner.
Verdict: No issues
Previous Feedback Status
All items from the previous review were addressed:
| Issue | Status |
|---|---|
| Input validation (addressed in dc485ab) | ✅ Verified - regex ^[a-zA-Z0-9-]+$ correctly validates GitHub usernames |
| JSON construction (acknowledged) | ✅ Current approach is fine for this simple case |
| Schema field ordering (acknowledged) | ✅ Non-blocking, JSON key order doesn't affect validity |
New Changes Review
The new commit removes the contract file .egg-state/contracts/331.json from the PR. This is appropriate - contract files are runtime state and should not be committed with implementation changes. The implementation code remains unchanged and correct.
Final Verification
I re-examined the full implementation to confirm:
- Workflow owner capture (lines 117-128): Correctly captures
github.event.sender.loginwith defense-in-depth validation - JSON serialization (lines 158-163, 182): Properly handles null vs quoted string for JSON output
- Reviewer assignment (lines 726-739): Gracefully handles permission failures with a warning
- Schema and model (contract.schema.json:71-75, models.py:209-212): Consistent
["string", "null"]/str | Nonetyping with appropriate defaults
The owner has approved the PR. Ready for merge.
— Authored by egg
|
egg review completed. View run logs |
Summary
Approve and advance to implement phase for issue #331
Issue: #331
Branch:
egg/issue-331This PR is managed by the SDLC pipeline. It will be marked ready for review once the implementation passes automated review.
✅ All automated checks passed. Ready for human review.
Authored-by: egg