-
Notifications
You must be signed in to change notification settings - Fork 14
201 lines (178 loc) · 8.84 KB
/
Copy pathpublish-shared-core.yml
File metadata and controls
201 lines (178 loc) · 8.84 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
name: Publish SharedCore
# Cuts a release of the `:kmp:shared-core` XCFramework into
# code-payments/flipcash-shared-core-spm, which is the repo iOS depends on. The
# Kotlin stays here; that repo only ever holds the generated `Package.swift` and
# the release assets it points at.
on:
workflow_dispatch:
inputs:
version:
description: 'Version to publish, e.g. 0.1.0 — also the Swift Package tag'
required: true
summary:
description: 'Optional lede for the release notes. The changelog below it is generated either way.'
required: false
type: string
concurrency:
# Two publishes at once would race on the same tag and release.
group: publish-shared-core
cancel-in-progress: false
env:
CI: true
SPM_REPO: code-payments/flipcash-shared-core-spm
jobs:
publish:
name: Publish SharedCore ${{ inputs.version }}
# `contents: write` is for this repo's `shared-core/*` tag; the Swift Package
# repo is reached with the PAT below, not with GITHUB_TOKEN.
permissions:
contents: write
# Apple targets and `swift package compute-checksum` both need Xcode, so this
# lane can't share the Ubuntu runners the rest of CI uses.
runs-on: macos-15
steps:
# The release notes are a `git log` between this publish and the previous
# `shared-core/*` tag, so this lane needs history and tags rather than the
# single commit a build would want.
- uses: actions/checkout@v4
with:
fetch-depth: 0
fetch-tags: true
- name: Validate Gradle wrapper
uses: gradle/actions/wrapper-validation@v4
- name: Setup Java env
uses: actions/setup-java@v3
with:
java-version: '21'
distribution: 'corretto'
cache: 'gradle'
# A fine-grained PAT with Contents: read & write on the Swift Package repo.
# The job's own GITHUB_TOKEN can't reach another repository, and a deploy
# key can only push git — it can't create the GitHub release the
# XCFramework is uploaded to — so one PAT covers both halves.
- name: Check out the Swift Package repo
uses: actions/checkout@v4
with:
repository: ${{ env.SPM_REPO }}
path: spm-repo
token: ${{ secrets.SHARED_CORE_PUBLISH_TOKEN }}
# Gradle configures every project in the build, and the Android app applies the
# secrets plugin, which fails configuration outright when `local.properties` is
# absent. This lane only builds the KMP module — nothing here compiles the app or
# talks to any of these services — so obviously-fake values are enough to get
# through configuration without handing this workflow the real secrets.
- name: Write placeholder local.properties
run: |
set -euo pipefail
{
echo 'BUGSNAG_API_KEY="00000000000000000000000000000000"'
echo 'GOOGLE_CLOUD_PROJECT_NUMBER=000000000000'
echo 'MIXPANEL_API_KEY="00000000000000000000000000000000"'
echo 'COINBASE_ONRAMP_API_KEY=00000000-0000-0000-0000-000000000000'
} > ./local.properties
# The Swift half of the package lives here, next to the Kotlin it wraps, so the
# two move in one commit; the Swift Package repo is a publish target, not a place
# to edit. `Package.swift` has to be in place before Gradle runs, since KMMBridge
# only rewrites the variables block inside it.
- name: Stage the Swift package sources
run: |
set -euo pipefail
rm -rf spm-repo/Sources spm-repo/Tests
cp -R kmp/shared-core/spm/Package.swift kmp/shared-core/spm/Sources kmp/shared-core/spm/Tests spm-repo/
- name: Build the XCFramework, upload it, and update Package.swift
env:
# Gradle reads ORG_GRADLE_PROJECT_-prefixed vars as project properties,
# which keeps the token out of the command line.
ORG_GRADLE_PROJECT_GITHUB_PUBLISH_TOKEN: ${{ secrets.SHARED_CORE_PUBLISH_TOKEN }}
run: |
./gradlew :kmp:shared-core:kmmBridgePublish \
-PENABLE_PUBLISHING=true \
-PsharedCoreVersion=${{ inputs.version }} \
-PspmRepoDir=$GITHUB_WORKSPACE/spm-repo
# KMMBridge points the binary target at the release asset's *API* URL, which
# serves private repos but is rate limited to 60 requests an hour per IP for
# anyone unauthenticated. This repo is public, so the plain download URL fetches
# the same bytes with no limit and no credentials -- without this, a developer or
# a CI runner that has spent its anonymous quota fails to resolve the package.
- name: Point the binary target at the unauthenticated download URL
working-directory: spm-repo
run: |
set -euo pipefail
download="https://github.com/${SPM_REPO}/releases/download/${{ inputs.version }}/SharedCore.xcframework.zip"
perl -pi -e 's{^let remoteKotlinUrl = ".*"$}{let remoteKotlinUrl = "'"$download"'"}' Package.swift
grep -q "$download" Package.swift
curl -fsSLI "$download" > /dev/null
# The release asset is up by now but the tag still points at the old
# Package.swift, so nothing consumes this build until the next step. Compiling
# the Swift glue against the framework we just uploaded is the last moment a
# mismatch between the two is cheap to fix — after the tag moves, it's a
# published-and-broken version.
- name: Verify the package builds against the uploaded framework
working-directory: spm-repo
run: |
set -euo pipefail
xcodebuild -scheme SharedCore \
-destination 'generic/platform=iOS Simulator' \
-clonedSourcePackagesDirPath "$RUNNER_TEMP/spm-verify" \
-quiet \
build
- name: Commit and tag the Swift Package
working-directory: spm-repo
run: |
set -euo pipefail
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add -A Package.swift Sources Tests
if git diff --cached --quiet; then
echo "Nothing to commit — the upload produced the same URL and checksum, and the Swift sources are unchanged."
exit 1
fi
git commit -m "SharedCore ${{ inputs.version }}"
git push origin HEAD:main
# The release upload already created this tag, pointing at whatever
# main was before the commit above — i.e. at a Package.swift that
# doesn't mention this release. Move it onto the commit that does, or
# SPM resolves the version to the previous binary.
git tag -f "${{ inputs.version }}"
git push -f origin "${{ inputs.version }}"
# The Swift Package repo has no commits of its own to describe — it holds a
# generated `Package.swift` and the zip it points at — so the notes are
# derived here, from the range between this publish and the last one.
- name: Write the release notes
env:
GH_TOKEN: ${{ secrets.SHARED_CORE_PUBLISH_TOKEN }}
SUMMARY: ${{ inputs.summary }}
run: |
set -euo pipefail
checksum=$(sed -n 's/^let remoteKotlinChecksum = "\(.*\)"$/\1/p' spm-repo/Package.swift)
summary_arg=()
if [ -n "$SUMMARY" ]; then
printf '%s\n' "$SUMMARY" > "$RUNNER_TEMP/summary.md"
summary_arg=(--summary-file "$RUNNER_TEMP/summary.md")
fi
bash scripts/shared-core-release-notes.sh "${{ inputs.version }}" \
--source "$GITHUB_SHA" \
--checksum "$checksum" \
"${summary_arg[@]+"${summary_arg[@]}"}" > "$RUNNER_TEMP/notes.md"
cat "$RUNNER_TEMP/notes.md"
gh release edit "${{ inputs.version }}" \
--repo "$SPM_REPO" \
--title "SharedCore ${{ inputs.version }}" \
--notes-file "$RUNNER_TEMP/notes.md"
# Nothing else records which Kotlin a published framework was built from, and
# without that the next release has no range to generate its notes over. The
# tag is created last so a failed publish doesn't claim a version.
- name: Tag the source commit
run: |
set -euo pipefail
git tag "shared-core/${{ inputs.version }}" "$GITHUB_SHA"
git push origin "shared-core/${{ inputs.version }}"
- name: Summary
run: |
{
echo "### SharedCore ${{ inputs.version }} published"
echo
echo "- Release: https://github.com/${SPM_REPO}/releases/tag/${{ inputs.version }}"
echo '- Consume: `.package(url: "https://github.com/'"${SPM_REPO}"'", from: "${{ inputs.version }}")`'
echo "- Built from \`${GITHUB_SHA}\`, tagged \`shared-core/${{ inputs.version }}\`"
} >> "$GITHUB_STEP_SUMMARY"