Skip to content

chore: move Android+iOS native builds from CI to a local pre-push gate - #608

Merged
alichherawalla merged 2 commits into
mainfrom
chore/drop-android-build-ci
Jul 24, 2026
Merged

chore: move Android+iOS native builds from CI to a local pre-push gate#608
alichherawalla merged 2 commits into
mainfrom
chore/drop-android-build-ci

Conversation

@alichherawalla

@alichherawalla alichherawalla commented Jul 24, 2026

Copy link
Copy Markdown
Collaborator

What

Relocates the native build gate from CI to a local pre-push hook.

  1. Removes the android-build job from .github/workflows/ci.yml.
  2. Adds both native builds to .husky/pre-push, scoped so they only run when relevant files change:
    • Android./gradlew assembleDebug assembleRelease when .kt/.kts, android/, or package*.json change.
    • iOS — simulator build (CODE_SIGNING_ALLOWED=NO, no signing prompts) when .swift, ios/, or Podfile change.
    • JS-only / docs pushes skip both and stay fast.

Why

The hosted android-build runner repeatedly hung for 3+ hours on the native C++ builds (react-native-audio-api, op-sqlite), blocking merges and burning CI hours for zero signal (it passed whenever it didn't hang). It even blocked a docs-only PR. Building locally on push catches native/gradle/pods breakage before it ever reaches the remote, without the flaky hosted runner.

lint, typecheck, test, architecture, SonarCloud and CodeRabbit remain in CI.

Summary by CodeRabbit

  • Chores
    • Removed Android native build execution from the hosted CI workflow.
    • Documented that native Android builds are enforced locally as a pre-merge gate, including the recommended debug/release Gradle commands.
    • Updated the pre-push checks to include local native build gates for both Android and iOS when relevant native files are changed (skipping unnecessary runs for docs-only and JavaScript-only changes).

…tead

The hosted android-build runner repeatedly hung for 3+ hours on the native C++ builds
(react-native-audio-api, op-sqlite) and burned hours per PR. Move it to a LOCAL pre-merge
gate: `cd android && ./gradlew assembleDebug assembleRelease` before merging any native/
Android/gradle/deps change (recorded in rules.md). JS-only / docs PRs don't need it.
@qodo-code-review

Copy link
Copy Markdown

ⓘ Qodo reviews are paused because your trial has ended. Ask your workspace admin to add credits to resume reviews. Manage billing

@coderabbitai

coderabbitai Bot commented Jul 24, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The hosted Android CI job is replaced with local pre-push native build gates. Changed Android and iOS files trigger their respective local builds, while the workflow documents the Android command and exceptions for docs-only and JS-only changes.

Changes

Native Build Gates

Layer / File(s) Summary
Native change detection
.husky/pre-push
Adds Android and iOS changed-file selectors that exclude generated build directories and iOS Pods.
Local native build execution
.husky/pre-push
Runs Android assembleDebug and assembleRelease builds, plus an unsigned iOS simulator Debug build, when matching native changes are detected.
Local Android validation guidance
.github/workflows/ci.yml
Removes the hosted android-build job and documents the local Gradle command and docs-only or JS-only exceptions.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Developer
  participant PrePushHook
  participant NativeBuildTools
  Developer->>PrePushHook: push changes
  PrePushHook->>PrePushHook: detect Android and iOS native paths
  PrePushHook->>NativeBuildTools: run matching local native builds
  NativeBuildTools-->>Developer: report build result
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly summarizes the main change: moving native build gates from CI to a local pre-push hook.
Description check ✅ Passed The description covers what changed and why, and it aligns with the template's core Summary/Type intent despite some optional sections being omitted.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/drop-android-build-ci

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/ci.yml:
- Around line 203-207: Revise the comment near the removed Android assemble job
to state specifically that the Android assemble build is not run in CI, while
acknowledging that the test job still installs the NDK and runs
:app:testDebugUnitTest. Keep the local pre-merge assemble commands and scope
guidance unchanged.
- Around line 203-207: Update the Android CI note near the workflow comments to
remove stale references to rules.md and the unverified Gradle command, or
replace them with a real, discoverable pre-merge process and exact
repository-supported gate command. Preserve the stated exceptions only if they
match the documented process.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 5faa584f-75c7-4667-a314-63bbeb2d9a02

📥 Commits

Reviewing files that changed from the base of the PR and between c1d0599 and 9eccc66.

📒 Files selected for processing (1)
  • .github/workflows/ci.yml

Comment thread .github/workflows/ci.yml
Comment on lines +203 to +207
# NOTE: the Android build is NOT run in CI — it is a LOCAL pre-merge gate instead (the hosted
# runner repeatedly hung for 3+ hours on the native C++ builds and burned hours). Run it locally
# before merging any change that touches native/Android/gradle/deps:
# cd android && ./gradlew assembleDebug assembleRelease
# (see rules.md → On-device testing & verification). Docs-only / JS-only PRs don't need it.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Narrow “Android build is NOT run in CI” to the removed assemble job.

The test job still installs the Android NDK and runs :app:testDebugUnitTest at Line [168]. As written, this note may imply that CI performs no Android validation at all.

Proposed wording
-  # NOTE: the Android build is NOT run in CI — it is a LOCAL pre-merge gate instead (the hosted
+  # NOTE: the hosted assembleDebug/assembleRelease Android build job is NOT run in CI; Android
+  # unit tests still run in the `test` job above. The full build is a LOCAL pre-merge gate (the hosted
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
# NOTE: the Android build is NOT run in CI — it is a LOCAL pre-merge gate instead (the hosted
# runner repeatedly hung for 3+ hours on the native C++ builds and burned hours). Run it locally
# before merging any change that touches native/Android/gradle/deps:
# cd android && ./gradlew assembleDebug assembleRelease
# (see rules.md → On-device testing & verification). Docs-only / JS-only PRs don't need it.
# NOTE: the hosted assembleDebug/assembleRelease Android build job is NOT run in CI; Android
# unit tests still run in the `test` job above. The full build is a LOCAL pre-merge gate (the hosted
# runner repeatedly hung for 3+ hours on the native C++ builds and burned hours). Run it locally
# before merging any change that touches native/Android/gradle/deps:
# cd android && ./gradlew assembleDebug assembleRelease
# (see rules.md → On-device testing & verification). Docs-only / JS-only PRs don't need it.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/ci.yml around lines 203 - 207, Revise the comment near the
removed Android assemble job to state specifically that the Android assemble
build is not run in CI, while acknowledging that the test job still installs the
NDK and runs :app:testDebugUnitTest. Keep the local pre-merge assemble commands
and scope guidance unchanged.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail
test -f rules.md
rg -n -F 'cd android && ./gradlew assembleDebug assembleRelease' rules.md
rg -n -i 'On-device testing|docs-only|JS-only|native|Android|Gradle|depend' rules.md

Repository: off-grid-ai/OGAM

Length of output: 154


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

printf 'Tracked candidate files:\n'
git ls-files | rg '(^|/)rules\.md$|(^|/)ci\.yml$|(^|/)github/workflows/.*\.ya?ml$' || true

printf '\nSearch exact command:\n'
rg -n -F 'cd android && ./gradlew assembleDebug assembleRelease' || true

printf '\nSearch nearby terms:\n'
rg -n -i 'assembleDebug|assembleRelease|On-device testing|on-device testing|docs-only|js-only|JS-only|native|Android|gradle|dependenc' . || true

Repository: off-grid-ai/OGAM

Length of output: 227


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

printf 'rules.md present in working tree and tracked files:\n'
test -f rules.md && echo "rules.md exists" || echo "rules.md does not exist"
git ls-tree -r HEAD --name-only | rg '(^|/)rules\.md$|(^|/)ci\.ya?ml$|^\.github/workflows/' || true

printf '\nExact command across repository:\n'
rg -n -F 'cd android && ./gradlew assembleDebug assembleRelease' || true

printf '\nAll ./gradlew/assemble references:\n'
rg -n -E '\./gradlew|assembleDebug|assembleRelease|On-device|docs-only|JS-only|js-only|gradle|dependenc' . --glob '!node_modules/**' --glob '!dist/**' --glob '!build/**' || true

printf '\ndotgithub workflow relevant sections if present:\n'
if [ -f .github/workflows/ci.yml ]; then
  wc -l .github/workflows/ci.yml
  sed -n '180,220p' .github/workflows/ci.yml
fi

Repository: off-grid-ai/OGAM

Length of output: 427


Remove or fix the stale references.

rules.md is not present, and the referenced cd android && ./gradlew assembleDebug assembleRelease command is not in the repository. Keep the comment only if the exact gate command and exceptions are added to rules.md; otherwise, update it to a real, discoverable pre-merge process.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/ci.yml around lines 203 - 207, Update the Android CI note
near the workflow comments to remove stale references to rules.md and the
unverified Gradle command, or replace them with a real, discoverable pre-merge
process and exact repository-supported gate command. Preserve the stated
exceptions only if they match the documented process.

Replaces the removed CI android-build with a LOCAL pre-push gate, and adds the iOS build too:
- Android: `assembleDebug assembleRelease` when .kt/.kts, android/, or package*.json change.
- iOS: simulator build (CODE_SIGNING_ALLOWED=NO) when .swift, ios/, or Podfile change.
JS-only / docs pushes skip both and stay fast.
@alichherawalla alichherawalla changed the title chore(ci): drop android-build job — run the Android build locally instead chore: move Android+iOS native builds from CI to a local pre-push gate Jul 24, 2026
@sonarqubecloud

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.husky/pre-push:
- Around line 92-108: Ensure the native build gates in .husky/pre-push propagate
failures by enabling fail-fast handling for the hook or explicitly checking the
statuses of the Android Gradle and iOS xcodebuild subshell commands and exiting
nonzero when either fails. Preserve the existing conditional execution based on
PUSHED_ANDROID_NATIVE and PUSHED_IOS_NATIVE.
- Line 46: Update the PUSHED_ANDROID_NATIVE matcher to include all documented
Android gate inputs: native C/C++ source and header files, root Gradle wrapper
files, the gradle/ directory, and Gradle build scripts, while retaining Kotlin,
existing Android, package manifest, and build-directory exclusions.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 48098f10-61e1-4943-84a7-dfbf85ede54b

📥 Commits

Reviewing files that changed from the base of the PR and between 9eccc66 and 71b3cee.

📒 Files selected for processing (1)
  • .husky/pre-push

Comment thread .husky/pre-push
# Native BUILD gate — moved OUT of CI (the hosted android-build runner hung for 3+ hours on the
# native C++ builds). Run the full native builds LOCALLY on push when native / gradle / pods / deps
# change. JS-only and docs-only pushes skip these (they stay fast).
PUSHED_ANDROID_NATIVE=$(printf '%s\n' "$CHANGED_FILES" | grep -E '\.(kt|kts)$|^android/|^package(-lock)?\.json$' | grep -v '/build/' || true)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Include all declared Android gate inputs.

This matcher misses native C++ files and Gradle inputs outside android/ (for example root gradlew, gradle/, or *.gradle). Those changes can bypass the replacement Android gate despite the documented native/Gradle scope.

Proposed fix
-PUSHED_ANDROID_NATIVE=$(printf '%s\n' "$CHANGED_FILES" | grep -E '\.(kt|kts)$|^android/|^package(-lock)?\.json$' | grep -v '/build/' || true)
+PUSHED_ANDROID_NATIVE=$(printf '%s\n' "$CHANGED_FILES" | grep -E '\.(kt|kts|c|cc|cpp|cxx|h|hpp)$|^android/|^gradle/|^gradlew$|(^|/)gradle\.properties$|\.gradle$|^package(-lock)?\.json$' | grep -v '/build/' || true)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
PUSHED_ANDROID_NATIVE=$(printf '%s\n' "$CHANGED_FILES" | grep -E '\.(kt|kts)$|^android/|^package(-lock)?\.json$' | grep -v '/build/' || true)
PUSHED_ANDROID_NATIVE=$(printf '%s\n' "$CHANGED_FILES" | grep -E '\.(kt|kts|c|cc|cpp|cxx|h|hpp)$|^android/|^gradle/|^gradlew$|(^|/)gradle\.properties$|\.gradle$|^package(-lock)?\.json$' | grep -v '/build/' || true)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.husky/pre-push at line 46, Update the PUSHED_ANDROID_NATIVE matcher to
include all documented Android gate inputs: native C/C++ source and header
files, root Gradle wrapper files, the gradle/ directory, and Gradle build
scripts, while retaining Kotlin, existing Android, package manifest, and
build-directory exclusions.

Comment thread .husky/pre-push
Comment on lines +92 to +108
if [ -n "$PUSHED_ANDROID_NATIVE" ]; then
echo "▶ Android build (assembleDebug + assembleRelease) — local gate, replaces CI android-build..."
(cd android && ./gradlew assembleDebug assembleRelease)
fi

if [ -n "$PUSHED_IOS_NATIVE" ]; then
echo "▶ iOS build (simulator, no code-signing) — local gate..."
(cd ios && xcodebuild \
-workspace OffgridMobile.xcworkspace \
-scheme OffgridMobile \
-configuration Debug \
-sdk iphonesimulator \
-destination 'generic/platform=iOS Simulator' \
-derivedDataPath build/prepush-ios \
CODE_SIGNING_ALLOWED=NO \
build)
fi

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/sh
sed -n '1,115p' .husky/pre-push

Repository: off-grid-ai/OGAM

Length of output: 4068


Make native build failures fail the pre-push hook.

.husky/pre-push does not run with set -e, and each native build runs in a subshell. If ./gradlew assembleDebug assembleRelease or xcodebuild fails, the hook can continue past that checkpoint or return success while the native gate did not block the push. Add explicit failure handling such as set -e at the top of the hook or check/exit on nonzero_status for those build commands.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.husky/pre-push around lines 92 - 108, Ensure the native build gates in
.husky/pre-push propagate failures by enabling fail-fast handling for the hook
or explicitly checking the statuses of the Android Gradle and iOS xcodebuild
subshell commands and exiting nonzero when either fails. Preserve the existing
conditional execution based on PUSHED_ANDROID_NATIVE and PUSHED_IOS_NATIVE.

@alichherawalla
alichherawalla merged commit d033959 into main Jul 24, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant