@@ -64,13 +64,29 @@ jobs:
6464 if : ${{ inputs.runner_provider == 'namespace' }}
6565 uses : namespacelabs/nscloud-cache-action@15799a6b54e5765f85b2aac25b3f0df43ed571c0 # v1
6666 with :
67+ cache : |
68+ gradle
69+ maven
6770 path : |
6871 ~/.cache/yarn
6972 .metamask
7073 node_modules
7174 .yarn/cache
7275 ${{ env.GRADLE_USER_HOME }}/caches
7376 ${{ env.GRADLE_USER_HOME }}/wrapper
77+ ${{ env.GRADLE_USER_HOME }}/apk-cache
78+
79+ - name : Configure Gradle remote build cache
80+ if : ${{ inputs.runner_provider == 'namespace' }}
81+ run : |
82+ mkdir -p "$GRADLE_USER_HOME/init.d"
83+ REF="${GITHUB_REF_NAME}"
84+ PUSH=true
85+ if [[ "$REF" != "main" && "$REF" != release/* && "$REF" != stable/* ]]; then
86+ PUSH=false
87+ fi
88+ nsc cache gradle setup --push="$PUSH" --init-gradle "$GRADLE_USER_HOME/init.d/namespace-cache.init.gradle"
89+ echo "Gradle remote build cache configured (push=$PUSH) at $GRADLE_USER_HOME/init.d/namespace-cache.init.gradle"
7490
7591 - name : Report source fingerprint
7692 run : |
@@ -102,6 +118,50 @@ jobs:
102118 exit 1
103119 fi
104120
121+ - name : Check Namespace E2E APK cache
122+ id : namespace-apk-cache
123+ if : ${{ inputs.runner_provider == 'namespace' && steps.force-builds.outputs.force != 'true' && inputs.source-fingerprint != '' }}
124+ shell : bash
125+ env :
126+ APK_TARGET : ${{ steps.determine-target-paths.outputs.apk-target-path }}
127+ TEST_APK_TARGET : ${{ steps.determine-target-paths.outputs.test-apk-target-path }}
128+ ARTIFACT_NAME : ${{ steps.determine-target-paths.outputs.artifact_name }}
129+ FINGERPRINT : ${{ inputs.source-fingerprint }}
130+ CACHE_GENERATION : ${{ env.CACHE_GENERATION }}
131+ GRADLE_FILES_HASH : ${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
132+ REF_NAME : ${{ github.ref_name }}
133+ BUILD_TYPE : ${{ inputs.build_type }}
134+ run : |
135+ MARKER="${GRADLE_USER_HOME}/apk-cache/.e2e-apk-cache-marker"
136+ APK_CACHED="${GRADLE_USER_HOME}/apk-cache/${ARTIFACT_NAME}.apk"
137+ TEST_APK_CACHED="${GRADLE_USER_HOME}/apk-cache/${ARTIFACT_NAME}-androidTest.apk"
138+ EXPECTED="${REF_NAME}"$'\n'"${BUILD_TYPE}"$'\n'"${CACHE_GENERATION}"$'\n'"${FINGERPRINT}"$'\n'"${GRADLE_FILES_HASH}"
139+ echo "--- Debug: APK cache marker diagnostics ---"
140+ echo "MARKER=$MARKER"
141+ echo "APK_CACHED=$APK_CACHED"
142+ echo "TEST_APK_CACHED=$TEST_APK_CACHED"
143+ echo "marker exists: $([[ -f "${MARKER}" ]] && echo yes || echo NO)"
144+ echo "apk exists: $([[ -f "${APK_CACHED}" ]] && echo yes || echo NO)"
145+ echo "test-apk exists: $([[ -f "${TEST_APK_CACHED}" ]] && echo yes || echo NO)"
146+ ls -la "${GRADLE_USER_HOME}/apk-cache/" 2>&1 || echo "apk-cache dir not found"
147+ if [[ -f "${MARKER}" ]]; then
148+ echo "--- marker contents ---"
149+ cat "${MARKER}"
150+ echo "--- expected ---"
151+ echo "${EXPECTED}"
152+ echo "--- match: $([[ "$(<"${MARKER}")" == "${EXPECTED}" ]] && echo YES || echo NO) ---"
153+ fi
154+ if [[ -f "${MARKER}" ]] && [[ -f "${APK_CACHED}" ]] && [[ -f "${TEST_APK_CACHED}" ]] && [[ "$(<"${MARKER}")" == "${EXPECTED}" ]]; then
155+ echo "cache-hit=true" >> "${GITHUB_OUTPUT}"
156+ echo "Namespace APK cache hit — restoring APKs to build output dirs."
157+ mkdir -p "${APK_TARGET}" "${TEST_APK_TARGET}"
158+ cp "${APK_CACHED}" "${APK_TARGET}/"
159+ cp "${TEST_APK_CACHED}" "${TEST_APK_TARGET}/"
160+ else
161+ echo "cache-hit=false" >> "${GITHUB_OUTPUT}"
162+ echo "Namespace APK cache miss — full build required."
163+ fi
164+
105165 - name : Find reusable build from prior run
106166 id : find-reusable-build
107167 if : ${{ inputs.runner_provider != 'namespace' && steps.force-builds.outputs.force != 'true' && inputs.source-fingerprint != '' }}
@@ -167,7 +227,10 @@ jobs:
167227 - name : Compute native-build gate
168228 id : gate
169229 run : |
170- if [[ "${{ steps.find-reusable-build.outputs.found }}" == "true" \
230+ if [[ "${{ steps.namespace-apk-cache.outputs.cache-hit }}" == "true" ]]; then
231+ echo "needs-native-build=false" >> "$GITHUB_OUTPUT"
232+ echo "Namespace APK cache hit; heavy Android setup + Gradle restore will be skipped."
233+ elif [[ "${{ steps.find-reusable-build.outputs.found }}" == "true" \
171234 && "${{ steps.download-reusable-apk.outcome }}" == "success" \
172235 && "${{ steps.download-reusable-test-apk.outcome }}" == "success" ]]; then
173236 echo "needs-native-build=false" >> "$GITHUB_OUTPUT"
@@ -315,6 +378,27 @@ jobs:
315378 MM_INFURA_PROJECT_ID : ${{ secrets.MM_INFURA_PROJECT_ID }}
316379 MM_PREDICT_GTM_MODAL_ENABLED : ' false'
317380
381+ - name : Record Namespace E2E APK cache marker
382+ if : ${{ inputs.runner_provider == 'namespace' && steps.gate.outputs.needs-native-build == 'true' && inputs.source-fingerprint != '' }}
383+ shell : bash
384+ env :
385+ APK_SOURCE : ${{ steps.determine-target-paths.outputs.apk-target-path }}/${{ steps.determine-target-paths.outputs.artifact_name }}.apk
386+ TEST_APK_SOURCE : ${{ steps.determine-target-paths.outputs.test-apk-target-path }}/${{ steps.determine-target-paths.outputs.artifact_name }}-androidTest.apk
387+ ARTIFACT_NAME : ${{ steps.determine-target-paths.outputs.artifact_name }}
388+ FINGERPRINT : ${{ inputs.source-fingerprint }}
389+ CACHE_GENERATION : ${{ env.CACHE_GENERATION }}
390+ GRADLE_FILES_HASH : ${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
391+ REF_NAME : ${{ github.ref_name }}
392+ BUILD_TYPE : ${{ inputs.build_type }}
393+ run : |
394+ CACHE_DIR="${GRADLE_USER_HOME}/apk-cache"
395+ mkdir -p "${CACHE_DIR}"
396+ cp "${APK_SOURCE}" "${CACHE_DIR}/${ARTIFACT_NAME}.apk"
397+ cp "${TEST_APK_SOURCE}" "${CACHE_DIR}/${ARTIFACT_NAME}-androidTest.apk"
398+ EXPECTED="${REF_NAME}"$'\n'"${BUILD_TYPE}"$'\n'"${CACHE_GENERATION}"$'\n'"${FINGERPRINT}"$'\n'"${GRADLE_FILES_HASH}"
399+ printf '%s\n' "${EXPECTED}" > "${CACHE_DIR}/.e2e-apk-cache-marker"
400+ echo "Namespace APK cache marker + APKs written to ${CACHE_DIR}."
401+
318402 - name : Repack APK with JS updates using @expo/repack-app
319403 if : ${{ steps.gate.outputs.needs-native-build != 'true' }}
320404 run : |
0 commit comments