Skip to content

Commit 7efa85c

Browse files
garrytanclaude
andauthored
v1.23.0.0 feat: always prefix PR titles with v<VERSION> (#1284)
* feat: add bin/gstack-pr-title-rewrite.sh shared helper Single source of truth for "rewrite a PR title to start with v<VERSION>". Three cases: already correct (no-op), different prefix (replace), no prefix (prepend). Rejects malformed VERSION (anything outside ^[0-9]+(\.[0-9]+)*$) with exit code 2. Uses literal case prefix match instead of bash's pattern- matching # operator so a VERSION with glob metacharacters cannot mismatch. Free bun test covers the four branches plus malformed-input rejection, plain-words-not-stripped, single-segment-not-stripped, idempotence, and missing-args. 9 tests, ~400ms. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * feat(skills): /ship and /document-release always prefix PR titles with v<VERSION> ship/SKILL.md.tmpl Step 19: idempotency block now always rewrites titles to start with v$NEW_VERSION via the new helper. Removes the "custom title kept intentionally" loophole that let unprefixed titles persist forever. Adds a post-edit self-check that re-fetches the title and retries once if the edit didn't stick. Inline comments on the create-PR snippets at lines 867 and 876 make the rule unmissable. document-release/SKILL.md.tmpl Step 9: new "PR/MR title sync" sub-step calls the same helper after the body update. Catches the case where Step 8 bumped VERSION after /ship had already created the PR — title now follows VERSION instead of going stale. Golden fixtures regenerated for claude/codex/factory ship variants. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * feat(ci): pr-title-sync rewrites titles unconditionally Drops the "eligible only if already prefixed" gate. Sources the new shared helper, rewrites unconditionally on every VERSION change. Defense-in-depth backstop for PRs opened outside the skills (manual gh pr create, web UI). Uses env: for OLD_TITLE so YAML expression injection cannot reach run:. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * chore: bump version and changelog (v1.23.0.0) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
1 parent 454423a commit 7efa85c

13 files changed

Lines changed: 309 additions & 37 deletions

File tree

.github/workflows/pr-title-sync.yml

Lines changed: 9 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -25,40 +25,19 @@ jobs:
2525
fetch-depth: 1
2626
ref: ${{ github.event.pull_request.head.sha }}
2727

28-
- name: Read VERSION + current title
29-
id: inspect
30-
run: |
31-
set -euo pipefail
32-
VERSION=$(cat VERSION | tr -d '[:space:]')
33-
TITLE=$(jq -r '.pull_request.title' "$GITHUB_EVENT_PATH")
34-
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
35-
# Only rewrite titles that ALREADY follow the v<X.Y.Z.W> prefix pattern.
36-
# Custom titles (no prefix) are left alone — user kept them intentionally.
37-
if printf '%s' "$TITLE" | grep -qE '^v[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+ '; then
38-
PREFIX=$(printf '%s' "$TITLE" | awk '{print $1}')
39-
REST=$(printf '%s' "$TITLE" | sed 's/^v[0-9][0-9.]* //')
40-
{
41-
echo "prefix=$PREFIX"
42-
echo "rest=$REST"
43-
echo "eligible=true"
44-
} >> "$GITHUB_OUTPUT"
45-
else
46-
echo "eligible=false" >> "$GITHUB_OUTPUT"
47-
fi
48-
49-
- name: Rewrite title if version changed
50-
if: steps.inspect.outputs.eligible == 'true'
28+
- name: Rewrite PR title to match VERSION
5129
env:
5230
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
5331
PR_NUM: ${{ github.event.pull_request.number }}
54-
NEW_V: ${{ steps.inspect.outputs.version }}
55-
OLD_PREFIX: ${{ steps.inspect.outputs.prefix }}
56-
REST: ${{ steps.inspect.outputs.rest }}
32+
OLD_TITLE: ${{ github.event.pull_request.title }}
5733
run: |
58-
if [ "v$NEW_V" = "$OLD_PREFIX" ]; then
59-
echo "Title already matches v$NEW_V; no change."
34+
set -euo pipefail
35+
chmod +x ./bin/gstack-pr-title-rewrite.sh
36+
VERSION=$(cat VERSION | tr -d '[:space:]')
37+
NEW_TITLE=$(./bin/gstack-pr-title-rewrite.sh "$VERSION" "$OLD_TITLE")
38+
if [ "$NEW_TITLE" = "$OLD_TITLE" ]; then
39+
echo "Title already correct; no change."
6040
exit 0
6141
fi
62-
NEW_TITLE="v$NEW_V $REST"
63-
echo "Rewriting: $OLD_PREFIX ... → v$NEW_V ..."
42+
echo "Rewriting: $OLD_TITLE -> $NEW_TITLE"
6443
gh pr edit "$PR_NUM" --title "$NEW_TITLE"

CHANGELOG.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,49 @@
11
# Changelog
22

3+
## [1.23.0.0] - 2026-04-30
4+
5+
## **Every PR title now starts with `vX.Y.Z.W`. `/ship`, `/document-release`, and the GitHub Action all enforce it.**
6+
7+
The format was already documented in `/ship` Step 19, but a "leave custom titles alone" loophole meant a PR opened without a version prefix would never get one — and `/document-release` never touched the title at all, so a doc-release VERSION bump silently left the PR pointing at the old version. This release closes both gaps. The rule lives in one place now (`bin/gstack-pr-title-rewrite.sh`), all three callers shell out to it, and a free `bun test` locks in the four branches.
8+
9+
### The numbers that matter
10+
11+
Numbers come from `git diff --shortstat origin/main..HEAD` and `bun test test/pr-title-rewrite.test.ts` on a clean tree.
12+
13+
| Metric | Δ |
14+
|---|---|
15+
| Net branch size vs main | +210 / −36 lines (5 files + 2 new) |
16+
| New helper script | **bin/gstack-pr-title-rewrite.sh** (40 lines, single source of truth) |
17+
| New unit tests added | **+9** (test/pr-title-rewrite.test.ts) |
18+
| Unit suite runtime | **402ms** (free-tier, runs on every push) |
19+
| Loopholes closed | **3** (ship Step 19, document-release Step 9, pr-title-sync.yml) |
20+
| Reviewers run on this PR | plan-eng-review (CLEARED) + adversarial (Claude subagent) |
21+
22+
### What this means for builders
23+
24+
PR titles are now a deterministic function of the VERSION file, no matter how the PR got created. Open one via the web UI with `feat: my thing` and the next push of a VERSION bump turns it into `v1.23.0.0 feat: my thing`. Run `/ship` from a stale branch where Step 12's queue-drift detection rebumps to a higher version and the title moves with it. Run `/document-release`, bump VERSION at Step 8, and the PR title now follows along instead of staying at the previous version.
25+
26+
The helper itself rejects malformed VERSION values (anything outside `^[0-9]+(\.[0-9]+)*$`) with exit code 2, uses a literal `case` prefix match instead of bash's pattern-matching `#` operator (so a hypothetical VERSION containing glob metacharacters can't silently mismatch), and is idempotent — applying it twice yields the same result.
27+
28+
### Itemized changes
29+
30+
#### Added
31+
32+
- `bin/gstack-pr-title-rewrite.sh`: shared helper. Takes `<NEW_VERSION>` + `<CURRENT_TITLE>`, prints the corrected title on stdout. Three cases: already correct (no-op), different version prefix (replace), no prefix (prepend). Validates NEW_VERSION shape at entry. Used by `/ship`, `/document-release`, and the GitHub Action.
33+
- `test/pr-title-rewrite.test.ts`: 9 deterministic tests covering already-correct, different-prefix, different-prefix-length, no-prefix, plain-words-not-stripped, single-segment-not-stripped, missing-args, malformed-VERSION rejection, and idempotence. Free-tier, runs on every `bun test`.
34+
35+
#### Changed
36+
37+
- `ship/SKILL.md.tmpl` Step 19: idempotency block now always rewrites titles to start with `v$NEW_VERSION` — no more "custom title kept intentionally" escape hatch. Shells out to `bin/gstack-pr-title-rewrite.sh` for the rule. Adds a post-edit self-check that re-fetches the title and retries once if the edit didn't stick.
38+
- `ship/SKILL.md.tmpl` create-PR snippets (lines 867 and 876): inline comment makes the `v$NEW_VERSION` requirement unmissable when reading the step.
39+
- `document-release/SKILL.md.tmpl` Step 9: new "PR/MR title sync" sub-step calls the same helper after the body update. Catches the case where Step 8 bumped VERSION after `/ship` had already created the PR — title follows VERSION instead of going stale.
40+
- `.github/workflows/pr-title-sync.yml`: drops the "eligible only if already prefixed" gate. Sources the helper, rewrites unconditionally on every VERSION change. Defense-in-depth backstop for PRs opened outside the skills (manual `gh pr create`, web UI). Uses `env:` for `OLD_TITLE` so YAML expression injection can't reach `run:`.
41+
42+
#### For contributors
43+
44+
- The helper is a regular `bin/` script with `set -euo pipefail`, no external deps beyond bash + sed. Slots into the existing pattern alongside `bin/gstack-config`, `bin/gstack-slug`, `bin/gstack-next-version`.
45+
- Test coverage gates this — any future change to the rule has to update the test fixtures or the suite goes red.
46+
347
## [1.21.1.0] - 2026-04-28
448

549
## **plan-ceo-review smoke tightens. The "agent skips Step 0 and ships a plan" regression now fails the gate.**

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
1.21.1.0
1+
1.23.0.0

bin/gstack-pr-title-rewrite.sh

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#!/usr/bin/env bash
2+
# Rewrite a PR/MR title to start with v<NEW_VERSION>.
3+
#
4+
# Usage: bin/gstack-pr-title-rewrite.sh <NEW_VERSION> <CURRENT_TITLE>
5+
# Output: corrected title on stdout.
6+
#
7+
# Rule: PR titles MUST start with v<NEW_VERSION>. Three cases:
8+
# 1. Already starts with "v<NEW_VERSION> " -> no change.
9+
# 2. Starts with a different "v<digits and dots> " prefix -> replace prefix.
10+
# 3. No version prefix -> prepend "v<NEW_VERSION> ".
11+
#
12+
# The version-prefix regex matches two or more dot-separated digit segments
13+
# (covers v1.2, v1.2.3, v1.2.3.4) so the rule is portable across repos that
14+
# use 3-part or 4-part versions, but does NOT strip plain words like
15+
# "version 5".
16+
17+
set -euo pipefail
18+
19+
if [ $# -lt 2 ]; then
20+
echo "usage: $0 <NEW_VERSION> <CURRENT_TITLE>" >&2
21+
exit 2
22+
fi
23+
24+
NEW_VERSION="$1"
25+
TITLE="$2"
26+
27+
# Reject malformed NEW_VERSION early. Real values are dot-separated digits;
28+
# anything with shell pattern metacharacters or whitespace is a caller bug.
29+
if ! printf '%s' "$NEW_VERSION" | grep -qE '^[0-9]+(\.[0-9]+)*$'; then
30+
echo "error: NEW_VERSION must be dot-separated digits, got: $NEW_VERSION" >&2
31+
exit 2
32+
fi
33+
34+
# Literal prefix match (case statement is glob-quoted by bash, but our
35+
# regex-validated NEW_VERSION has no glob metacharacters so this is safe).
36+
case "$TITLE" in
37+
"v$NEW_VERSION "*)
38+
printf '%s\n' "$TITLE"
39+
exit 0
40+
;;
41+
esac
42+
43+
REST=$(printf '%s' "$TITLE" | sed -E 's/^v[0-9]+(\.[0-9]+)+ //')
44+
printf 'v%s %s\n' "$NEW_VERSION" "$REST"

document-release/SKILL.md

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1018,6 +1018,54 @@ rm -f /tmp/gstack-pr-body-$$.md
10181018
7. If `gh pr edit` / `glab mr update` fails: warn "Could not update PR/MR body — documentation changes are in the
10191019
commit." and continue.
10201020

1021+
**PR/MR title sync (idempotent, always-on):**
1022+
1023+
PR titles must always start with `v<VERSION>` — same rule as `/ship`. If Step 8 bumped VERSION after `/ship` had already created the PR, the title is now stale. This sub-step fixes it.
1024+
1025+
1. Read the current VERSION:
1026+
1027+
```bash
1028+
V=$(cat VERSION 2>/dev/null | tr -d '[:space:]')
1029+
```
1030+
1031+
If `VERSION` does not exist or is empty, skip this sub-step entirely.
1032+
1033+
2. Read the current PR/MR title:
1034+
1035+
**If GitHub:**
1036+
```bash
1037+
CURRENT_TITLE=$(gh pr view --json title -q .title 2>/dev/null || true)
1038+
```
1039+
1040+
**If GitLab:**
1041+
```bash
1042+
CURRENT_TITLE=$(glab mr view -F json 2>/dev/null | jq -r .title 2>/dev/null || true)
1043+
```
1044+
1045+
If `CURRENT_TITLE` is empty (no open PR/MR), skip with message "No PR/MR found — skipping title sync."
1046+
1047+
3. Compute the corrected title using the shared helper (single source of truth — same one `/ship` uses):
1048+
1049+
```bash
1050+
NEW_TITLE=$(~/.claude/skills/gstack/bin/gstack-pr-title-rewrite.sh "$V" "$CURRENT_TITLE")
1051+
```
1052+
1053+
The helper handles three cases: title already correct (no-op), title has a different `v<X.Y.Z.W>` prefix (replace it), or title has no version prefix (prepend one).
1054+
1055+
4. If `NEW_TITLE` differs from `CURRENT_TITLE`, update it:
1056+
1057+
**If GitHub:**
1058+
```bash
1059+
gh pr edit --title "$NEW_TITLE"
1060+
```
1061+
1062+
**If GitLab:**
1063+
```bash
1064+
glab mr update -t "$NEW_TITLE"
1065+
```
1066+
1067+
5. If the edit command fails: warn "Could not update PR/MR title — documentation changes are still in the commit." and continue. Do not block on title sync failure.
1068+
10211069
**Structured doc health summary (final output):**
10221070

10231071
Output a scannable summary showing every documentation file's status:

document-release/SKILL.md.tmpl

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,54 @@ rm -f /tmp/gstack-pr-body-$$.md
342342
7. If `gh pr edit` / `glab mr update` fails: warn "Could not update PR/MR body — documentation changes are in the
343343
commit." and continue.
344344

345+
**PR/MR title sync (idempotent, always-on):**
346+
347+
PR titles must always start with `v<VERSION>` — same rule as `/ship`. If Step 8 bumped VERSION after `/ship` had already created the PR, the title is now stale. This sub-step fixes it.
348+
349+
1. Read the current VERSION:
350+
351+
```bash
352+
V=$(cat VERSION 2>/dev/null | tr -d '[:space:]')
353+
```
354+
355+
If `VERSION` does not exist or is empty, skip this sub-step entirely.
356+
357+
2. Read the current PR/MR title:
358+
359+
**If GitHub:**
360+
```bash
361+
CURRENT_TITLE=$(gh pr view --json title -q .title 2>/dev/null || true)
362+
```
363+
364+
**If GitLab:**
365+
```bash
366+
CURRENT_TITLE=$(glab mr view -F json 2>/dev/null | jq -r .title 2>/dev/null || true)
367+
```
368+
369+
If `CURRENT_TITLE` is empty (no open PR/MR), skip with message "No PR/MR found — skipping title sync."
370+
371+
3. Compute the corrected title using the shared helper (single source of truth — same one `/ship` uses):
372+
373+
```bash
374+
NEW_TITLE=$(~/.claude/skills/gstack/bin/gstack-pr-title-rewrite.sh "$V" "$CURRENT_TITLE")
375+
```
376+
377+
The helper handles three cases: title already correct (no-op), title has a different `v<X.Y.Z.W>` prefix (replace it), or title has no version prefix (prepend one).
378+
379+
4. If `NEW_TITLE` differs from `CURRENT_TITLE`, update it:
380+
381+
**If GitHub:**
382+
```bash
383+
gh pr edit --title "$NEW_TITLE"
384+
```
385+
386+
**If GitLab:**
387+
```bash
388+
glab mr update -t "$NEW_TITLE"
389+
```
390+
391+
5. If the edit command fails: warn "Could not update PR/MR title — documentation changes are still in the commit." and continue. Do not block on title sync failure.
392+
345393
**Structured doc health summary (final output):**
346394

347395
Output a scannable summary showing every documentation file's status:

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "gstack",
3-
"version": "1.21.1.0",
3+
"version": "1.23.0.0",
44
"description": "Garry's Stack — Claude Code skills + fast headless browser. One repo, one install, entire AI engineering workflow.",
55
"license": "MIT",
66
"type": "module",

ship/SKILL.md

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2760,7 +2760,14 @@ glab mr view -F json 2>/dev/null | jq -r 'if .state == "opened" then "MR_EXISTS"
27602760
27612761
If an **open** PR/MR already exists: **update** the PR body using `gh pr edit --body "..."` (GitHub) or `glab mr update -d "..."` (GitLab). Always regenerate the PR body from scratch using this run's fresh results (test output, coverage audit, review findings, adversarial review, TODOS summary, documentation_section from Step 18). Never reuse stale PR body content from a prior run.
27622762
2763-
**Also update the PR title** if the version changed on rerun. PR titles use the workspace-aware format `v<NEW_VERSION> <type>: <summary>` — version ALWAYS first. If the current title's version prefix doesn't match `NEW_VERSION`, run `gh pr edit --title "v$NEW_VERSION <type>: <summary>"` (or the `glab mr update -t ...` equivalent). This keeps the title truthful when Step 12's queue-drift detection rebumps a stale version. If the title has no `v<X.Y.Z.W>` prefix (a custom title kept intentionally), leave the title alone — only rewrite titles that already follow the format.
2763+
**Always update the PR title to start with `v$NEW_VERSION`.** PR titles use the workspace-aware format `v<NEW_VERSION> <type>: <summary>` — version ALWAYS first, no exceptions, no "custom title kept intentionally" escape hatch. The shared helper `bin/gstack-pr-title-rewrite.sh` is the single source of truth for the rule.
2764+
2765+
1. Read the current title: `CURRENT=$(gh pr view --json title -q .title)` (or `glab mr view -F json | jq -r .title`).
2766+
2. Compute the corrected title: `NEW_TITLE=$(~/.claude/skills/gstack/bin/gstack-pr-title-rewrite.sh "$NEW_VERSION" "$CURRENT")`. The helper handles three cases: title already correct (no-op), title has a different `v<X.Y.Z.W>` prefix (replace it), or title has no version prefix (prepend one).
2767+
3. If `NEW_TITLE` differs from `CURRENT`, run `gh pr edit --title "$NEW_TITLE"` (or `glab mr update -t "$NEW_TITLE"`).
2768+
4. **Self-check:** re-fetch the title and assert it starts with `v$NEW_VERSION `. If it does not, retry the edit once. If still wrong, surface the failure to the user.
2769+
2770+
This keeps the title truthful when Step 12's queue-drift detection rebumps a stale version, and forces the format on PRs that were created without it.
27642771
27652772
Print the existing URL and continue to Step 20.
27662773
@@ -2830,6 +2837,8 @@ you missed it.>
28302837
**If GitHub:**
28312838
28322839
```bash
2840+
# PR title MUST start with v$NEW_VERSION — enforced on every run, no exceptions.
2841+
# (See Step 19 idempotency block + bin/gstack-pr-title-rewrite.sh for the rule.)
28332842
gh pr create --base <base> --title "v$NEW_VERSION <type>: <summary>" --body "$(cat <<'EOF'
28342843
<PR body from above>
28352844
EOF
@@ -2839,6 +2848,8 @@ EOF
28392848
**If GitLab:**
28402849
28412850
```bash
2851+
# MR title MUST start with v$NEW_VERSION — enforced on every run, no exceptions.
2852+
# (See Step 19 idempotency block + bin/gstack-pr-title-rewrite.sh for the rule.)
28422853
glab mr create -b <base> -t "v$NEW_VERSION <type>: <summary>" -d "$(cat <<'EOF'
28432854
<MR body from above>
28442855
EOF

ship/SKILL.md.tmpl

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -794,7 +794,14 @@ glab mr view -F json 2>/dev/null | jq -r 'if .state == "opened" then "MR_EXISTS"
794794

795795
If an **open** PR/MR already exists: **update** the PR body using `gh pr edit --body "..."` (GitHub) or `glab mr update -d "..."` (GitLab). Always regenerate the PR body from scratch using this run's fresh results (test output, coverage audit, review findings, adversarial review, TODOS summary, documentation_section from Step 18). Never reuse stale PR body content from a prior run.
796796

797-
**Also update the PR title** if the version changed on rerun. PR titles use the workspace-aware format `v<NEW_VERSION> <type>: <summary>` — version ALWAYS first. If the current title's version prefix doesn't match `NEW_VERSION`, run `gh pr edit --title "v$NEW_VERSION <type>: <summary>"` (or the `glab mr update -t ...` equivalent). This keeps the title truthful when Step 12's queue-drift detection rebumps a stale version. If the title has no `v<X.Y.Z.W>` prefix (a custom title kept intentionally), leave the title alone — only rewrite titles that already follow the format.
797+
**Always update the PR title to start with `v$NEW_VERSION`.** PR titles use the workspace-aware format `v<NEW_VERSION> <type>: <summary>` — version ALWAYS first, no exceptions, no "custom title kept intentionally" escape hatch. The shared helper `bin/gstack-pr-title-rewrite.sh` is the single source of truth for the rule.
798+
799+
1. Read the current title: `CURRENT=$(gh pr view --json title -q .title)` (or `glab mr view -F json | jq -r .title`).
800+
2. Compute the corrected title: `NEW_TITLE=$(~/.claude/skills/gstack/bin/gstack-pr-title-rewrite.sh "$NEW_VERSION" "$CURRENT")`. The helper handles three cases: title already correct (no-op), title has a different `v<X.Y.Z.W>` prefix (replace it), or title has no version prefix (prepend one).
801+
3. If `NEW_TITLE` differs from `CURRENT`, run `gh pr edit --title "$NEW_TITLE"` (or `glab mr update -t "$NEW_TITLE"`).
802+
4. **Self-check:** re-fetch the title and assert it starts with `v$NEW_VERSION `. If it does not, retry the edit once. If still wrong, surface the failure to the user.
803+
804+
This keeps the title truthful when Step 12's queue-drift detection rebumps a stale version, and forces the format on PRs that were created without it.
798805

799806
Print the existing URL and continue to Step 20.
800807

@@ -864,6 +871,8 @@ you missed it.>
864871
**If GitHub:**
865872

866873
```bash
874+
# PR title MUST start with v$NEW_VERSION — enforced on every run, no exceptions.
875+
# (See Step 19 idempotency block + bin/gstack-pr-title-rewrite.sh for the rule.)
867876
gh pr create --base <base> --title "v$NEW_VERSION <type>: <summary>" --body "$(cat <<'EOF'
868877
<PR body from above>
869878
EOF
@@ -873,6 +882,8 @@ EOF
873882
**If GitLab:**
874883

875884
```bash
885+
# MR title MUST start with v$NEW_VERSION — enforced on every run, no exceptions.
886+
# (See Step 19 idempotency block + bin/gstack-pr-title-rewrite.sh for the rule.)
876887
glab mr create -b <base> -t "v$NEW_VERSION <type>: <summary>" -d "$(cat <<'EOF'
877888
<MR body from above>
878889
EOF

0 commit comments

Comments
 (0)