Skip to content

docs(agents): add downstream repository checklist to the PR template - #3298

Merged
myasnikovdaniil merged 1 commit into
mainfrom
docs/pr-template-downstream-checklist
Jul 15, 2026
Merged

docs(agents): add downstream repository checklist to the PR template#3298
myasnikovdaniil merged 1 commit into
mainfrom
docs/pr-template-downstream-checklist

Conversation

@lexfrei

@lexfrei Aleksei Sviridkin (lexfrei) commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

What this PR does

Cozystack is upstream for repositories that nothing keeps in sync with it, and no CI job compares the two sides, so a change here can break them in silence. It has already happened: packages/apps/opensearch ships but has no reference page on the website, the Terraform provider still offers a Kubernetes version this repo removed, and the plugin repo still sends operators to a hack/ script that was deleted.

This adds a Downstream Repositories trigger map to docs/agents/contributing.md — per repository, which change here forces a change over there and which file to touch — and a checklist in the PR template that links to it. The template addresses AI agents directly, since they author a large share of PRs, and tells them to open the follow-up rather than tick a box that claims work nobody did.

A unit test (hack/downstream-trigger-map.bats) keeps the map from rotting: it pins every in-repo path the map cites to a file that exists, pins the map and the checklist to the same repository list, and pins the CI carve-out that keeps the test running when the map is edited alone. Its header is explicit about what it cannot check — whether a coupling is real, and whether it still holds in the other repo, stays a human's job.

Downstream repositories

  • No downstream repository is affected by this change

Release note

NONE

Summary by CodeRabbit

  • Documentation

    • Expanded contributor guidance for downstream repository changes and follow-up links.
    • Clarified how to preserve PR template checklists when creating pull requests.
    • Added detailed downstream repository trigger-map instructions.
  • CI

    • Documentation changes affecting the trigger map now run unit and controller checks.
  • Tests

    • Added validation to ensure trigger-map paths, workflow wiring, and repository lists remain consistent.

Cozystack is upstream for repositories that nothing keeps in sync with
it, and no CI job compares the two sides, so a change here breaks them
in silence. Only two narrow paths are automated, and both fire on a
release rather than on a PR.

It has already happened. The website docs generator works from an app
list hardcoded in its own Makefile, and packages/apps/opensearch was
never added to it, so an application we ship has no reference page at
all. The Terraform provider still offers a Kubernetes version this repo
removed. The plugin repo still sends operators to hack/ scripts that
were deleted, one of them rewritten as a Go command.

Add a Downstream Repositories trigger map to the contributing guide,
naming per repository which change here forces a change over there and
which file to touch, and a checklist in the PR template that links to
it. The template addresses AI agents directly: they author a large share
of PRs and will otherwise tick a box without opening the follow-up it
claims.

The coupling is wider than the obvious ones, and mostly invisible. talm
restates the node contract, overlapping ours but already diverged, so it
must be diffed rather than overwritten. cozyhr reads an annotation the
operator writes and silently merges the wrong values if it is renamed.
cozy-proxy is vendored in from its own repo, yet consumes labels
produced here and quietly stops handling external VM services if they
move. The telemetry server queries metric names emitted here, and a
rename just empties its dashboards. None of these fail loudly.

Guard the map with a unit test, because a map about silent drift must
not drift silently itself. It pins every in-repo path the map cites to a
file that exists, pins the map and the checklist to the same repository
list, and pins the workflow carve-out below to the map's location, to
the job that reads the flag, and to the output that carries it: cutting
any one of those three leaves the other two looking wired up. The header
states plainly what the suite cannot check, so a green tick is not
mistaken for a correct map: whether a coupling is real, and whether it
still holds over there, stays a human's job.

Editing the map alone is a docs-only PR, which skips the unit tests and
would exempt the map from its own guard. Rather than widen the docs-only
rule, which also gates the Talos image build, the plan step exports a
separate flag that only the unit-test job reads: a docs PR now runs the
tests and still builds nothing. It detects the map by its old path too,
since a rename is reported as the new path alone.

