Skip to content

Q.a - #24

Merged
v-Kaefer merged 19 commits into
mainfrom
Q.A
Aug 10, 2026
Merged

Q.a#24
v-Kaefer merged 19 commits into
mainfrom
Q.A

Conversation

@v-Kaefer

@v-Kaefer v-Kaefer commented Aug 10, 2026

Copy link
Copy Markdown
Owner

Linked Issue

  • Closes #

Milestone

Summary

How to test

  • Test type: automated | smoke | manual
  • Steps:

Evidence

  • Screenshot/GIF attached when applicable
  • Log/output attached when applicable
  • Manual checklist executed when applicable

Known risks

DoD checklist

  • Scope implemented as defined
  • Tests executed and documented
  • Evidence attached when applicable
  • No known critical breakage introduced

Summary by CodeRabbit

  • New Features

    • Added automatic PR synchronization with linked tasks, including labels, milestones, assignees, parent/sub-issue relationships, and optional project status updates.
    • Added configurable synchronization settings, dry-run support, status reporting, and safeguards for forks and promotion PRs.
    • Included the synchronization workflow in new project installations.
  • Documentation

    • Added setup, configuration, security, branching, limitations, and troubleshooting guidance in English and Portuguese.
  • Tests

    • Added coverage for synchronization behavior, workflow safeguards, configuration, and installation validation.

@v-Kaefer v-Kaefer self-assigned this Aug 10, 2026
@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This change adds PR Sync automation. It synchronizes implementation pull requests with linked tasks, metadata, parent relationships, and optional Project v2 status. It adds workflow installation, configuration, tests, security policies, and English and Portuguese documentation.

Changes

PR Sync

