From bf2ffd8690ec38a8443e8553e4a3d08b242c06a6 Mon Sep 17 00:00:00 2001 From: Sjoerd-Bo3 Date: Thu, 25 Jun 2026 06:02:33 +0000 Subject: [PATCH] Add Xcode Cloud TestFlight What-to-Test notes generation ci_scripts/ci_post_xcodebuild.sh writes TestFlight/WhatToTest.en-US.txt on each distribution build: branch, build number, an optional manual message (ci_scripts/whattotest_message.txt), and a tidied, cumulative list of every feature/PR the branch adds on top of its base (default dev, via WHATTOTEST_BASE_BRANCH). Generated notes are git-ignored. CLAUDE.md documents the convention so merge/PR subjects stay TestFlight-readable. Self-contained and branch-agnostic so it can be merged/cherry-picked into any build branch. --- .gitignore | 4 +- CLAUDE.md | 28 +++++++++++ ci_scripts/ci_post_xcodebuild.sh | 83 ++++++++++++++++++++++++++++++++ 3 files changed, 114 insertions(+), 1 deletion(-) create mode 100644 CLAUDE.md create mode 100755 ci_scripts/ci_post_xcodebuild.sh diff --git a/.gitignore b/.gitignore index 50d364dbc78..46c1e95c772 100644 --- a/.gitignore +++ b/.gitignore @@ -79,4 +79,6 @@ fastlane/screenshots fastlane/test_output fastlane/FastlaneRunner -ConfigOverride.xcconfig \ No newline at end of file +ConfigOverride.xcconfig +# Xcode Cloud TestFlight "What to Test" notes (generated by ci_scripts/ci_post_xcodebuild.sh) +TestFlight/ diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 00000000000..71dfb570d7f --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,28 @@ +# Repository guidance for Claude + +## TestFlight "What to Test" notes (Xcode Cloud) + +`ci_scripts/ci_post_xcodebuild.sh` runs after every Xcode Cloud archive and +generates `TestFlight/WhatToTest.en-US.txt`, which Xcode Cloud uses as the +build's **"What to Test"** notes. The change list is built automatically from +the branch's **first-parent commit subjects** since its base branch (default +`dev`), with merge subjects tidied (e.g. `Merge nightscout/Trio PR #1203 (...)` +→ `PR #1203 — ...`). + +**Because the notes are auto-generated from commit/merge subjects, write clear, +user-facing subject lines:** + +- Feature/fix commits: a short imperative summary of the user-visible change, + e.g. `Allow override percentage down to 10%`, not `wip` / `fixup`. +- When merging a branch or PR, give the merge commit a descriptive subject, + e.g. `Merge: ` or keep the upstream `PR #NNNN ()` form. +- Avoid noisy internal merges in the first-parent history where possible + (e.g. repeated `Merge branch 'dev'` syncs) — the script filters the obvious + ones, but clean history keeps the notes readable. + +**Manual note for a specific build:** put text in +`ci_scripts/whattotest_message.txt`; it is prepended above the auto change list. +The generated `TestFlight/` folder is git-ignored. + +To change the base branch the notes diff against, set `WHATTOTEST_BASE_BRANCH` +(default `dev`) as an Xcode Cloud environment variable. diff --git a/ci_scripts/ci_post_xcodebuild.sh b/ci_scripts/ci_post_xcodebuild.sh new file mode 100755 index 00000000000..f62b99e50ac --- /dev/null +++ b/ci_scripts/ci_post_xcodebuild.sh @@ -0,0 +1,83 @@ +#!/bin/sh + +# ci_post_xcodebuild.sh +# +# Xcode Cloud runs this after the build. For distribution builds (a signed app +# exists) it writes the TestFlight "What to Test" notes so every build is +# self-documenting: the branch, the build number, an optional manual message, +# and a cumulative, tidied list of everything this branch adds on top of its +# base branch (default: dev) — i.e. the features/PRs included in this build. +# +# Xcode Cloud picks up TestFlight/WhatToTest..txt from the repo root. +# +# To add a manual note for a build, put text in ci_scripts/whattotest_message.txt +# (it is prepended above the auto-generated change list). The change list stays +# automatic, so good merge/PR subject lines keep these notes readable — see +# CLAUDE.md ("TestFlight What-to-Test notes"). + +set -e + +# Only act on distribution builds (a signed app exists). +if [ -z "$CI_APP_STORE_SIGNED_APP_PATH" ]; then + echo "No signed app (not a distribution build) — skipping What to Test notes." + exit 0 +fi + +REPO="${CI_PRIMARY_REPOSITORY_PATH:-$(cd "$(dirname "$0")/.." && pwd)}" +NOTES_DIR="$REPO/TestFlight" +NOTES_FILE="$NOTES_DIR/WhatToTest.en-US.txt" +MESSAGE_FILE="$REPO/ci_scripts/whattotest_message.txt" + +BASE_BRANCH="${WHATTOTEST_BASE_BRANCH:-dev}" # diff this branch against here +MAX_LINES="${WHATTOTEST_MAX_LINES:-30}" # keep notes under TestFlight's limit + +mkdir -p "$NOTES_DIR" + +BRANCH="${CI_BRANCH:-$(git -C "$REPO" rev-parse --abbrev-ref HEAD 2>/dev/null)}" +SHORT_SHA="$(git -C "$REPO" rev-parse --short HEAD 2>/dev/null)" + +# Xcode Cloud uses a shallow clone; get enough history to find the merge-base. +git -C "$REPO" fetch --unshallow origin >/dev/null 2>&1 \ + || git -C "$REPO" fetch origin >/dev/null 2>&1 || true +git -C "$REPO" fetch origin "$BASE_BRANCH" >/dev/null 2>&1 || true +BASE="$(git -C "$REPO" merge-base HEAD "origin/$BASE_BRANCH" 2>/dev/null || true)" + +# Collapse first-parent history to one tidy line per feature/PR. +tidy_changes() { + range="$1" + git -C "$REPO" log --first-parent --pretty=format:'%s' $range 2>/dev/null \ + | grep -vE "^Merge (branch|remote-tracking branch) '(origin/)?(dev|${BASE_BRANCH})'" \ + | sed -E \ + -e "s|^Merge [^ ]+/[^ ]+ PR #([0-9]+) \((.*)\) into .*|PR #\1 — \2|" \ + -e "s|^Merge [^ ]+/[^ ]+ PR #([0-9]+) into .*|PR #\1|" \ + -e "s|^Merge remote-tracking branch 'origin/(.*)' into .*|\1|" \ + -e "s|^Merge branch '(.*)' into .*|\1|" \ + -e "s| into ${BRANCH}\$||" \ + -e "s|^Merge ||" \ + -e "s|^claude/||" \ + | sed -E 's/^/- /' \ + | head -n "$MAX_LINES" +} + +{ + echo "Branch: ${BRANCH:-unknown}" + echo "Build: ${CI_BUILD_NUMBER:-?} (${SHORT_SHA:-?})" + echo "" + + if [ -f "$MESSAGE_FILE" ] && [ -s "$MESSAGE_FILE" ]; then + cat "$MESSAGE_FILE" + echo "" + fi + + if [ -n "$BASE" ] && [ "$BASE" != "$(git -C "$REPO" rev-parse HEAD)" ]; then + echo "Included in this build (vs ${BASE_BRANCH}):" + tidy_changes "${BASE}..HEAD" + else + echo "Recent changes:" + tidy_changes "-n ${MAX_LINES}" + fi + echo "" +} > "$NOTES_FILE" + +echo "Wrote What to Test notes to $NOTES_FILE:" +cat "$NOTES_FILE"