Skip to content

[SDK-115] Enable full BCIT on CI#1061

Open
franco-zalamena-iterable wants to merge 9 commits into
masterfrom
SDK-115-bcit-ci
Open

[SDK-115] Enable full BCIT on CI#1061
franco-zalamena-iterable wants to merge 9 commits into
masterfrom
SDK-115-bcit-ci

Conversation

@franco-zalamena-iterable

@franco-zalamena-iterable franco-zalamena-iterable commented Jun 1, 2026

Copy link
Copy Markdown
Contributor

🔹 Jira Ticket(s) if any

✏️ Description

We had two different test sets before for bcit, some functionality was not working, now with this pr we are adding all the bcit test suite.

The new test is called Integration Tests (BCIT), on this PR it runs what was already running on E2E in app tests.
We are then creating different PRs for each test suite and we can see it working independently

franco-zalamena-iterable and others added 5 commits June 1, 2026 09:27
After the SDK-170 migration of this workflow to ubuntu-latest + KVM
(#1048, commit 7d4a80b), every PR opened against master has been
failing the In-App Message E2E Tests check at the build stage:

    Execution failed for task ':integration-tests:mergeDebugAndroidTestResources'.
    > Cannot access output property 'blameLogOutputFolder' …
       > Failed to create MD5 hash for file
         '.../merged_res_blame_folder/.../values-az.json' as it does not exist.

with this warning a few lines earlier:

    Detected multiple Kotlin daemon sessions at kotlin/sessions

The 'Pre-download Gradle and Build (Parallel with Emulator)' step
backgrounded a separate Gradle invocation that was meant to assemble
the APKs while the emulator booted. On macos-15-intel the background
process was resource-starved during emulator boot (2 cores / slow HVF)
so it usually finished or stalled before the action's Gradle started.
On ubuntu-latest + KVM both Gradle processes get real CPU and run in
true parallel, racing on the same integration-tests/build/intermediates
directory.

Affected runs:
  - feature/sdk-338-mobile-inbox-customization: 5 failures
  - fix/SDK-412-UUA-Naming-inconsistencies: 1 failure
  - SDK-170-emulator-network-trace: green (warm cache made the race
    window negligible — masked the regression during review)

Removing the parallel pre-build is sufficient. The action's script
already invokes ':integration-tests:connectedDebugAndroidTest' which
transitively builds the APKs it needs. Expected wall-clock impact:
+30-90s on a cold Gradle cache, traded for 'all PRs can run this
check'.

Co-authored-by: Cursor <cursoragent@cursor.com>
- Rename .github/workflows/inapp-e2e-tests.yml to integration-tests-bcit.yml;
  rename job/step/artifact accordingly and update path filters.
- Add a global concurrency group so runs serialise across all branches/refs:
  the suite drives a single shared BCIT user, so two PRs (or a PR overlapping
  the nightly cron) would race on backend state otherwise.
- Switch run-e2e.sh from a single-method class filter to a package filter
  (com.iterable.integration.tests), so all five integration-test classes
  run in CI and any new test under that package is picked up automatically.
- Add a CI fail-fast gate when any BCIT_* secret is empty, so a
  misconfigured branch fails clearly instead of running with the gradle
  default 'test_api_key' and 401-ing later.
- Drop the dead test-summary block and stale block-comments left over from
  the macOS-Intel era.

@ignore PushNotificationIntegrationTest#testPushNotificationMVP for now:
local-suite run shows the foreground assertion after openNotification()
is unreliable on the BCIT emulator (notification taps don't always resume
the test app). Tracked in an SDK-115 follow-up.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…ger BCIT

The `branches:` key under `pull_request:` filters by the PR's *target*
branch, not its head — so PRs targeting long-lived integration branches
(e.g. the followup #1062 targeting SDK-115-bcit-ci) silently skipped this
workflow. Path filters still gate which PRs actually fire it; only PRs
that touch integration-tests / iterableapi(-ui) / the workflow / the
run-e2e.sh script will trigger.

Push trigger keeps `branches: [master]` so we don't double-run on every
feature branch's push events alongside its PR run.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The SDK-115 BCIT CI run revealed that /api/embedded-messaging/messages
returns `{"placements": []}` for the CI user (bcituser@iterable.com)
after updateUser({isPremium: true}), so embeddedManager.syncMessages
finds no eligible message and the test asserts on an empty list.

This is a campaign / user-configuration gap in the BCIT Iterable
project, not a code bug. @ignore'd on the base SDK-115 branch so PR
#1061 can land with the workflow consolidation green; a separate
follow-up will re-enable the test once the backend side is configured
to deliver an eligible embedded message to bcituser@iterable.com for
placement 2157 when isPremium=true.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@franco-zalamena-iterable franco-zalamena-iterable changed the title [SDK-115] Add bcit full test suite [SDK-115] Enable full BCIT on CI Jun 2, 2026
franco-zalamena-iterable and others added 4 commits June 2, 2026 18:16
The BCIT iOS suite uses a per-day generated test email
(YYYY-MM-DD-integration-test-user@test.com) so a fresh user is created
daily; campaign audience-eligibility transitions fire reliably without
state accumulating on a long-lived account. Android was using a
hardcoded BCIT_ITERABLE_TEST_USER_EMAIL secret (bcituser@iterable.com)
which had stale state and caused the embedded test to fail with
`placements: []` on CI.

Changes:
  - New TestUserEmailGenerator object that produces the dated email in
    UTC; takes a Date param so the formatting logic is unit-testable
    without time mocks. Avoids java.time so the test app keeps working
    on minSdk 21 without core-library desugaring.
  - 4 unit tests covering format, zero-padding, epoch boundary and
    late-day-UTC stability.
  - BaseIntegrationTest gains `isRunningInCI` (instrumentation-arg
    routed; env vars don't reach the device-side test JVM through
    `am instrument`) and `testUserEmail` (dated email in CI, secret
    fallback locally).
  - InApp / Deeplink / Embedded tests' ensureUserSignedIn calls use
    `testUserEmail` so the SDK email and the request-payload email
    match end-to-end.
  - Embedded test refactored to mirror iOS shape (false→true isPremium
    transition with sync polling); helpers extracted.

Local verification (CI mode, dated user 2026-06-02-...@test.com):
  $ ./gradlew :integration-tests:connectedDebugAndroidTest \
      -Pandroid.testInstrumentationRunnerArguments.package=com.iterable.integration.tests \
      -Pandroid.testInstrumentationRunnerArguments.notClass=com.iterable.integration.tests.PushNotificationIntegrationTest \
      -Pandroid.testInstrumentationRunnerArguments.ci=true
  Tests 8/7 completed. (1 skipped) (0 failed)
  BUILD SUCCESSFUL

testEmbeddedMessageMVP stays @ignore'd — even with the dated user AND
the iOS-shape transition, /api/embedded-messaging/messages returns
`placements: []`. Same dated email works fine for InApp + Deeplink and
for iOS embedded, so the gap is on the BCIT-project configuration side
(no Android-targeting embedded campaign). Re-enable once the backend
side is set up — no further code change should be needed.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Lets a developer pick which user the SDK signs in as without editing
local.properties or rebuilding. Field + Save / Clear buttons on
MainActivity persist to SharedPreferences; both manual app flows and
instrumented tests honour it (override → CI dated email → BuildConfig).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
CI run on PR #1064 surfaced four failures that all share the same root
cause: the Pixel Launcher ANRs on Ubuntu+KVM during heavy parallel work
and steals focus from the activity-under-test, so findObject().exists()
returns false even though the view is in the tree (logcat shows
`current package: android` instead of `com.iterable.integration.tests`).

Three fixes:

1. BaseIntegrationTest.setUp now pressBack/pressHome to dismiss any
   lingering system dialog before the test runs. Universal CI-emulator
   hardening; benefits every test class that extends BaseIntegrationTest.
2. EmbeddedMessageIntegrationTest + DeepLinkIntegrationTest now use
   findObject().waitForExists(5000) instead of bare .exists().
   ActivityScenario reports RESUMED before the view tree is fully
   rendered; waitForExists handles the race. Same pattern as
   PushNotificationIntegrationTest already uses.
3. activity_main.xml is now wrapped in a ScrollView so the Test Scenario
   buttons stay reachable even when the override card grows.

Local verification: `Tests 7/7 completed. (0 skipped) (0 failed)` for
the full non-push suite with `ci=true`.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…ster\")

Two small infra pieces that every BCIT test needs:

- run-e2e.sh now passes `ci=true` as an instrumentation argument so
  tests can detect CI mode via InstrumentationRegistry.getArguments().
  Env vars don't reach the test JVM through `am instrument`, so the
  arg is the only reliable channel.
- BaseIntegrationTest.initializeIterableSDK now adds `tester` to
  IterableConfig.allowedProtocols. BCIT campaigns use `tester://` deep
  links; without this the SDK silently drops the URL before invoking
  the URL handler. Matches iOS's
  `config.allowedProtocols = ["tester", "https", "http"]`.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

@sumeruchat sumeruchat left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nice stack split and good dated-user pattern. One non-blocking follow-up: the stable test email still reaches public CI diagnostics (MainActivity card, DeepLinkIntegrationTest.kt:114), worth masking to keep the dated-user hardening intact.

@sumeruchat sumeruchat left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Approving.

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.

2 participants