-
Notifications
You must be signed in to change notification settings - Fork 0
184 lines (168 loc) · 7.38 KB
/
Copy pathtest-android.yml
File metadata and controls
184 lines (168 loc) · 7.38 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
name: Test Android Builds
on:
push:
branches: [main]
# No paths filter on pull_request — required status checks need this workflow to
# always trigger so the aggregator can report. find-projects below narrows the
# matrix to only projects whose subtree changed, so docs-only / other-framework
# PRs produce an empty matrix → build job skipped → aggregator passes via
# `result == 'skipped'`.
pull_request:
schedule:
- cron: "0 9 * * 1"
workflow_dispatch:
permissions:
contents: read
# Needed by find-projects' `gh api .../pulls/N/files` call.
pull-requests: read
jobs:
find-projects:
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.find.outputs.matrix }}
steps:
- uses: actions/checkout@v6
# Default shallow checkout — we only need the working tree for `find`
# below, not git history. The PR's changed files come from gh api.
- id: find
env:
EVENT_NAME: ${{ github.event_name }}
PR_NUMBER: ${{ github.event.pull_request.number }}
WORKFLOW_FILE: .github/workflows/test-android.yml
GH_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
# Discover any sample with an Android Gradle wrapper. Today: react-native
# samples and native android samples.
ALL=$(find samples -name "gradlew" -not -path "*/node_modules/*" -not -path "*/build/*" -exec dirname {} \; 2>/dev/null | sort)
if [ "$EVENT_NAME" = "pull_request" ]; then
CHANGED=$(gh api --paginate "/repos/$GITHUB_REPOSITORY/pulls/$PR_NUMBER/files" --jq '.[].filename' 2>/dev/null || echo "")
if printf '%s\n' "$CHANGED" | grep -qFx "$WORKFLOW_FILE"; then
FILTERED="$ALL"
else
# For each gradlew dir, walk up to find a package.json. If found (an
# RN sample — gradlew sits under <rn-root>/android/), watch the RN
# root: JS dep changes upstairs affect Android autolinking. If not
# found (a native Android sample), watch the gradlew dir itself.
# Mirrors the "Install JS dependencies (RN samples)" step's walk-up.
FILTERED=$(while IFS= read -r proj; do
[ -z "$proj" ] && continue
watch_root="$proj"
d="$proj"
while [ "$d" != "." ] && [ "$d" != "/" ]; do
if [ -f "$d/package.json" ]; then
watch_root="$d"
break
fi
d=$(dirname "$d")
done
if printf '%s\n' "$CHANGED" | grep -q "^${watch_root}/"; then
echo "$proj"
fi
done <<< "$ALL")
fi
else
FILTERED="$ALL"
fi
MATRIX=$(printf '%s\n' "$FILTERED" | jq -R -s -c 'split("\n") | map(select(. != ""))')
echo "matrix=$MATRIX" >> "$GITHUB_OUTPUT"
build:
needs: find-projects
if: ${{ needs.find-projects.outputs.matrix != '[]' }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
android_dir: ${{ fromJson(needs.find-projects.outputs.matrix) }}
steps:
- uses: actions/checkout@v6
- name: Set up JDK 17
uses: actions/setup-java@v5
with:
distribution: "temurin"
java-version: "17"
- name: Set up Android SDK
# The community `android-actions/setup-android` action isn't on the org's
# third-party action allowlist, so we install Android command-line tools
# ourselves. The build number in the cmdline-tools URL is pinned (Google
# publishes new ones periodically; bump intentionally rather than chasing).
env:
ANDROID_HOME: ${{ runner.temp }}/android-sdk
CMDLINE_TOOLS_ZIP: commandlinetools-linux-11076708_latest.zip
# SHA-256 of the build above as published by Google. Bumping the build
# number requires updating this hash; mismatch fails the workflow so we
# never silently run a corrupted/poisoned download.
CMDLINE_TOOLS_SHA256: 2d2d50857e4eb553af5a6dc3ad507a17adf43d115264b1afc116f95c92e5e258
run: |
set -euo pipefail
mkdir -p "$ANDROID_HOME/cmdline-tools"
cd "$ANDROID_HOME/cmdline-tools"
curl -fsSL "https://dl.google.com/android/repository/$CMDLINE_TOOLS_ZIP" -o tools.zip
echo "$CMDLINE_TOOLS_SHA256 tools.zip" | sha256sum -c -
unzip -q tools.zip
mv cmdline-tools latest
rm tools.zip
# Expose for subsequent steps (Gradle reads ANDROID_HOME).
{
echo "ANDROID_HOME=$ANDROID_HOME"
echo "ANDROID_SDK_ROOT=$ANDROID_HOME"
} >> "$GITHUB_ENV"
{
echo "$ANDROID_HOME/cmdline-tools/latest/bin"
echo "$ANDROID_HOME/platform-tools"
} >> "$GITHUB_PATH"
# Accept licenses (sdkmanager errors out otherwise).
printf 'y\n%.0s' $(seq 1 50) | "$ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager" --licenses > /dev/null
"$ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager" \
"platform-tools" "platforms;android-36" "build-tools;36.0.0"
# React Native samples need their JS deps installed first so autolinking
# can resolve native modules from node_modules. Detect by walking up to
# the directory that owns package.json.
- uses: actions/setup-node@v6
with:
node-version: "22"
- name: Enable Corepack
run: corepack enable
- name: Install JS dependencies (RN samples)
run: |
# ${{ matrix.android_dir }} is e.g. "samples/react-native/login-pkce/android".
# Walk up until we find a package.json or hit the repo root.
dir="${{ matrix.android_dir }}"
while [ "$dir" != "." ] && [ "$dir" != "/" ]; do
if [ -f "$dir/package.json" ]; then
echo "Installing JS deps in $dir"
(cd "$dir" && yarn install --immutable)
break
fi
dir=$(dirname "$dir")
done
- name: Generate debug keystore
# The committed sample doesn't ship debug.keystore (gitignored).
# Generate a throwaway one so Gradle's `validateSigningDebug` passes.
run: |
keytool -genkeypair -v \
-keystore "${{ matrix.android_dir }}/app/debug.keystore" \
-storepass android -alias androiddebugkey -keypass android \
-keyalg RSA -keysize 2048 -validity 10000 \
-dname "CN=Android Debug,O=Android,C=US"
- name: Cache Gradle
uses: actions/cache@v5
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: gradle-${{ runner.os }}-${{ hashFiles(format('{0}/gradle/wrapper/gradle-wrapper.properties', matrix.android_dir), format('{0}/build.gradle*', matrix.android_dir), format('{0}/app/build.gradle*', matrix.android_dir)) }}
restore-keys: gradle-${{ runner.os }}-
- name: assembleDebug
working-directory: ${{ matrix.android_dir }}
run: ./gradlew assembleDebug --no-daemon
# Stable aggregator for branch protection.
all-tests-passed:
name: Android tests passed
needs: build
if: always()
runs-on: ubuntu-latest
steps:
- name: Verify build matrix succeeded
if: needs.build.result != 'success' && needs.build.result != 'skipped'
run: exit 1