Layer / File(s) Summary
Synchronization engine and configuration
project_setup.json, project_setup/pr_sync.py
Adds PR Sync configuration and the synchronization engine for event parsing, task resolution, metadata, parent relationships, Project v2 status, comments, dry runs, and CLI execution.
Workflow distribution and validation
.github/workflows/pr-sync.yml, project_setup/installer.py, scripts/validation/repo_quality.py, tests/test_pr_sync.py
Adds the guarded workflow, distributes it through the installer, registers required repository files, and tests synchronization and workflow contracts.
Documentation and repository policy
README*, docs/DOCUMENTATION-GUIDE.md, docs/repo/*
Documents setup, configuration, security boundaries, source markers, promotion exclusions, automation responsibilities, and PR Sync behavior in English and Portuguese.

Estimated code review effort: 4 (Complex) | ~45 minutes

Possibly related issues

Possibly related PRs

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description contains every required section, but all fields remain placeholders and provide no issue, summary, test steps, evidence, risks, or checklist status. Replace all placeholders with the linked issue, milestone, change summary, test commands and results, applicable evidence, known risks, and completed DoD checklist items.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title identifies the Q.A promotion branch, so it relates to the pull request, but it does not summarize the PR Sync changes.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 2
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch Q.A

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@v-Kaefer
v-Kaefer merged commit e4232a6 into main Aug 10, 2026
17 of 20 checks passed

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (1)
project_setup/installer.py (1)

21-21: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Assert the installer output, not only the source text.

The downstream contract test currently checks that the path string exists in project_setup/installer.py. It can pass even when template_files() does not return the workflow, or when automatic package discovery omits project_setup/pr_sync.py. Assert both paths in the returned (source, target) manifest so this registration is tested end to end.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@project_setup/installer.py` at line 21, Update the contract test around
template_files() to assert that both the workflow source path and
project_setup/pr_sync.py source path appear in the returned (source, target)
manifest, rather than checking only installer.py text; preserve the expected
target paths while validating the complete registration end to end.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@project_setup/pr_sync.py`:
- Around line 575-585: Add an --owner-type argument to the project-sync CLI
parser, then propagate its value from the entrypoint through
apply_pr_sync_from_path and sync_project_status to find_project. Ensure the flow
also preserves the existing resolve_owner_type behavior, including
PROJECT_SETUP_OWNER_TYPE when no command-line value is provided.
- Around line 144-145: Update the workflow_run handling around
context_from_pull_request to derive the action from the live_pr state instead of
always passing "synchronize", preserving terminal project statuses for closed
merged and unmerged pull requests. Add coverage for delayed validation runs
covering both closed-merged and closed-unmerged PRs.
- Around line 365-371: Update the exception handling around add_sub_issue and
sync_parent_relationship so “may only have one parent” is not treated as success
automatically. Query the task’s current sub-issue parent, compare it with
parent_number, and only return the existing-link message when they match;
otherwise propagate the failure or perform the required parent replacement.

---

Nitpick comments:
In `@project_setup/installer.py`:
- Line 21: Update the contract test around template_files() to assert that both
the workflow source path and project_setup/pr_sync.py source path appear in the
returned (source, target) manifest, rather than checking only installer.py text;
preserve the expected target paths while validating the complete registration
end to end.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 4df118cd-9f62-45a5-9eaa-73d22652072a

📥 Commits

Reviewing files that changed from the base of the PR and between ee7ea25 and fdb616d.

📒 Files selected for processing (14)
  • .github/workflows/pr-sync.yml
  • README.md
  • README.pt-BR.md
  • docs/DOCUMENTATION-GUIDE.md
  • docs/repo/branching-policy.md
  • docs/repo/branching-policy.pt-BR.md
  • docs/repo/pr-sync.md
  • docs/repo/pr-sync.pt-BR.md
  • docs/repo/project-setup-shared-tool.md
  • project_setup.json
  • project_setup/installer.py
  • project_setup/pr_sync.py
  • scripts/validation/repo_quality.py
  • tests/test_pr_sync.py

Comment thread project_setup/pr_sync.py
Comment on lines +144 to +145
live_pr = client.request_json("GET", f"{API_BASE}/repos/{repo}/pulls/{number}")
return context_from_pull_request(live_pr, "synchronize")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate and inspect the relevant file and nearby code.
wc -l project_setup/pr_sync.py
ast-grep outline project_setup/pr_sync.py --view expanded | sed -n '1,220p'
echo '--- relevant lines 120-170 ---'
sed -n '120,170p' project_setup/pr_sync.py | nl -ba -v120
echo '--- related functions/usages ---'
rg -n "workflow_run|context_from_pull_request|context_from_event|project_status_for_context|resolve_owner_type|PROJECT_SETUP_OWNER_TYPE|state|state_reason|closed" project_setup/pr_sync.py

Repository: v-Kaefer/Github-Project-Automation

Length of output: 2431


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- project_setup/pr_sync.py lines 100-185 ---'
sed -n '100,185p' project_setup/pr_sync.py
echo '--- project_setup/pr_sync.py lines 370-450 ---'
sed -n '370,450p' project_setup/pr_sync.py
echo '--- test files mentioning workflow_run / pr_sync ---'
git ls-files | rg '(^tests?/|test_)|project_setup' | sed -n '1,200p'
rg -n "workflow_run|push_to_project|project-status|Done|In progress|project_status_for_context|context_from_pull_request" .

Repository: v-Kaefer/Github-Project-Automation

Length of output: 12150


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- tests/test_pr_sync.py relevant lines 50-90 and 240-320 ---'
sed -n '50,90p' tests/test_pr_sync.py
sed -n '240,320p' tests/test_pr_sync.py

echo '--- focused read-only verifier for event/status semantics ---'
python3 - <<'PY'
from dataclasses import dataclass
from typing import Any

`@dataclass`
class PullRequestContext:
    number: int
    action: str
    body: str
    base_ref: str
    head_ref: str
    head_repo: str
    author: str
    draft: bool
    merged: bool

def context_from_pull_request(pr: dict[str, Any], action: str = "") -> PullRequestContext:
    head = pr.get("head") or {}
    base = pr.get("base") or {}
    head_repo = (head.get("repo") or {}).get("full_name") or ""
    return PullRequestContext(
        number=int(pr["number"]),
        action=action,
        body=pr.get("body") or "",
        base_ref=base.get("ref") or "",
        head_ref=head.get("ref") or "",
        head_repo=head_repo,
        author=(pr.get("user") or {}).get("login") or "",
        draft=bool(pr.get("draft")),
        merged=bool(pr.get("merged")),
    )

def project_status_for_context(ctx: PullRequestContext, config: dict[str, Any]) -> str:
    mapping = config["projectStatus"]
    if ctx.action == "closed":
        return str(mapping["merged"] if ctx.merged else mapping["closed"])
    if ctx.action == "converted_to_draft" or ctx.draft:
        return str(mapping["draft"])
    return str(mapping["review"])

DEFAULT_SYNC_CONFIG = {
    "projectStatus": {
        "review": "Ready",
        "draft": "In progress",
        "closed": "In progress",
        "merged": "Done",
    },
}

for state, merged in [("open", False), ("closed", False), ("closed", True), ("draft", False)]:
    pr = {"state": state, "merged": merged, "number": 123}
    ctx = context_from_pull_request(pr, "synchronize")
    print({"state": state, "merged": merged, "action": ctx.action, "project_status": project_status_for_context(ctx, DEFAULT_SYNC_CONFIG)})
PY

Repository: v-Kaefer/Github-Project-Automation

Length of output: 4638


Preserve the terminal Project status for late workflow_run events.

workflow_run currently passes "synchronize" to context_from_pull_request, so project_status_for_context still applies the review mapping for closed PRs. Use the live pull request state for the action, and add coverage for closed merged/unmerged PRs after a delayed validation run.

Proposed fix
         number = int(related_prs[0]["number"])
         live_pr = client.request_json("GET", f"{API_BASE}/repos/{repo}/pulls/{number}")
-        return context_from_pull_request(live_pr, "synchronize")
+        action = "closed" if live_pr.get("state") == "closed" else "synchronize"
+        return context_from_pull_request(live_pr, action)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
live_pr = client.request_json("GET", f"{API_BASE}/repos/{repo}/pulls/{number}")
return context_from_pull_request(live_pr, "synchronize")
live_pr = client.request_json("GET", f"{API_BASE}/repos/{repo}/pulls/{number}")
action = "closed" if live_pr.get("state") == "closed" else "synchronize"
return context_from_pull_request(live_pr, action)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@project_setup/pr_sync.py` around lines 144 - 145, Update the workflow_run
handling around context_from_pull_request to derive the action from the live_pr
state instead of always passing "synchronize", preserving terminal project
statuses for closed merged and unmerged pull requests. Add coverage for delayed
validation runs covering both closed-merged and closed-unmerged PRs.

Comment thread project_setup/pr_sync.py
Comment on lines +365 to +371
except Exception as exc:
text = str(exc).casefold()
if any(
marker in text
for marker in ("already", "exists", "duplicate sub-issues", "may only have one parent")
):
return f"already linked under a parent (requested #{parent_number})."

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

GitHub GraphQL addSubIssue behavior and error response when a sub-issue already has a different parent issue.

💡 Result:

When using the GitHub GraphQL addSubIssue mutation, attempting to add a sub-issue that already has a different parent will result in a 422 Unprocessable Entity error with a message similar to "Sub issue may only have one parent" [1][2]. To handle this scenario, the AddSubIssueInput object provides a replaceParent boolean field [3][4]. Setting replaceParent: true in your mutation input allows the operation to silently move the sub-issue from its existing parent to the new target parent [2][5]. If this field is omitted or set to false, the mutation will fail if the sub-issue is already associated with another parent [2]. Example mutation structure: mutation { addSubIssue(input: { issueId: "PARENT_NODE_ID" subIssueId: "CHILD_NODE_ID" replaceParent: true }) { issue { id } subIssue { id } } } [5]

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== locate file =="
git ls-files | rg '(^|/)project_setup/pr_sync\.py$|(^|/)pr_sync\.py$' || true

echo "== relevant section =="
sed -n '320,390p' project_setup/pr_sync.py

echo "== mutation/addSubIssue references =="
rg -n "addSubIssue|Sub issue may only have one parent|may only have one parent|duplicate sub-issues|already linked|replaceParent|parent" project_setup/pr_sync.py

Repository: v-Kaefer/Github-Project-Automation

Length of output: 4232


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== outline around add_sub_issue =="
ast-grep outline project_setup/pr_sync.py --match add_sub_issue --view expanded || true

echo "== add_sub_issue and nearby helper implementation =="
rg -n -A 80 -B 20 "def add_sub_issue|--add-sub-issue|subIssues|parentIds|parents|projectId" project_setup/pr_sync.py

echo "== mutation usage =="
rg -n "mutation |query |addSubIssue|subIssue|SubIssue|GitHubClient|run_github|gh " project_setup/pr_sync.py | sed -n '1,220p'

Repository: v-Kaefer/Github-Project-Automation

Length of output: 299


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== all lines containing add_sub_issue =="
rg -n "add_sub_issue|subissue|sub-issue|subIssue|parentIds|projectId|run_github|gh " project_setup/pr_sync.py || true

echo "== full function references context =="
rg -n -C 6 "add_sub_issue|parent_issue_number|sync_parent_relationship" project_setup/pr_sync.py || true

echo "== line count =="
wc -l project_setup/pr_sync.py

echo "== file top =="
sed -n '1,120p' project_setup/pr_sync.py

Repository: v-Kaefer/Github-Project-Automation

Length of output: 7294


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== locate issues.py =="
git ls-files | rg '(^|/)issues\.py$' || true

echo "== issues.py outline =="
ast-grep outline project_setup/issues.py --view expanded || true

echo "== add_sub_issue implementation and sub-issue related code =="
rg -n -A 60 -B 20 "def add_sub_issue|add_sub_issue|subIssues|subIssue|parentIds|parents|addSubIssue|migrateSubIssues" project_setup/issues.py || true

Repository: v-Kaefer/Github-Project-Automation

Length of output: 5138


Do not classify a different parent as an existing sub-issue relationship.

add_sub_issue calls GitHub addSubIssue without replaceParent, so may only have one parent can mean the task already belongs to another issue. sync_parent_relationship then returns “already linked under …” even though it did not create or move the required relationship. Query the task’s current sub-issue parent and compare it; fail/swap only if it differs.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@project_setup/pr_sync.py` around lines 365 - 371, Update the exception
handling around add_sub_issue and sync_parent_relationship so “may only have one
parent” is not treated as success automatically. Query the task’s current
sub-issue parent, compare it with parent_number, and only return the
existing-link message when they match; otherwise propagate the failure or
perform the required parent replacement.

Comment thread project_setup/pr_sync.py
Comment on lines +575 to +585
client = require_client()
project_pat = get_project_pat()
project_client = GitHubClient(project_pat) if project_pat else None
return apply_pr_sync_from_path(
client,
args.repo,
args.event_path,
args.config,
project_client=project_client,
project_number=project_number_from_value(args.project_number),
owner=args.owner,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

ast-grep outline project_setup/project.py --items all
rg -n -C 5 'def resolve_owner_type|PROJECT_SETUP_OWNER_TYPE|def find_project' project_setup
rg -n -C 5 'owner_type|find_project\(' project_setup/pr_sync.py

Repository: v-Kaefer/Github-Project-Automation

Length of output: 6553


🏁 Script executed:

#!/bin/bash
set -euo pipefail

ast-grep outline project_setup/pr_sync.py --items all
sed -n '540,610p' project_setup/pr_sync.py
sed -n '470,525p' project_setup/pr_sync.py
sed -n '380,425p' project_setup/project.py

echo '--- main argument handling in pr_sync.py ---'
rg -n -C 4 'def main\(|argparse|add_argument|sync_project_status\(' project_setup/pr_sync.py

echo '--- sync_project_status definitions/usages ---'
rg -n -C 7 'def sync_project_status|sync_project_status\(' project_setup/pr_sync.py

Repository: v-Kaefer/Github-Project-Automation

Length of output: 9259


🏁 Script executed:

#!/bin/bash
set -euo pipefail

sed -n '388,448p' project_setup/pr_sync.py
sed -n '400,412p' project_setup/project.py

Repository: v-Kaefer/Github-Project-Automation

Length of output: 2357


Provide a command-line owner_type path for this entrypoint.

resolve_owner_type does read PROJECT_SETUP_OWNER_TYPE, but project_setup/pr_sync.py parses only --owner, and apply_pr_sync_from_path(...) passes no owner_type into sync_project_status(...), so that environment variable is ignored for project-sync. Add --owner-type to the parser and pass it through sync_project_status(...) to find_project(...).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@project_setup/pr_sync.py` around lines 575 - 585, Add an --owner-type
argument to the project-sync CLI parser, then propagate its value from the
entrypoint through apply_pr_sync_from_path and sync_project_status to
find_project. Ensure the flow also preserves the existing resolve_owner_type
behavior, including PROJECT_SETUP_OWNER_TYPE when no command-line value is
provided.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant