Repository navigation
236 lines (214 loc) 路 10.2 KB
/
Copy pathandroid-store-release.yml
File metadata and controls
236 lines (214 loc) 路 10.2 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
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
name: Android Store Release
run-name: Android ${{ github.event_name == 'schedule' && github.event.schedule == '0 11 * * 1' && 'Store release (weekly)' || (((github.event_name == 'schedule' && github.event.schedule == '0 7 * * *') || inputs.operation == 'internal') && 'Internal testing distribution' || 'Store release') }}
on:
schedule:
- cron: "0 7 * * *"
timezone: America/Los_Angeles
- cron: "0 11 * * 1"
timezone: America/Los_Angeles
workflow_dispatch:
inputs:
operation:
description: Stage a Google Play release or distribute an Internal testing build
required: true
default: release
type: choice
options:
- release
- internal
permissions: {}
concurrency:
group: android-release
cancel-in-progress: false
queue: max
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
NODE_VERSION: "24.21.0"
jobs:
qualify:
if: >-
github.ref == 'refs/heads/main' && github.repository == 'openclaw/openclaw' &&
((github.event_name == 'schedule' && github.event.schedule == '0 11 * * 1') ||
(github.event_name == 'workflow_dispatch' && inputs.operation == 'release'))
permissions:
actions: read
contents: read
uses: ./.github/workflows/android-release-e2e.yml
with:
target_sha: ${{ github.sha }}
release:
name: Prepare and upload Android release
needs: qualify
if: >-
!cancelled() &&
github.ref == 'refs/heads/main' && github.repository == 'openclaw/openclaw' &&
((github.event_name == 'schedule' && github.event.schedule == '0 7 * * *' && vars.ANDROID_INTERNAL_ENABLED == 'true') ||
(github.event_name == 'workflow_dispatch' && inputs.operation == 'internal') ||
(needs.qualify.result == 'success' &&
((github.event_name == 'schedule' && github.event.schedule == '0 11 * * 1') ||
(github.event_name == 'workflow_dispatch' && inputs.operation == 'release'))))
permissions:
contents: write
runs-on: ubuntu-24.04
timeout-minutes: 120
environment: ${{ ((github.event_name == 'schedule' && github.event.schedule == '0 7 * * *') || inputs.operation == 'internal') && 'android-internal' || 'android-store-release' }}
steps:
- name: Checkout release source
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: ${{ github.sha }}
fetch-depth: 0
persist-credentials: false
- name: Verify release source
shell: bash
run: |
set -euo pipefail
test "$(git rev-parse HEAD)" = "$GITHUB_SHA"
- name: Prepare trusted Linux Android tooling
if: >-
(github.event_name == 'schedule' && github.event.schedule == '0 11 * * 1') ||
(github.event_name == 'workflow_dispatch' && inputs.operation == 'release')
shell: bash
run: |
set -euo pipefail
test "$RUNNER_OS/$RUNNER_ARCH" = "Linux/X64"
for executable in /usr/bin/apt-get /usr/bin/sudo /usr/bin/timeout; do
test -x "$executable"
done
apt_source="/etc/apt/sources.list.d/ubuntu.sources"
apt_source_parts="$RUNNER_TEMP/openclaw-android-apt-sourceparts-disabled"
test -s "$apt_source"
if [[ -e "$apt_source_parts" || -L "$apt_source_parts" ]]; then
echo "::error::Task-private APT source-parts path must remain absent"
exit 1
fi
apt_options=(
-o "Dir::Etc::sourcelist=$apt_source"
-o "Dir::Etc::sourceparts=$apt_source_parts"
)
/usr/bin/timeout --signal=TERM --kill-after=10s 300s \
/usr/bin/sudo env DEBIAN_FRONTEND=noninteractive \
/usr/bin/apt-get "${apt_options[@]}" update
/usr/bin/timeout --signal=TERM --kill-after=10s 300s \
/usr/bin/sudo env DEBIAN_FRONTEND=noninteractive \
/usr/bin/apt-get "${apt_options[@]}" install \
-y --no-install-recommends imagemagick
test -x /usr/bin/convert
test -x /usr/bin/identify
tool_dir="$RUNNER_TEMP/openclaw-android-tools"
mkdir -p "$tool_dir"
install -m 700 scripts/android-sips-linux.sh "$tool_dir/android-sips-linux.sh"
- name: Setup Node environment
uses: ./.github/actions/setup-node-env
with:
cache-mode: off
install-bun: "true"
node-version: ${{ env.NODE_VERSION }}
- name: Setup Android toolchain
uses: ./.github/actions/setup-android-toolchain
with:
cache-mode: off
install-screenshot-emulators: ${{ ((github.event_name == 'schedule' && github.event.schedule == '0 11 * * 1') || (github.event_name == 'workflow_dispatch' && inputs.operation == 'release')) && 'true' || 'false' }}
- name: Setup Ruby
uses: ruby/setup-ruby@651ff0d62c5c79bed6d53ec518387aae20e72c1a # v1.329.0
with:
ruby-version: "3.4.11"
bundler: "4.0.22"
bundler-cache: false
working-directory: apps/android
- name: Install locked Fastlane bundle
working-directory: apps/android
run: |
set -euo pipefail
bundle _4.0.22_ install --jobs 4 --retry 3
bundle _4.0.22_ check
test "$(bundle _4.0.22_ exec ruby -e 'require "fastlane"; print Fastlane::VERSION')" = "2.240.1"
- name: Create apps-signing read token
id: apps-signing-token
uses: actions/create-github-app-token@64ab729a6294000f5aa4a4bc0b73d1f32bc45510 # v3.3.0
with:
app-id: "2729701"
private-key: ${{ secrets.GH_APP_PRIVATE_KEY }}
owner: openclaw
repositories: apps-signing
permission-contents: read
- name: Checkout encrypted Android signing assets
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
repository: openclaw/apps-signing
ref: main
path: apps/android/build/release-signing/apps-signing
token: ${{ steps.apps-signing-token.outputs.token }}
persist-credentials: false
- name: Materialize Android release signing
env:
MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
run: node scripts/android-release-signing.mjs --mode materialize
- name: Prepare and upload Android release
env:
GH_TOKEN: ${{ github.token }}
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
ANDROID_RELEASE_DESTINATION: ${{ ((github.event_name == 'schedule' && github.event.schedule == '0 7 * * *') || inputs.operation == 'internal') && 'internal' || 'play-store' }}
GOOGLE_PLAY_JSON_KEY_DATA: ${{ secrets.GOOGLE_PLAY_JSON_KEY_DATA }}
FIREBASE_APP_DISTRIBUTION_JSON_KEY_DATA: ${{ secrets.FIREBASE_APP_DISTRIBUTION_JSON_KEY_DATA }}
FIREBASE_APP_ID: "1:627614795142:android:3daa833ca787ca67959807"
FIREBASE_TESTER_GROUPS: android-daily
GOOGLE_PLAY_PACKAGE_NAME: ai.openclaw.app
GOOGLE_PLAY_RELEASE_STATUS: completed
GOOGLE_PLAY_TRACK: internal
GOOGLE_PLAY_VALIDATE_ONLY: "0"
SIPS: ${{ runner.temp }}/openclaw-android-tools/android-sips-linux.sh
run: |
set -euo pipefail
gh auth setup-git
pnpm android:release:upload -- \
--destination "$ANDROID_RELEASE_DESTINATION" \
--recovery-dir "$RUNNER_TEMP/android-release-recovery"
- name: Remove materialized signing files
if: always()
run: |
rm -rf apps/android/build/release-signing \
"$RUNNER_TEMP/android-release-recovery/source/apps/android/build/release-signing"
- name: Retain release plan and notes
if: always()
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: android-release-recovery-${{ github.run_id }}-${{ github.run_attempt }}
path: |
${{ runner.temp }}/android-release-recovery/release-notes.json
${{ runner.temp }}/android-release-recovery/android-plan.json
${{ runner.temp }}/android-release-recovery/firebase-result.json
if-no-files-found: error
retention-days: 30
- name: Retain screenshot diagnostics
if: >-
always() && ((github.event_name == 'schedule' && github.event.schedule == '0 11 * * 1') ||
(github.event_name == 'workflow_dispatch' && inputs.operation == 'release'))
continue-on-error: true
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: android-release-emulator-diagnostics-${{ github.run_id }}-${{ github.run_attempt }}
path: |
${{ runner.temp }}/android-release-recovery/source/.artifacts/android-screenshots/latest/*/emulator.log
${{ runner.temp }}/android-release-recovery/source/.artifacts/android-screenshots/latest/*/emulator-args.txt
${{ runner.temp }}/android-release-recovery/source/.artifacts/android-screenshots/latest/*/process-status.txt
${{ runner.temp }}/android-release-recovery/source/.artifacts/android-screenshots/latest/*/ui-dumps/openclaw-*.xml
${{ runner.temp }}/android-release-recovery/source/.artifacts/android-screenshots/latest/*/activity-start/openclaw-*.txt
if-no-files-found: ignore
retention-days: 30
- name: Retain signed release artifacts
if: always()
continue-on-error: true
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: android-release-artifacts-${{ github.run_id }}-${{ github.run_attempt }}
path: |
${{ runner.temp }}/android-release-recovery/artifacts/*.aab
${{ runner.temp }}/android-release-recovery/artifacts/*.apk
${{ runner.temp }}/android-release-recovery/artifacts/*.sha256
${{ runner.temp }}/android-release-recovery/source/apps/android/build/release-artifacts/*.aab
${{ runner.temp }}/android-release-recovery/source/apps/android/build/release-artifacts/*.apk
${{ runner.temp }}/android-release-recovery/source/apps/android/build/release-artifacts/*.sha256
if-no-files-found: ignore
compression-level: 0
retention-days: 30