|
| 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