Skip to content

chore(ci): refactor test-nitro-cli workflow#328

Merged
patrickkabwe merged 2 commits intomainfrom
chore/ci-refactor-test-nitro-cli-20250829-205119
Aug 29, 2025
Merged

chore(ci): refactor test-nitro-cli workflow#328
patrickkabwe merged 2 commits intomainfrom
chore/ci-refactor-test-nitro-cli-20250829-205119

Conversation

@patrickkabwe
Copy link
Owner

@patrickkabwe patrickkabwe commented Aug 29, 2025

This PR refactors the test workflow for safety and speed.

  • perms: reduce to read-only
  • support workflow_dispatch
  • matrix: fail-fast=false
  • rm pnpm setup
  • node only for yarn
  • add pods/gradle cache
  • env-based iOS scheme

Summary by CodeRabbit

  • New Features
    • Manual trigger added to mobile build workflows.
  • Bug Fixes
    • Build scripts now exit with clear errors on iOS/Android build failures.
  • Chores
    • Tightened CI permissions to read-only.
    • Updated runners to macOS-latest and disabled fail-fast in matrices.
    • Simplified Node setup and removed pnpm usage.
    • Added caching for CocoaPods and Gradle to speed builds.
    • Downloading upstream artifacts integrated into iOS build flow.
    • iOS E2E tests now set up Xcode 16.4 before running.

perms: reduce to read-only

support workflow_dispatch

matrix: fail-fast=false

rm pnpm setup

node only for yarn

add pods/gradle cache

env-based iOS scheme
@coderabbitai
Copy link

coderabbitai bot commented Aug 29, 2025

Walkthrough

Updates CI workflows and scripts: adjusts permissions to read-only, broadens triggers, switches macOS runner, adds Xcode setup for E2E iOS, introduces CocoaPods and Gradle caching, simplifies Node.js gating (removes pnpm), adds SCHEME env for iOS builds, downloads upstream artifacts, and adds explicit iOS/Android build failure checks in the Maestro script.

Changes

Cohort / File(s) Summary of changes
Nitro CLI CI workflow
.github/workflows/test-nitro-cli.yml
permissions.contents: write→read; broadened triggers to include workflow_dispatch; runners macOS-15→macOS-latest; strategy.fail-fast: false; added SCHEME env for matrix-based scheme; added artifact download for iOS; added CocoaPods cache; added Gradle cache; removed pnpm setup; Node.js setup gated on Yarn only; iOS build uses -scheme "${SCHEME}".
E2E iOS workflow setup
.github/workflows/e2e-tests.yml
Added Setup Xcode step (Xcode 16.4 via maxim-lobanov/setup-xcode@v1) early in the iOS job control flow.
E2E build script fail-fast
scripts/e2e-maestro.sh
Added explicit exit-on-failure checks after iOS xcodebuild (with/without xcpretty) and after Android Gradle assemble, with clear error messages.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor Dev as Upstream Workflow/Dispatch
  participant GHA as GitHub Actions (test-nitro-cli.yml)
  participant Cache as Actions Cache
  participant Art as Artifact Store
  participant Xcode as xcodebuild
  participant Gradle as Gradle

  Dev->>GHA: Trigger (workflow_run success or workflow_dispatch)
  rect rgba(200,230,255,0.3)
    note over GHA: iOS Job
    GHA->>Art: Download generated package
    GHA->>Cache: Restore CocoaPods cache
    GHA->>Xcode: Build with SCHEME (env)
    alt Build succeeds
      Xcode-->>GHA: 0
    else Build fails
      Xcode-->>GHA: non-zero
      GHA-->>GHA: Job fails
    end
  end
  rect rgba(200,255,200,0.3)
    note over GHA: Android Job
    GHA->>Cache: Restore Gradle cache
    GHA->>Gradle: assembleRelease
    alt Build succeeds
      Gradle-->>GHA: 0
    else Build fails
      Gradle-->>GHA: non-zero
      GHA-->>GHA: Job fails
    end
  end
Loading
sequenceDiagram
  autonumber
  participant GHA as GitHub Actions (e2e-tests.yml)
  participant XSetup as setup-xcode@v1
  participant Steps as Subsequent iOS steps

  GHA->>XSetup: Install Xcode 16.4
  alt Setup succeeds
    XSetup-->>GHA: OK
    GHA->>Steps: Continue (download/codegen/bun/pods/maestro)
  else Setup fails
    XSetup-->>GHA: Error
    GHA-->>GHA: Fail early
  end
Loading
sequenceDiagram
  autonumber
  participant Script as scripts/e2e-maestro.sh
  participant Xcode as xcodebuild|xcpretty
  participant Gradle as ./gradlew

  Script->>Xcode: iOS build (pipe to xcpretty if present)
  alt Non-zero exit
    Xcode-->>Script: Failure
    Script-->>Script: Print "❌ iOS build failed!" and exit 1
  else Zero exit
    Xcode-->>Script: Success
    Script->>Gradle: Android assembleRelease
    alt Non-zero exit
      Gradle-->>Script: Failure
      Script-->>Script: Print "❌ Android build failed!" and exit 1
    else Zero exit
      Gradle-->>Script: Success
      Script-->>Script: Continue
    end
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

I thump my paws on build-time ground,
Caches warmed, artifacts found.
Xcode brewed to sixteen-four,
Schemes align—no guessing more.
If builds should fail, I’ll squeak “abort!”
Then hop again with quick report. 🐇✨

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch chore/ci-refactor-test-nitro-cli-20250829-205119

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

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

Other keywords and placeholders

  • Add @coderabbitai ignore or @coderabbit ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
.github/workflows/test-nitro-cli.yml (1)

38-46: Manual runs will fail: run-id is undefined on workflow_dispatch.

The download step dereferences github.event.workflow_run.id when manually dispatched, causing failure; the rest of the job also needs the artifact. Add event-guarded download steps and require a run_id input for workflow_dispatch.

-      - name: Download generated package
-        uses: actions/download-artifact@v5
-        with:
-          name: test-${{ matrix.package-type }}-${{ matrix.pm }}
-          path: ${{ env.WORKING_DIR }}
-          run-id: ${{ github.event.workflow_run.id }}
-          github-token: ${{ github.token }}
-          repository: ${{ github.repository }}
+      - name: Download generated package (from workflow_run)
+        if: github.event_name == 'workflow_run'
+        uses: actions/download-artifact@v5
+        with:
+          name: test-${{ matrix.package-type }}-${{ matrix.pm }}
+          path: ${{ env.WORKING_DIR }}
+          run-id: ${{ github.event.workflow_run.id }}
+          github-token: ${{ github.token }}
+          repository: ${{ github.repository }}
+
+      - name: Download generated package (from manual input)
+        if: github.event_name == 'workflow_dispatch'
+        uses: actions/download-artifact@v5
+        with:
+          name: test-${{ matrix.package-type }}-${{ matrix.pm }}
+          path: ${{ env.WORKING_DIR }}
+          run-id: ${{ github.event.inputs.run_id }}
+          github-token: ${{ github.token }}
+          repository: ${{ github.repository }}

Add the input to workflow_dispatch (outside this hunk):

on:
  workflow_dispatch:
    inputs:
      run_id:
        description: 'Run ID of the upstream "Generate Packages" workflow'
        required: true
        type: string
🧹 Nitpick comments (5)
.github/workflows/test-nitro-cli.yml (5)

22-24: Condition is fine; consider being explicit for workflow_run.

Optional: guard references to github.event.workflow_run.* behind an explicit event check for readability.

- if: github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success'
+ if: github.event_name == 'workflow_dispatch' || (github.event_name == 'workflow_run' && github.event.workflow_run.conclusion == 'success')

31-34: SCHEME env: OK, but workspace coupling may bite later.

If workspace name ever diverges from scheme, introduce WORKSPACE_NAME to decouple.

 env:
   WORKING_DIR: ${{ github.workspace }}/react-native-test-${{ matrix.package-type }}
-  SCHEME: ${{ matrix.package-type == 'module' && 'TestModuleExample' || 'TestViewExample' }}
+  SCHEME: ${{ matrix.package-type == 'module' && 'TestModuleExample' || 'TestViewExample' }}
+  WORKSPACE_NAME: ${{ env.SCHEME }} # change if workspace != scheme

And use "${WORKSPACE_NAME}.xcworkspace" below.


96-105: Pod cache key may be empty on cold starts; broaden restore key.

hashFiles on Podfile.lock can be empty before install. Include Podfile in the key or keep as-is but add an additional restore key for the workspace to improve hit rate.

-  key: ${{ runner.os }}-pods-${{ hashFiles(format('{0}/example/ios/Podfile.lock', env.WORKING_DIR)) }}
-  restore-keys: |
-    ${{ runner.os }}-pods-
+  key: ${{ runner.os }}-pods-${{ hashFiles(format('{0}/example/ios/Podfile.lock', env.WORKING_DIR)) }}-${{ hashFiles(format('{0}/example/ios/Podfile', env.WORKING_DIR)) }}
+  restore-keys: |
+    ${{ runner.os }}-pods-
+    ${{ runner.os }}-pods-${{ hashFiles(format('{0}/example/ios/Podfile', env.WORKING_DIR)) }}-

160-165: Node is required later even for bun path.

node post-script.js runs regardless of pm; rely on runner Node or install explicitly for predictability.

-  - name: Setup Node.js
-    if: matrix.pm == 'yarn'
+  - name: Setup Node.js
+    # Node needed for yarn and for node post-script.js

If you prefer keeping it conditional, add a lightweight check step to echo node -v on bun path to ensure availability.


203-212: Duplicate Gradle caching with setup-java.

actions/setup-java@v5 with cache: gradle already configures the Gradle cache. Keeping both can lead to unnecessary cache churn. Pick one.

-  - name: Cache Gradle
-    uses: actions/cache@v4
-    with:
-      path: |
-        ~/.gradle/caches
-        ~/.gradle/wrapper
-      key: ${{ runner.os }}-gradle-${{ hashFiles(format('{0}/example/android/**/*.gradle*', env.WORKING_DIR)) }}
-      restore-keys: |
-        ${{ runner.os }}-gradle-
+  # Rely on setup-java cache: gradle above, or remove 'cache: gradle' there and keep this block — but not both.
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 45bc4ed and bb53ba9.

📒 Files selected for processing (1)
  • .github/workflows/test-nitro-cli.yml (8 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
.github/workflows/test-nitro-cli.yml (1)
src/generate-nitro-package.ts (2)
  • setupWorkflows (475-499)
  • configureExamplePackageJson (303-343)
🔇 Additional comments (2)
.github/workflows/test-nitro-cli.yml (2)

3-6: Least-privilege perms look good.

contents: read and actions: read are sufficient for cross-run artifact download; nice hardening.


114-127: Verify workspace/scheme exist to fail fast with diagnostics.

Add a quick list step before build so misnamed schemes/workspaces are obvious in logs.

   - name: Build iOS project
     working-directory: ${{ env.WORKING_DIR }}/example/ios
-    run: |
+    run: |
+      echo "Available workspaces:" && ls -1 *.xcworkspace || true
+      echo "Available schemes:" && xcodebuild -list -json | jq -r '.workspace.schemes[]?' || true
       set -o pipefail && xcodebuild \
         CC=clang CPLUSPLUS=clang++ LD=clang LDPLUSPLUS=clang++ \
         -derivedDataPath build -UseModernBuildSystem=YES \
-        -workspace "${SCHEME}.xcworkspace" \
+        -workspace "${WORKSPACE_NAME:-${SCHEME}}.xcworkspace" \
         -scheme "${SCHEME}" \
         -sdk iphonesimulator \
         -configuration ${{ matrix.mode }} \
         -destination 'platform=iOS Simulator,name=iPhone 16' \
         build \
         CODE_SIGNING_ALLOWED=NO | xcpretty

Comment on lines 128 to 132
test-android-build:
name: Test Android Build - ${{ matrix.pm }} - ${{ matrix.package-type }} (${{ matrix.mode }})
if: github.event.workflow_run.conclusion == 'success'
# Run on successful upstream, or when manually dispatched
if: github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success'
runs-on: ubuntu-latest
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Same artifact issue on Android manual runs.

Mirror the iOS fix: add event-guarded download steps and workflow_dispatch input usage.

-  if: github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success'
+  if: github.event_name == 'workflow_dispatch' || (github.event_name == 'workflow_run' && github.event.workflow_run.conclusion == 'success')

And apply the two-step download pattern as in Lines 38-46 for Lines 145-153.

📝 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
test-android-build:
name: Test Android Build - ${{ matrix.pm }} - ${{ matrix.package-type }} (${{ matrix.mode }})
if: github.event.workflow_run.conclusion == 'success'
# Run on successful upstream, or when manually dispatched
if: github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success'
runs-on: ubuntu-latest
test-android-build:
name: Test Android Build - ${{ matrix.pm }} - ${{ matrix.package-type }} (${{ matrix.mode }})
# Run on successful upstream, or when manually dispatched
if: github.event_name == 'workflow_dispatch' || (github.event_name == 'workflow_run' && github.event.workflow_run.conclusion == 'success')
runs-on: ubuntu-latest

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
.github/workflows/e2e-tests.yml (1)

42-49: Explicit permissions required to download artifacts from another workflow.

actions/download-artifact with run-id needs actions: read (and contents: read). Without an explicit permissions block, org-level restrictive defaults can cause 403s.

 name: E2E Test with Maestro

 on:
   workflow_run:
     workflows: ['Generate Packages']
     types:
       - completed
   workflow_dispatch:

+permissions:
+  actions: read
+  contents: read
+
 concurrency:
   group: ${{ github.workflow }}-${{ github.event.workflow_run.id || github.run_id }}
   cancel-in-progress: true
scripts/e2e-maestro.sh (1)

44-46: Fragile “iPhone 16” UDID extraction; add fallback and case-insensitive UDID regex.

If no “iPhone 16” exists, iphone16Id becomes empty and xcodebuild fails. Also, UDIDs can include lowercase hex.

-  iphone16Id=$(xcrun simctl list devices | grep "iPhone 16 (" | grep -E '\(Booted\)|\(Shutdown\)' | head -1 | grep -E -o '\([0-9A-F-]{36}\)' | tr -d '()')
-  echo "📱 Using iPhone 16 simulator with ID: $iphone16Id"
+  iphone16Id=$(xcrun simctl list devices | grep "iPhone 16 (" | grep -E '\(Booted\)|\(Shutdown\)' | head -1 | grep -E -o '\([0-9a-fA-F-]{36}\)' | tr -d '()')
+  if [ -z "${iphone16Id:-}" ]; then
+    echo "⚠️  No iPhone 16 simulator found; falling back to latest available iPhone device."
+    iphone16Id=$(xcrun simctl list devices | grep -E 'iPhone [0-9]+' | grep -E '\(Booted\)|\(Shutdown\)' | head -1 | grep -E -o '\([0-9a-fA-F-]{36}\)' | tr -d '()')
+  fi
+  if [ -z "${iphone16Id:-}" ]; then
+    echo "❌ Could not resolve a simulator UDID. Ensure a simulator is available for the installed Xcode runtime."
+    exit 1
+  fi
+  echo "📱 Using simulator with ID: $iphone16Id"
🧹 Nitpick comments (5)
.github/workflows/e2e-tests.yml (1)

10-12: Safer concurrency key for workflow_run events.

Using github.ref under workflow_run can collide or be empty. Prefer the triggering run id to avoid unintended cancellations across branches.

 concurrency:
-    group: ${{ github.workflow }}-${{ github.ref }}
+    group: ${{ github.workflow }}-${{ github.event.workflow_run.id || github.run_id }}
     cancel-in-progress: true
scripts/e2e-maestro.sh (4)

81-89: Replace fixed sleep with simulator boot status wait.

Avoid flaky timing by waiting until the simulator reports “Booted”.

-  # Launch the simulator if not already booted
-  if ! xcrun simctl list devices | grep "$iphone16Id" | grep -q "Booted"; then
-    echo "🚀 Booting simulator..."
-    xcrun simctl boot $iphone16Id
-  else
-    echo "✅ Simulator already booted"
-  fi
-  # Wait for 10 seconds
-  sleep 10
+  # Launch the simulator if not already booted and wait until ready
+  if ! xcrun simctl list devices | grep "$iphone16Id" | grep -q "Booted"; then
+    echo "🚀 Booting simulator..."
+    xcrun simctl boot "$iphone16Id"
+  else
+    echo "✅ Simulator already booted"
+  fi
+  echo "⏳ Waiting for simulator to be fully booted..."
+  xcrun simctl bootstatus "$iphone16Id" -b

41-41: Quote paths to handle spaces.

Harden cd against spaces in EXAMPLE_DIR.

-  cd $EXAMPLE_DIR/ios
+  cd "$EXAMPLE_DIR/ios"

97-97: Quote paths to handle spaces.

Same nit for Android path.

-  cd $EXAMPLE_DIR/android
+  cd "$EXAMPLE_DIR/android"

25-33: Allow SCHEME override via environment for consistency with workflows.

Let CI pass SCHEME when needed; fall back to PACKAGE_TYPE defaults.

-APP_ID=""
-SCHEME=""
+APP_ID=""
+SCHEME="${SCHEME:-}"

 if [ "$PACKAGE_TYPE" == "module" ]; then
     APP_ID="com.testmoduleexample"
-    SCHEME="TestModuleExample"
+    SCHEME="${SCHEME:-TestModuleExample}"
 elif [ "$PACKAGE_TYPE" == "view" ]; then
     APP_ID="com.testviewexample"
-    SCHEME="TestViewExample"
+    SCHEME="${SCHEME:-TestViewExample}"
 else
     echo "Error! You must pass either 'module' or 'view'"
     echo ""
     exit 1
 fi
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between bb53ba9 and 154d89e.

📒 Files selected for processing (2)
  • .github/workflows/e2e-tests.yml (1 hunks)
  • scripts/e2e-maestro.sh (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
.github/workflows/e2e-tests.yml (1)
src/generate-nitro-package.ts (1)
  • setupWorkflows (475-499)
🔇 Additional comments (4)
.github/workflows/e2e-tests.yml (1)

124-128: Verify Xcode 16.4 availability on macOS-15 and matching simulator runtime.

macOS-15 runners may not always have Xcode 16.4 pre-provisioned. Also, the e2e script targets an “iPhone 16” simulator; ensure that Xcode 16.4 provides the required iOS runtime/device. If not present, this step or downstream builds will fail.

Would you like me to add a fallback to a supported Xcode version and/or parameterize the version via an input?

scripts/e2e-maestro.sh (3)

65-71: LGTM: explicit iOS build failure handling after xcpretty.

Great addition; prevents silent green pipelines when xcodebuild fails behind the pipe.


74-77: LGTM: explicit iOS build failure handling without xcpretty.

Consistent exit-on-fail with a clear message.


102-106: LGTM: Android build failure handling.

Clear failure messaging with non-zero exit.

@patrickkabwe patrickkabwe merged commit ab7727b into main Aug 29, 2025
6 checks passed
@patrickkabwe patrickkabwe deleted the chore/ci-refactor-test-nitro-cli-20250829-205119 branch August 29, 2025 19:16
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