Document that gh pr create --body and --body-file replace the body
wholesale, which would otherwise drop the checklist from every
CLI-authored PR.

Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request addresses the silent breakage of downstream repositories by introducing a mandatory checklist and a comprehensive trigger map. By explicitly documenting coupling points and enforcing a follow-up process, the changes ensure that contributors and AI agents are aware of the impact their changes have on satellite repositories, reducing the risk of drift and broken integrations.

Highlights

  • Downstream Repository Checklist: Added a new checklist to the PR template that requires contributors to acknowledge and link follow-up PRs for affected downstream repositories.
  • Trigger Map Documentation: Expanded docs/agents/contributing.md with a detailed trigger map that outlines which changes in the upstream repository necessitate updates in specific downstream projects.
  • Automated Validation: Introduced a new unit test (hack/downstream-trigger-map.bats) to ensure the trigger map remains accurate, paths are valid, and the PR template checklist stays synchronized with the documentation.
New Features

🧠 You can now enable Memory (public preview) to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Ignored Files
  • Ignored by pattern: .github/workflows/** (1)
    • .github/workflows/pull-requests.yaml
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment Gemini (@gemini-code-assist) Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize the Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counterproductive. You can react with 👍 and 👎 on Gemini (@gemini-code-assist) comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@dosubot dosubot Bot added area/ai Issues or PRs related to AI agent guides, AGENTS.md, docs/agents/ area/testing Issues or PRs related to testing (e2e, bats, unit tests) kind/documentation Categorizes issue or PR as related to documentation labels Jul 14, 2026
@coderabbitai

coderabbitai Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 168e7255-1127-4bba-87d9-5b9dd090ea71

📥 Commits

Reviewing files that changed from the base of the PR and between 6f58898 and 44507d2.

📒 Files selected for processing (4)
  • .github/PULL_REQUEST_TEMPLATE.md
  • .github/workflows/pull-requests.yaml
  • docs/agents/contributing.md
  • hack/downstream-trigger-map.bats

📝 Walkthrough

Walkthrough

The PR adds downstream repository guidance and checklist content, triggers unit tests when the trigger map changes, and adds Bats coverage for documented paths, workflow wiring, and repository-list consistency.

Changes

Downstream trigger map

Layer / File(s) Summary
Downstream guidance and checklist
.github/PULL_REQUEST_TEMPLATE.md, docs/agents/contributing.md
Adds downstream repository checklist entries, trigger-map instructions, PR creation guidance, and repository-specific impact criteria.
Trigger-map CI wiring
.github/workflows/pull-requests.yaml
Exports trigger_map when the contributing guide changes and runs unit tests when that output is true.
Trigger-map consistency tests
hack/downstream-trigger-map.bats
Validates documented paths, workflow integration, and matching downstream repository lists.
Estimated code review effort: 3 (Moderate) ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant PRDiff
  participant PlanJob
  participant ChecksJob
  participant TriggerMapTests
  PRDiff->>PlanJob: detect contributing guide changes
  PlanJob->>ChecksJob: set trigger_map output
  ChecksJob->>TriggerMapTests: run make unit-tests
  TriggerMapTests->>TriggerMapTests: validate map, workflow, and repository lists
Loading

Possibly related PRs

Suggested labels: area/ci

Suggested reviewers: kvaps, androndo

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes a real part of the PR by adding the downstream repository checklist to the PR template.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch docs/pr-template-downstream-checklist

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.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a "Downstream Repositories" trigger map and checklist to track changes affecting downstream repositories, accompanied by a BATS test suite to ensure the map's paths and repository lists remain valid and synchronized. The reviewer suggested making the workflow parsing in the BATS test more robust by normalizing whitespace and quotes to prevent fragility against minor formatting changes in the workflow YAML.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +115 to +163
code_only="$(sed 's/#.*//' "$WORKFLOW")"

