|
| 1 | +# Creating a pull request |
| 2 | + |
| 3 | +This is the canonical workflow for opening a pull request on this repository. It is written to be followed by both humans and AI coding agents. Tool-specific entry points — the Claude Code skill, the Cursor rule, any future Copilot chat mode — should be thin pointers to this file so every tool follows the same procedure. |
| 4 | + |
| 5 | +Rules and templates live elsewhere — this file is the **procedure**: |
| 6 | + |
| 7 | +- **Changelog grammar, label rules, bracket-prefix rules, release-branch rules** → [`.github/PULL_REQUEST_TEMPLATE.md`](../../.github/PULL_REQUEST_TEMPLATE.md) |
| 8 | +- **Architecture, repository layout, placement rules, dependency injection, build/test commands, Yoast CS ruleset, testing policy, coverage policy, commit style, branching, pre-push checks** → [`.github/CONTRIBUTING.md`](../../.github/CONTRIBUTING.md) |
| 9 | +- **Agent-specific behaviours (delegate long-running commands, verify before recommending, ask don't guess)** → [`AGENTS.md`](../../AGENTS.md) |
| 10 | + |
| 11 | +If anything here contradicts those files, prefer them. Edits to rules belong there, not in this file. |
| 12 | + |
| 13 | +## 0. Creator vs. merger responsibilities |
| 14 | + |
| 15 | +Every merged PR needs a milestone, a changelog entry, and a changelog label. Split: |
| 16 | + |
| 17 | +- **Creator provides:** a changelog entry (in the PR body) and a changelog label on the PR. |
| 18 | +- **Creator MUST NOT set:** the milestone. That is the merger's job. Do not add a milestone via `gh pr edit --milestone`. |
| 19 | + |
| 20 | +## 1. Gather context |
| 21 | + |
| 22 | +Run in parallel: |
| 23 | + |
| 24 | +- `git status` |
| 25 | +- `git diff` |
| 26 | +- `git log <base>..HEAD` and `git diff <base>...HEAD` — inspect **every** commit since the branch diverged, not just the tip |
| 27 | +- Check whether the branch has an upstream and is up to date |
| 28 | + |
| 29 | +Identify the base branch: usually `trunk`. PRs targeting `release/*` follow stricter label rules — see the PR template. |
| 30 | + |
| 31 | +Read [`.github/PULL_REQUEST_TEMPLATE.md`](../../.github/PULL_REQUEST_TEMPLATE.md) so the PR body matches it section-for-section. |
| 32 | + |
| 33 | +## 2. Verify checks |
| 34 | + |
| 35 | +Follow the pre-push checklist in [`.github/CONTRIBUTING.md` — "Before you push or open/update a PR"](../../.github/CONTRIBUTING.md). All required checks must pass **before** calling `gh pr create`. Do not silently skip a check; if something cannot be run locally (e.g. `composer test-wp-env` without Docker), disclose it in the PR body's *Test instructions* section. |
| 36 | + |
| 37 | +Do not paper over failures by excluding tests, lowering CS thresholds, or adding ignore pragmas without explicit permission. |
| 38 | + |
| 39 | +If a `build-runner`-style agent is available in your tool, delegate the actual command execution there so the main session stays focused on the workflow. |
| 40 | + |
| 41 | +## 3. Decide how many changelog bullets the PR needs |
| 42 | + |
| 43 | +Default is **one bullet**, describing one logical change. Write more than one bullet only in these cases: |
| 44 | + |
| 45 | +- **Case A — multiple distinct changes in the same repo and same label.** One bullet per change; no brackets. |
| 46 | +- **Case B — bullets with different changelog types.** Add a `[repo type]` override only on the bullets whose type *differs* from the PR label; bullets that match the PR label stay unprefixed. |
| 47 | +- **Case C — impact on multiple repos or packages.** One bullet per affected changelog, each prefixed with `[<repo-or-package>]`. Routing prefix is mandatory for non-Free targets. |
| 48 | + |
| 49 | +Grammar, bracket syntax, semver hints, bugfix template, and the release-branch label rules all live in the PR template — follow the template, do not restate the rules here or in the PR body. |
| 50 | + |
| 51 | +If you are not certain a change affects another repo (Premium, Shopify, etc.), ask the user rather than guessing. |
| 52 | + |
| 53 | +## 4. Fill every PR-template section |
| 54 | + |
| 55 | +Cover every section of `.github/PULL_REQUEST_TEMPLATE.md`: |
| 56 | + |
| 57 | +- **Context** — *why* the change is being made. |
| 58 | +- **Summary** — the bullet(s) from step 3. |
| 59 | +- **Relevant technical choices** — non-obvious decisions, trade-offs, architectural notes. **If coverage decreased, explain here why tests weren't feasible.** |
| 60 | +- **Test instructions (acceptance)** — step-by-step, aimed at non-technical users. |
| 61 | +- **Relevant test scenarios** — tick the boxes that apply and explain why for each ticked box. |
| 62 | +- **QA instructions** — for non-user-facing PRs (docs, pure refactors, tooling), leave the checkbox unticked and write "Not applicable". Otherwise tick "same steps as above" when acceptance and QA match, or write separate steps (or link to the epic). |
| 63 | +- **Impact check** — parts of the plugin that may need regression testing. |
| 64 | +- **Other environments** — tick Shopify / Google Docs boxes only when the corresponding entry is present in step 3. |
| 65 | +- **Documentation / Quality assurance / Innovation** checkboxes — tick only those that are actually true. |
| 66 | +- **Fixes #** — link the issue being closed, if any. |
| 67 | + |
| 68 | +Preserve the HTML comments from the template so future editors keep the same structure. |
| 69 | + |
| 70 | +## 5. Create and label the PR |
| 71 | + |
| 72 | +1. Push the branch if it has no upstream: `git push -u origin <branch>`. |
| 73 | +2. `gh pr create --title "<title>" --body "$(cat <<'EOF' ... EOF)"`. |
| 74 | + - Title under 70 characters. Use a Conventional Commits prefix when natural (`fix: …`, `feat(dashboard): …`). |
| 75 | + - The body is the completed template, verbatim-structured. |
| 76 | +3. Apply the changelog label immediately: `gh pr edit <number> --add-label "changelog: <type>"`. Attach Shopify / Google Docs / innovation labels in the same call only when the corresponding condition holds. |
| 77 | +4. **Never set the milestone.** |
| 78 | +5. Return the PR URL. |
| 79 | + |
| 80 | +## 6. Self-check |
| 81 | + |
| 82 | +Before reporting the PR as created, verify: |
| 83 | + |
| 84 | +- [ ] Pre-push checks (step 2) ran and passed — any skipped check is disclosed in the PR body. |
| 85 | +- [ ] Coverage increased or held flat — or the *Relevant technical choices* section explains why tests weren't feasible. |
| 86 | +- [ ] The body contains at least one changelog bullet, correctly prefixed for every affected changelog. |
| 87 | +- [ ] Exactly one `changelog:` label is attached; Shopify / Google Docs / innovation labels match the content. |
| 88 | +- [ ] Bugfix bullets describe the incorrect behaviour followed by the triggering condition, in past tense, per the PR template's grammar rules. |
| 89 | +- [ ] Every PR-template section has content — no empty bullets, no leftover placeholder text. |
| 90 | +- [ ] No milestone was set. |
| 91 | +- [ ] If the branch adds or edits any image or SVG, `grunt build:images` was run and its optimised output committed. Tick the matching *Quality assurance* checkbox in the PR body. |
| 92 | +- [ ] Each changelog bullet is one short sentence; extra context lives in *Context* or *Relevant technical choices*. |
| 93 | + |
| 94 | +If any item fails, fix it (edit the body or labels with `gh pr edit`) before returning the URL. |
0 commit comments