Skip to content

Commit 578bac0

Browse files
committed
docs(release): add release runbook
- Document the metadata update, version bump, validation, and publishing flow - Add CocoaPods trunk publishing and final verification guidance - Link the release runbook from the README maintenance guides
1 parent 0df8459 commit 578bac0

2 files changed

Lines changed: 207 additions & 0 deletions

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -483,6 +483,7 @@ xcodebuild test -scheme libPhoneNumberShortNumber -destination 'platform=iOS Sim
483483

484484
- [Upstream parity guide](docs/UPSTREAM_PARITY.md)
485485
- [Testing guide](docs/TESTING.md)
486+
- [Release runbook](docs/RELEASE_RUNBOOK.md)
486487
- [Metadata patch policy](docs/METADATA_PATCH_POLICY.md)
487488
- [Metadata update log](docs/METADATA_UPDATE_LOG.md)
488489
- [Package size options](docs/PACKAGE_SIZE_OPTIONS.md)

docs/RELEASE_RUNBOOK.md

Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
# Release Runbook
2+
3+
Use this runbook for metadata updates, version bumps, validation, GitHub releases, and CocoaPods publication. Keep command outputs and upstream refs in the pull request so future releases can audit the release decision from code and logs instead of memory.
4+
5+
## Release Types
6+
7+
- Patch release: bug fixes or metadata-only updates.
8+
- Minor release: additive public API, new modules, or metadata work that also changes public behavior beyond freshness.
9+
- Major release: breaking API or packaging changes.
10+
11+
Metadata-only releases should normally be patch releases. Do not add local metadata overrides unless the requirements in `docs/METADATA_PATCH_POLICY.md` are met.
12+
13+
## Preflight
14+
15+
Start from a clean working tree:
16+
17+
```bash
18+
git status --short
19+
```
20+
21+
Check the current local metadata ref and latest upstream candidate:
22+
23+
```bash
24+
swift scripts/checkMetadataFreshness.swift --output .build/metadata-freshness
25+
```
26+
27+
Review these generated artifacts before deciding scope:
28+
29+
- `.build/metadata-freshness/metadata-diff-summary.md`
30+
- `.build/metadata-freshness/metadata-update-issue.md`
31+
- `.build/metadata-freshness/metadata-update-pr.md`
32+
- `.build/metadata-freshness/metadata-update-log-entry.md`
33+
34+
If the release is for a user-reported numbering-plan issue, add or run a focused regression test that proves the old metadata fails and the new metadata fixes the case.
35+
36+
## Update Metadata
37+
38+
Update main, testing, and short-number metadata:
39+
40+
```bash
41+
swift scripts/metadataGenerator.swift <metadata-ref> --pretty
42+
```
43+
44+
Update geocoding metadata when upstream geocoding resources changed:
45+
46+
```bash
47+
swift scripts/updateGeocodingMetadata.swift <metadata-ref> --replace-bundle
48+
```
49+
50+
Update carrier metadata when upstream carrier resources changed:
51+
52+
```bash
53+
swift scripts/updateCarrierMetadata.swift <metadata-ref> --replace-bundle
54+
```
55+
56+
Update timezone metadata when upstream timezone resources changed:
57+
58+
```bash
59+
swift scripts/updateTimeZonesMetadata.swift <metadata-ref> --replace-bundle
60+
```
61+
62+
Use `--output <dir>` instead of `--replace-bundle` when reviewing generated artifacts before changing checked-in bundles.
63+
64+
## Version Bump
65+
66+
Update all project, podspec, dependency, and README version references:
67+
68+
```bash
69+
swift scripts/updateProjectVersions.swift <new-version>
70+
```
71+
72+
Confirm version alignment:
73+
74+
```bash
75+
swift scripts/checkVersionConsistency.swift
76+
```
77+
78+
## Validation
79+
80+
Run upstream parity checks against the exact metadata ref:
81+
82+
```bash
83+
swift scripts/checkUpstreamTestParity.swift --upstream-ref <metadata-ref>
84+
swift scripts/checkUpstreamAPIParity.swift --upstream-ref <metadata-ref>
85+
```
86+
87+
Run the local SwiftPM baseline:
88+
89+
```bash
90+
swift test
91+
LC_ALL=ko_KR.UTF-8 LANG=ko_KR.UTF-8 swift test
92+
swift build -c release
93+
git diff --check
94+
```
95+
96+
Run the main Xcode schemes:
97+
98+
```bash
99+
xcodebuild test -scheme libPhoneNumber -destination 'platform=iOS Simulator,name=iPhone 16'
100+
xcodebuild test -scheme libPhoneNumberGeocoding -destination 'platform=iOS Simulator,name=iPhone 16'
101+
xcodebuild test -scheme libPhoneNumberShortNumber -destination 'platform=iOS Simulator,name=iPhone 16'
102+
```
103+
104+
If the simulator destination is ambiguous, use a concrete UDID:
105+
106+
```bash
107+
xcodebuild -scheme libPhoneNumber -showdestinations
108+
xcodebuild test -scheme libPhoneNumber -destination 'id=<simulator-udid>'
109+
```
110+
111+
Run CocoaPods lint for every shipped podspec when packaging, dependency, or release metadata changed:
112+
113+
```bash
114+
pod lib lint libPhoneNumber-iOS.podspec --allow-warnings
115+
pod lib lint libPhoneNumberGeocoding.podspec --allow-warnings --include-podspecs='*.podspec'
116+
pod lib lint libPhoneNumberShortNumber.podspec --allow-warnings --include-podspecs='*.podspec'
117+
pod lib lint libPhoneNumberCarrier.podspec --allow-warnings --include-podspecs='*.podspec'
118+
pod lib lint libPhoneNumberTimeZones.podspec --allow-warnings --include-podspecs='*.podspec'
119+
pod lib lint libPhoneNumber-iOS-SwiftCore.podspec --allow-warnings --include-podspecs='*.podspec'
120+
pod lib lint libPhoneNumber-iOS-SwiftGeocoding.podspec --allow-warnings --include-podspecs='*.podspec'
121+
pod lib lint libPhoneNumber-iOS-SwiftShortNumber.podspec --allow-warnings --include-podspecs='*.podspec'
122+
pod lib lint libPhoneNumber-iOS-SwiftCarrier.podspec --allow-warnings --include-podspecs='*.podspec'
123+
pod lib lint libPhoneNumber-iOS-SwiftTimeZones.podspec --allow-warnings --include-podspecs='*.podspec'
124+
pod lib lint libPhoneNumber-iOS-SwiftUI.podspec --allow-warnings --include-podspecs='*.podspec'
125+
pod lib lint libPhoneNumber-iOS-SwiftUIEnrichment.podspec --allow-warnings --include-podspecs='*.podspec'
126+
pod lib lint libPhoneNumber-iOS-Swift.podspec --allow-warnings --include-podspecs='*.podspec'
127+
```
128+
129+
Re-run freshness after the metadata update to confirm the checked-in metadata matches the selected upstream ref:
130+
131+
```bash
132+
swift scripts/checkMetadataFreshness.swift --current-ref <metadata-ref> --output .build/metadata-freshness
133+
```
134+
135+
## Update Release Notes
136+
137+
Update `docs/METADATA_UPDATE_LOG.md` for metadata releases. Include:
138+
139+
- Previous local upstream ref.
140+
- New upstream ref.
141+
- Which metadata families changed.
142+
- Issue-specific verification, when applicable.
143+
- Commands that were run.
144+
- Test, parity, build, lint, and freshness results.
145+
146+
The generated `.build/metadata-freshness/metadata-update-log-entry.md` is a starting point, not a substitute for recording release-specific results.
147+
148+
## Pull Request
149+
150+
Open a pull request that includes:
151+
152+
- Upstream metadata ref or source commit.
153+
- Summary of changed metadata families and behavior impact.
154+
- Links to issue-specific verification, if any.
155+
- Upstream parity results.
156+
- Local validation results.
157+
- CocoaPods lint results when podspecs or packaging are affected.
158+
159+
Do not publish CocoaPods podspecs until the release commit is merged and the GitHub release/tag exists.
160+
161+
## GitHub Release
162+
163+
After merge, create the GitHub release for the new version tag. The tag must match each podspec `s.source` tag and `s.version`.
164+
165+
Before publishing, confirm the version alignment from the release checkout:
166+
167+
```bash
168+
swift scripts/checkVersionConsistency.swift
169+
```
170+
171+
## CocoaPods Publish
172+
173+
Check the dependency-aware publish plan first:
174+
175+
```bash
176+
swift scripts/publishPodspecs.swift
177+
```
178+
179+
Publish missing podspec versions in dependency order:
180+
181+
```bash
182+
swift scripts/publishPodspecs.swift --publish
183+
```
184+
185+
The publish script:
186+
187+
- Discovers all root `*.podspec` files.
188+
- Parses actual podspec dependencies with `pod ipc spec`.
189+
- Orders local podspecs so prerequisites publish before dependents.
190+
- Skips versions that already exist on trunk.
191+
- Checks trunk visibility after every push.
192+
- Treats timeout or server errors as inconclusive until `pod trunk info` confirms whether the version exists.
193+
194+
If CocoaPods trunk returns a timeout or internal server error, do not change podspecs as a workaround. Re-run the script; it will skip versions that became visible and retry only missing versions.
195+
196+
## Final Verification
197+
198+
After publication, run:
199+
200+
```bash
201+
swift scripts/publishPodspecs.swift
202+
```
203+
204+
The release is complete only when every podspec version is reported as present on trunk.
205+
206+
Record any CocoaPods trunk incidents in the release notes or maintenance log when they affected the release process.

0 commit comments

Comments
 (0)