# The block of the job that runs the unit tests, from its header to the next
# job's. The condition has to sit on THAT job: pinning it file-wide would accept
# the exact expression pasted into some other job while the unit-test job quietly
# loses it.
unit_job="$(printf '%s\n' "$code_only" | awk '
/^ [a-zA-Z0-9_-]+:[[:space:]]*$/ { inside = ($0 == " checks:") }
inside')"
printf '%s\n' "$unit_job" | grep -q 'make unit-tests' || {
echo "The 'checks' job in .github/workflows/pull-requests.yaml no longer runs 'make unit-tests'." >&2
echo "This suite pins the trigger-map carve-out to that job. If the unit tests moved, point" >&2
echo "the checks below at their new job." >&2
exit 1
}

# Three links carry the carve-out: the plan step names the map, the plan job
# exports the flag, and the unit-test job gates on it. Cutting any one leaves the
# other two looking perfectly wired, and none of them fails loudly — an unset or
# unexported output dereferences to an empty string, so the condition is merely
# false and the suite is skipped in silence, on exactly the PRs it guards, with
# every test in this file still green. Pin all three.
rel="${MAP_FILE#"$REPO_ROOT"/}"
printf '%s\n' "$code_only" | grep -qF "'$rel'" || {
echo "The plan step in .github/workflows/pull-requests.yaml does not name '$rel'." >&2
echo "Without it, a PR that only edits the trigger map is treated as docs-only, the unit" >&2
echo "tests are skipped, and this file never runs — exactly when it is needed most." >&2
echo "Fix: point the trigger_map detection at the map's new path." >&2
exit 1
}

printf '%s\n' "$code_only" | grep -qF 'trigger_map: ${{ steps.p.outputs.trigger_map }}' || {
echo "The plan job in .github/workflows/pull-requests.yaml does not export trigger_map." >&2
echo "The step still computes it and the unit-test job still reads it, so this looks wired" >&2
echo "up, but an unexported output dereferences to an empty string: the job is skipped in" >&2
echo "silence on exactly the PRs this suite guards." >&2
echo "Fix: restore 'trigger_map: \${{ steps.p.outputs.trigger_map }}' to the plan job's outputs." >&2
exit 1
}

condition="(needs.plan.outputs.code == 'true' || needs.plan.outputs.trigger_map == 'true')"
printf '%s\n' "$unit_job" | grep -qF "$condition" || {
echo "The job that runs 'make unit-tests' is not gated on:" >&2
echo " $condition" >&2
echo "Mentioning trigger_map in another job, or in a comment, does not count. Without that" >&2
echo "exact condition on that job, a PR which only edits the trigger map stays docs-only," >&2
echo "skips the unit tests, and never runs this file — while every test here still passes." >&2
exit 1
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

low

The current implementation of the workflow checks uses exact string matching (grep -qF) on multi-line YAML structures. This is highly fragile to minor formatting changes in .github/workflows/pull-requests.yaml (such as changing single quotes to double quotes, adding/removing trailing whitespace, or altering spacing around operators).

We can make these checks extremely robust by normalizing the whitespace and quotes (e.g., using tr -d "[:space:]'\"") before performing the substring matches. Additionally, we can refine the awk pattern for finding the checks job to safely handle trailing spaces or carriage returns.

  code_only="$(sed 's/#.*//' "$WORKFLOW")"
  normalized_code="$(printf '%s\n' "$code_only" | tr -d "[:space:]'\"")"

  # The block of the job that runs the unit tests, from its header to the next
  # job's. The condition has to sit on THAT job: pinning it file-wide would accept
  # the exact expression pasted into some other job while the unit-test job quietly
  # loses it.
  unit_job="$(printf '%s\n' "$code_only" | awk '
    /^  [a-zA-Z0-9_-]+:[[:space:]]*$/ { inside = ($0 ~ /^  checks:[[:space:]]*$/) }
    inside')"
  normalized_unit_job="$(printf '%s\n' "$unit_job" | tr -d "[:space:]'\"")"

  printf '%s\n' "$unit_job" | grep -q 'make unit-tests' || {
    echo "The 'checks' job in .github/workflows/pull-requests.yaml no longer runs 'make unit-tests'." >&2
    echo "This suite pins the trigger-map carve-out to that job. If the unit tests moved, point"
    echo "the checks below at their new job." >&2
    exit 1
  }

  # Three links carry the carve-out: the plan step names the map, the plan job
  # exports the flag, and the unit-test job gates on it. Cutting any one leaves the
  # other two looking perfectly wired, and none of them fails loudly — an unset or
  # unexported output dereferences to an empty string, so the condition is merely
  # false and the suite is skipped in silence, on exactly the PRs it guards, with
  # every test in this file still green. Pin all three.
  rel="${MAP_FILE#"$REPO_ROOT"/}"
  printf '%s\n' "$normalized_code" | grep -qF "$rel" || {
    echo "The plan step in .github/workflows/pull-requests.yaml does not name '$rel'." >&2
    echo "Without it, a PR that only edits the trigger map is treated as docs-only, the unit"
    echo "tests are skipped, and this file never runs — exactly when it is needed most." >&2
    echo "Fix: point the trigger_map detection at the map's new path." >&2
    exit 1
  }

  printf '%s\n' "$normalized_code" | grep -qF 'trigger_map:${{steps.p.outputs.trigger_map}}' || {
    echo "The plan job in .github/workflows/pull-requests.yaml does not export trigger_map." >&2
    echo "The step still computes it and the unit-test job still reads it, so this looks wired"
    echo "up, but an unexported output dereferences to an empty string: the job is skipped in"
    echo "silence on exactly the PRs this suite guards." >&2
    echo "Fix: restore 'trigger_map: \${{ steps.p.outputs.trigger_map }}' to the plan job's outputs." >&2
    exit 1
  }

  condition_norm="(needs.plan.outputs.code==true||needs.plan.outputs.trigger_map==true)"
  printf '%s\n' "$normalized_unit_job" | grep -qF "$condition_norm" || {
    echo "The job that runs 'make unit-tests' is not gated on:" >&2
    echo "  (needs.plan.outputs.code == 'true' || needs.plan.outputs.trigger_map == 'true')" >&2
    echo "Mentioning trigger_map in another job, or in a comment, does not count. Without that"
    echo "exact condition on that job, a PR which only edits the trigger map stays docs-only,"
    echo "skips the unit tests, and never runs this file — while every test here still passes." >&2
    exit 1
  }

@github-actions github-actions Bot added the size/L This PR changes 100-499 lines, ignoring generated files label Jul 14, 2026

@myasnikovdaniil myasnikovdaniil left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM.

The trigger-map + PR-template checklist + hack/downstream-trigger-map.bats guard are internally consistent — the workflow carve-out is wired across all three links (plan-step detection, output export, and the checks job if:), the map/template repository lists agree (10↔10), the rename tripwire (git diff --no-renames + grep -qxF) and the anti-vacuum floor back each other up, and every cited shared-root path resolves (28 paths, 0 missing). Guard scope is honest: it validates the map's internal consistency when contributing.md changes; the checklist itself stays advisory — nothing in CI blocks a PR that skips it. One non-blocking note inline.

needs: ["plan"]
# trigger_map opts a docs-only PR back in when it edits the downstream trigger
# map, so hack/downstream-trigger-map.bats still guards it. No other job reads
# that flag: a docs PR runs the unit tests and nothing heavier.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Minor wording: the checks job runs both make unit-tests and make test-controllers, so a docs-only edit that trips this flag also runs the envtest controller suite — “nothing heavier” is slightly optimistic. Still safe (that job builds no images), so the intent holds.

@myasnikovdaniil
myasnikovdaniil merged commit ce1b74d into main Jul 15, 2026
50 checks passed
@myasnikovdaniil
myasnikovdaniil deleted the docs/pr-template-downstream-checklist branch July 15, 2026 08:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/ai Issues or PRs related to AI agent guides, AGENTS.md, docs/agents/ area/testing Issues or PRs related to testing (e2e, bats, unit tests) kind/documentation Categorizes issue or PR as related to documentation size/L This PR changes 100-499 lines, ignoring generated files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants