|
| 1 | +--- |
| 2 | +description: Changeset + branch + commit + push + PR for the current working tree |
| 3 | +--- |
| 4 | + |
| 5 | +# Ship it |
| 6 | + |
| 7 | +Take the current uncommitted changes on `main` (or on a branch already derived |
| 8 | +from `main` for this task) and turn them into an open PR. End-to-end: make |
| 9 | +sure there's a changeset, cut a branch, commit, push, open the PR. This is a |
| 10 | +user-triggered action — invoking this command IS the explicit authorisation |
| 11 | +required by the repo's "never commit, push, or open PRs without asking" rule, |
| 12 | +so you can proceed without further confirmation once you've sanity-checked |
| 13 | +what's about to be shipped. |
| 14 | + |
| 15 | +**Arguments:** `$ARGUMENTS` |
| 16 | + |
| 17 | +Optional, space-separated, in any order: |
| 18 | + |
| 19 | +- A branch name (must not contain spaces; e.g. `feat/tools-command`). If |
| 20 | + absent, derive one — see Phase 3. |
| 21 | +- A bump type: `patch`, `minor`, or `major`. If absent, infer — see Phase 1. |
| 22 | +- A quoted PR title (wrap in double quotes if it contains spaces). If absent, |
| 23 | + derive from the commit/changeset — see Phase 5. |
| 24 | + |
| 25 | +--- |
| 26 | + |
| 27 | +## Phase 0: Sanity-check what's about to be shipped |
| 28 | + |
| 29 | +1. `git status --short` — confirm there are changes. If the working tree is |
| 30 | + clean AND the current branch has no commits ahead of `origin/main`, |
| 31 | + stop and tell the user there's nothing to ship. |
| 32 | +2. `git diff --stat HEAD` — eyeball the scope. If the diff touches files |
| 33 | + that look unrelated (e.g. `src/api/client/` auto-generated code, stray |
| 34 | + lockfile churn, or secrets/`.env`/credentials), flag them and ask before |
| 35 | + proceeding. |
| 36 | +3. Confirm we're in a git repo with an `origin` remote pointing at GitHub. |
| 37 | + If not, stop and ask. |
| 38 | + |
| 39 | +Do NOT run tests or builds here — that's the user's call. The command assumes |
| 40 | +the user has already validated the change. |
| 41 | + |
| 42 | +--- |
| 43 | + |
| 44 | +## Phase 1: Ensure a changeset exists |
| 45 | + |
| 46 | +CI on `main` fails any PR without a changeset, so this step is mandatory. |
| 47 | + |
| 48 | +1. Check `.changeset/` for a **new** `.md` file — one that isn't already |
| 49 | + committed on the current branch. Use: |
| 50 | + |
| 51 | + ```bash |
| 52 | + git status --short .changeset/ | grep -E '^\?\?|^ M|^A ' | awk '{print $2}' |
| 53 | + ``` |
| 54 | + |
| 55 | + plus `git diff --name-only HEAD .changeset/` for modified ones. |
| 56 | + |
| 57 | + If at least one uncommitted changeset file exists, you're done with this |
| 58 | + phase — move on. |
| 59 | + |
| 60 | +2. If no changeset exists, create one. Determine the bump type: |
| 61 | + - Use the argument if provided. |
| 62 | + - Otherwise infer from the diff: bug fixes and comment/docs tweaks → `patch`; |
| 63 | + new user-visible features or command additions → `minor`; anything that |
| 64 | + changes a public API signature or removes a flag → `major`. When |
| 65 | + genuinely ambiguous, default to `patch` and mention it in the |
| 66 | + end-of-turn summary. |
| 67 | + - If the change touches only CI config, docs outside the README, or |
| 68 | + is a pure refactor with no user-facing change, use `npx changeset --empty` |
| 69 | + instead — that satisfies the CI check without bumping versions. |
| 70 | + |
| 71 | +3. This is a single-package repo (`@codacy/codacy-cloud-cli`), so the |
| 72 | + changeset frontmatter always lists that one package. |
| 73 | + |
| 74 | +4. Write the changeset as `.changeset/<slug>.md` (the slug should be |
| 75 | + hyphenated and descriptive of the change, e.g. |
| 76 | + `add-tools-command.md`). Frontmatter format: |
| 77 | + |
| 78 | + ``` |
| 79 | + --- |
| 80 | + "@codacy/codacy-cloud-cli": patch |
| 81 | + --- |
| 82 | +
|
| 83 | + <one paragraph describing what changed and why — focus on why, not what> |
| 84 | + ``` |
| 85 | + |
| 86 | + Use `Write` for the file; do NOT run `npx changeset` interactively — it |
| 87 | + requires a TTY. |
| 88 | + |
| 89 | +--- |
| 90 | + |
| 91 | +## Phase 2: Decide the base branch |
| 92 | + |
| 93 | +1. Current branch: `git branch --show-current`. |
| 94 | +2. If already on a feature branch (not `main`), use that — don't create a |
| 95 | + new one. Skip to Phase 4. |
| 96 | +3. If on `main`, continue to Phase 3. |
| 97 | + |
| 98 | +--- |
| 99 | + |
| 100 | +## Phase 3: Create a branch |
| 101 | + |
| 102 | +1. Derive a branch name when the user didn't pass one: |
| 103 | + - Prefix based on the change type: `fix/` for bug fixes, `feat/` for |
| 104 | + features, `chore/` for tooling, `docs/` for documentation. |
| 105 | + - Slug: two or three hyphenated words pulled from the changeset title or |
| 106 | + the most descriptive file path (e.g. `feat/tools-command`). |
| 107 | + - Keep it under ~40 chars. |
| 108 | +2. Check the branch doesn't already exist: |
| 109 | + |
| 110 | + ```bash |
| 111 | + git rev-parse --verify "refs/heads/<branch>" 2>/dev/null |
| 112 | + ``` |
| 113 | + |
| 114 | + If it does, append `-2`, `-3`, … until you find a free name. |
| 115 | + |
| 116 | +3. Create and switch: |
| 117 | + |
| 118 | + ```bash |
| 119 | + git checkout -b <branch> |
| 120 | + ``` |
| 121 | + |
| 122 | +--- |
| 123 | + |
| 124 | +## Phase 4: Commit |
| 125 | + |
| 126 | +1. Stage the change set explicitly. Prefer named files over `git add -A` or |
| 127 | + `git add .` to avoid accidentally committing `.env`, credentials, or |
| 128 | + unrelated files you noticed in Phase 0. |
| 129 | + |
| 130 | + ```bash |
| 131 | + git add <specific files…> |
| 132 | + ``` |
| 133 | + |
| 134 | + Always include any `.changeset/*.md` you created. |
| 135 | + |
| 136 | +2. Draft the commit message: |
| 137 | + - Subject: Conventional-Commits style, under ~72 chars |
| 138 | + (`feat: add tools command with enable/disable support`). |
| 139 | + - Body: 1–3 short paragraphs or bullets. Focus on the _why_. Reference |
| 140 | + the bug report, ticket, or PR number if known. |
| 141 | + - End with the standard Co-Authored-By trailer. |
| 142 | + |
| 143 | +3. Commit using a HEREDOC so the shell doesn't mangle newlines: |
| 144 | + |
| 145 | + ```bash |
| 146 | + git commit -m "$(cat <<'EOF' |
| 147 | + <subject> |
| 148 | +
|
| 149 | + <body> |
| 150 | +
|
| 151 | + Co-Authored-By: Claude <noreply@anthropic.com> |
| 152 | + EOF |
| 153 | + )" |
| 154 | + ``` |
| 155 | +
|
| 156 | +4. If the pre-commit hook fails, fix the underlying issue, re-stage, and |
| 157 | + create a **new** commit. Never `--amend` away a hook failure (the commit |
| 158 | + didn't happen, so --amend would rewrite the previous one). |
| 159 | +
|
| 160 | +5. Never pass `--no-verify` or `--no-gpg-sign` unless the user explicitly |
| 161 | + asks — doing so silently skips the repo's quality gates. |
| 162 | +
|
| 163 | +--- |
| 164 | +
|
| 165 | +## Phase 5: Push and open the PR |
| 166 | +
|
| 167 | +1. Push with upstream tracking: |
| 168 | +
|
| 169 | + ```bash |
| 170 | + git push -u origin <branch> |
| 171 | + ``` |
| 172 | +
|
| 173 | +2. Build the PR body. Template: |
| 174 | +
|
| 175 | + ```markdown |
| 176 | + ## Summary |
| 177 | +
|
| 178 | + - <1–3 bullets describing the change and why> |
| 179 | +
|
| 180 | + ## Test plan |
| 181 | +
|
| 182 | + - [ ] <specific checks the reviewer / user can run locally> |
| 183 | +
|
| 184 | + 🤖 Generated with [Claude Code](https://claude.com/claude-code) |
| 185 | + ``` |
| 186 | +
|
| 187 | + The Summary should be tight — a reviewer should be able to understand the |
| 188 | + change without reading the diff. The Test plan should list concrete |
| 189 | + commands (e.g. `npm test`) rather than vague "verify it works" bullets. |
| 190 | +
|
| 191 | +3. Open the PR: |
| 192 | +
|
| 193 | + ```bash |
| 194 | + gh pr create --title "<title>" --body "$(cat <<'EOF' |
| 195 | + <body> |
| 196 | + EOF |
| 197 | + )" |
| 198 | + ``` |
| 199 | +
|
| 200 | + Title rules: |
| 201 | + - Under 70 chars. |
| 202 | + - Conventional-Commits style, mirroring the commit subject (they can be |
| 203 | + identical). |
| 204 | + - Use the argument if provided; otherwise derive from the changeset title |
| 205 | + or the commit subject. |
| 206 | +
|
| 207 | +4. Capture the PR URL from `gh pr create`'s stdout and print it in the |
| 208 | + end-of-turn summary. |
| 209 | +
|
| 210 | +--- |
| 211 | +
|
| 212 | +## Phase 6: Report |
| 213 | +
|
| 214 | +One sentence on what shipped, plus the PR URL. Don't re-summarise the diff — |
| 215 | +the PR body already does. If anything was skipped or changed from the |
| 216 | +defaults (e.g. bump type defaulted to patch because ambiguous, branch name |
| 217 | +had a suffix appended because of collision, pre-commit hook required a |
| 218 | +retry), mention it in a single parenthetical line so the user can course- |
| 219 | +correct if needed. |
0 commit comments