-
Notifications
You must be signed in to change notification settings - Fork 11
171 lines (156 loc) · 8.02 KB
/
publish-example-android.yml
File metadata and controls
171 lines (156 loc) · 8.02 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
# Publish the React Native SDK example app to Google Play Console internal track.
#
# Triggers:
# - workflow_dispatch: Manual publish (preferred — SDK releases don't map 1:1 to example app publishes)
# - release: published: Fires on every SDK release to keep the example app in sync
#
# Required secrets (set in repo Settings → Secrets and variables → Actions):
# GOOGLE_SERVICES_JSON - Contents of google-services.json for Firebase
# SIGNING_KEY - Base64-encoded release keystore
# ALIAS - Key alias in the keystore
# KEY_STORE_PASSWORD - Keystore password
# KEY_PASSWORD - Key password
# SERVICE_ACCOUNT_JSON - Google Play service account JSON (plain text)
# KLAVIYO_EXAMPLE_API_KEY - Klaviyo public API key for the example app build.
# Required: workflow fails early if unset (guard step after checkout).
name: Publish Example App to Play Store Internal Track
on:
workflow_dispatch:
release:
types: [published]
# Temporary: run on every push to this branch so we can iterate on the workflow
# before merge. `workflow_dispatch` only works from the default branch, so this
# is the only way to exercise the pipeline end-to-end against the PR. Remove
# this `push` trigger before merging to master.
push:
branches: [ecm/ci/android-example-play-publish]
jobs:
deploy:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- name: Verify KLAVIYO_EXAMPLE_API_KEY secret is set
run: |
if [ -z "${KLAVIYO_EXAMPLE_API_KEY}" ]; then
echo "::error::KLAVIYO_EXAMPLE_API_KEY secret is not set. The workflow cannot proceed — the build would produce an app that crashes at launch."
exit 1
fi
shell: bash
env:
KLAVIYO_EXAMPLE_API_KEY: ${{ secrets.KLAVIYO_EXAMPLE_API_KEY }}
# Node + Yarn 3 + workspace deps. Required because the React Native Gradle plugin
# invokes the Metro bundler during bundleRelease to generate the JS bundle. Installs
# the example workspace too, making react-native and its CLI available to Gradle.
- name: Setup
uses: ./.github/actions/setup
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
distribution: 'zulu'
java-version: '17'
java-package: jdk
- name: Add Google Services from Secrets
run: 'echo "$GOOGLE_SERVICES_JSON" > ./example/android/app/google-services.json'
shell: bash
env:
GOOGLE_SERVICES_JSON: ${{ secrets.GOOGLE_SERVICES_JSON }}
# Write the Klaviyo public API key into example/.env so react-native-dotenv
# can expose it to the JS layer as KLAVIYO_API_KEY (imported from '@env').
# The guard step above ensures the secret is set before we reach this point.
- name: Write .env with Klaviyo API key
run: echo "KLAVIYO_API_KEY=${KLAVIYO_EXAMPLE_API_KEY}" > example/.env
env:
KLAVIYO_EXAMPLE_API_KEY: ${{ secrets.KLAVIYO_EXAMPLE_API_KEY }}
# Decode the base64-encoded upload keystore from secrets into a file that
# the Gradle signing config can point at. The runner is ephemeral so the
# plaintext .jks is torn down with the VM, but we also remove it at the
# end of the job as hygiene.
- name: Decode upload keystore
run: echo "$SIGNING_KEY" | base64 -d > "${RUNNER_TEMP}/upload.jks"
env:
SIGNING_KEY: ${{ secrets.SIGNING_KEY }}
# bundleRelease triggers react-native bundle automatically via the RN Gradle plugin.
# We cd into the android directory so that relative paths in settings.gradle resolve correctly.
#
# Signing is done inline via `-Pandroid.injected.signing.*` gradle properties so AGP
# produces a properly v2/v3-signed AAB in a single pass — no separate re-sign step,
# no risk of double-signing (Play rejects AABs with multiple signer certificates).
# versionCode is overridden per-run via github.run_number so successive
# CI uploads never collide on Play's strictly-increasing versionCode rule.
# Read in build.gradle as `project.findProperty("versionCode")` — AGP's
# `android.injected.version.code` is an IDE flag and isn't reliably
# honored by command-line Gradle builds.
# Caveat: manual Play uploads that bump versionCode outside CI can get
# ahead of run_number — if that happens, bump CI past the manual number
# (re-trigger the workflow N times, or add an offset).
- name: Assemble Release Bundle
run: |
cd example/android && ./gradlew :app:bundleRelease \
-PreleaseVersionCode=${{ github.run_number }} \
-Pandroid.injected.signing.store.file="${RUNNER_TEMP}/upload.jks" \
-Pandroid.injected.signing.store.password="${KEY_STORE_PASSWORD}" \
-Pandroid.injected.signing.key.alias="${ALIAS}" \
-Pandroid.injected.signing.key.password="${KEY_PASSWORD}"
env:
KEY_STORE_PASSWORD: ${{ secrets.KEY_STORE_PASSWORD }}
KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }}
ALIAS: ${{ secrets.ALIAS }}
# Prevent Metro from trying to start a dev server during the build
CI: true
# `status: draft` — the release lands on the internal track unpublished
# so you can manually promote it in Play Console. Required while the app
# listing itself is still in Draft state (no published version yet);
# flip to `completed` once the listing is fully configured for release.
- name: Deploy to Internal Track
uses: r0adkll/[email protected]
with:
serviceAccountJsonPlainText: ${{ secrets.SERVICE_ACCOUNT_JSON }}
packageName: com.klaviyoreactnativesdkexample
releaseFiles: example/android/app/build/outputs/bundle/release/app-release.aab
track: internal
status: draft
- name: Clean up keystore
if: always()
run: rm -f "${RUNNER_TEMP}/upload.jks"
- name: Notify Slack on success
if: success()
uses: slackapi/[email protected]
with:
webhook: ${{ secrets.SLACK_WEBHOOK_URL }}
webhook-type: incoming-webhook
payload: |
text: "✅ RN SDK Example App published to Play Store internal track"
blocks:
- type: "header"
text:
type: "plain_text"
text: "✅ RN SDK Example App published to Play Store internal track"
- type: "section"
text:
type: "mrkdwn"
text: "*Repository:* ${{ github.repository }}\n*Workflow:* ${{ github.workflow }}\n*Release:* `${{ github.event.release.tag_name || 'manual' }}`\n*Commit:* `${{ github.sha }}`\n*Author:* ${{ github.actor }}"
- type: "section"
text:
type: "mrkdwn"
text: "*Workflow Run:* <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|View Details>"
- name: Notify Slack on failure
if: failure()
uses: slackapi/[email protected]
with:
webhook: ${{ secrets.SLACK_WEBHOOK_URL }}
webhook-type: incoming-webhook
payload: |
text: "🚨 RN SDK Example App Play Store publish failed"
blocks:
- type: "header"
text:
type: "plain_text"
text: "🚨 RN SDK Example App Play Store publish failed"
- type: "section"
text:
type: "mrkdwn"
text: "*Repository:* ${{ github.repository }}\n*Workflow:* ${{ github.workflow }}\n*Release:* `${{ github.event.release.tag_name || 'manual' }}`\n*Commit:* `${{ github.sha }}`\n*Author:* ${{ github.actor }}"
- type: "section"
text:
type: "mrkdwn"
text: "*Workflow Run:* <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|View Details>"