Skip to content

Conversation

teodorciuraru
Copy link
Contributor

@teodorciuraru teodorciuraru commented Oct 2, 2025

Summary

Refactors CI workflows to improve test data isolation and adds GitHub Step Summary reporting with direct BrowserStack links.

Key Changes

1. Test Data Seeding

  • Moved seed steps inline into each BrowserStack test job (previously separate jobs)
  • When retrying a failed BrowserStack job, a fresh test document is seeded automatically
  • Prevents test task accumulation and improves test isolation
  • Uses reusable composite action: .github/actions/seed-ditto-document

2. CI Reporting

  • Added Step Summary to all 8 BrowserStack workflows
  • Each summary includes:
    • Overall status badge (✅/❌)
    • Job status table (Lint, Build, BrowserStack Tests)
    • Direct links to BrowserStack dashboard filtered by project + build number
    • List of tested devices/browsers

3. BrowserStack Links

All workflows now provide specific links to their test results:

  • android-cpp → Ditto Android C++
  • android-java → Ditto Android Java
  • android-kotlin → Ditto Android Kotlin
  • dotnet-maui → Ditto .NET MAUI (Android + iOS)
  • flutter → Flutter Ditto Tasks (Android + iOS with BUILD_ID)
  • java-spring → Ditto Java Spring Tasks
  • kotlin-multiplatform → Ditto Kotlin Multiplatform
  • swift → Ditto Swift

Workflows Updated

  1. .github/workflows/android-cpp-ci.yml
  2. .github/workflows/android-java-ci.yml
  3. .github/workflows/android-kotlin-ci.yml
  4. .github/workflows/dotnet-maui-ci.yml
  5. .github/workflows/flutter-ci.yml
  6. .github/workflows/java-spring-ci.yml
  7. .github/workflows/kotlin-multiplatform-ci.yml
  8. .github/workflows/swift-ci.yml

Benefits

  • Better test isolation: Each BrowserStack retry gets fresh test data
  • Easier debugging: Direct links to specific BrowserStack builds
  • Improved visibility: Clear status summaries for all CI runs
  • Consistent pattern: All workflows follow same structure

teodorciuraru and others added 2 commits October 2, 2025 13:08
…ming

- Remove PR comments from android-java-ci.yml and android-cpp-ci.yml
- Add summary jobs to all CI workflows with consistent format
- Rename javascript-web-browserstack.yml to javascript-web-ci.yml for consistency
- All 16 CI workflows now use GITHUB_STEP_SUMMARY instead of PR comments
- Summary includes: overall status, job status table, BrowserStack links

Each workflow now displays a clean summary with:
- Overall status badge (✅/❌)
- Job status table (Lint, Build, BrowserStack Tests)
- Direct links to BrowserStack dashboard with project and build number
- List of tested devices/browsers

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
- Create .github/actions/seed-ditto-document composite action
- Replace ~480 lines of duplicated seed logic across 16 workflows
- Standardize output naming to 'document-title' across all workflows
- Maintain consistent data model: _id, title, done, deleted

Benefits:
- DRY: Single source of truth for seeding test documents
- Consistency: All workflows use identical seeding logic
- Maintainability: Changes to seed logic only need updating in one place
- Standardization: All apps verified to use title/done/deleted fields

Updated workflows:
- android-cpp-ci.yml
- android-java-ci.yml
- android-kotlin-ci.yml
- cpp-tui-ci.yml
- dotnet-maui-ci.yml
- dotnet-tui-ci.yml
- dotnet-winforms-ci.yml
- flutter-ci.yml
- java-spring-ci.yml
- javascript-tui-ci.yml
- javascript-web-ci.yml
- kotlin-multiplatform-ci.yml
- react-native-ci.yml
- react-native-expo-ci.yml
- rust-tui-ci.yml
- swift-ci.yml

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
@teodorciuraru teodorciuraru self-assigned this Oct 2, 2025
teodorciuraru and others added 15 commits October 2, 2025 15:01
The javascript-web app was sorting tasks by completion status instead of
by the inverted timestamp _id field. This caused CI test documents (which
use inverted timestamps to appear first) to not show up at the top of the list,
breaking BrowserStack tests.

Changed query from:
  ORDER BY done
To:
  ORDER BY _id ASC

This matches the ordering used in all other quickstart apps and ensures
CI-seeded test documents appear at the top of the task list.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
- Changed javascript-web from ORDER BY _id ASC to ORDER BY title ASC
- Changed rust-tui from ORDER BY _id to ORDER BY title ASC
- All 16 apps now consistently use ORDER BY title ASC
- This ensures CI test documents (with inverted timestamp in title) appear at top of list

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
- Removed incorrect "GitHub Test Task" string check that doesn't exist in seeded documents
- Document title is just the ID itself (e.g., 8240590183_javascript-web_ci_test_18193630918_4)
- Fixed array indexing to match actual document ID format: INVERTED_TIMESTAMP_app-name_ci_test_RUNID_RUNNUMBER
- Test now looks for either the full doc_id or the run_id portion in task text

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
1. Fixed seed-ditto-document action for macOS compatibility
   - Changed `head -n -1` to `sed '$d'` (BSD/GNU portable)
   - macOS BSD head doesn't support negative line counts
   - This fixes "illegal line count" error on KMP iOS and other macOS jobs

2. Fixed javascript-web BrowserStack test for exact document matching
   - Changed from substring/partial matching to exact match: `element_text == doc_id`
   - Removed extraction logic that was looking for run_id substring
   - Document title IS the document ID, so exact match is correct
   - Ensures only the seeded CI test document is matched, not user tasks

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
…uilds

- Remove seed steps from build-android (lines 105-111) and build-ios (lines 175-181)
- Remove test_doc_title output from both build jobs
- Add single seed-task-data job that depends on both build-android and build-ios
- Update browserstack-android to depend on seed-task-data instead of just build-android
- Change browserstack-android to read test_task_title from seed-task-data outputs
- Update build-summary to include seed-task-data in dependencies

This brings KMP workflow in line with the standard pattern used by other CI workflows:
1. Lint runs first
2. Build jobs (android, ios, desktop) run in parallel after lint
3. Single seed-task-data job runs after both android and ios builds complete
4. BrowserStack tests depend on seed-task-data (which depends on builds)

The composite action .github/actions/seed-ditto-document correctly seeds
documents with title, done, and deleted fields matching the KMP app model.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
Changed kotlin-multiplatform and dotnet-maui workflows to use consistent
`seed-ditto-cloud` job name instead of `seed-task-data`.

This is part of standardizing all CI workflows to use the same pattern:
- Job name: `seed-ditto-cloud`
- Job display name: "Seed Test Task to Ditto Cloud"
- Step name: "Seed test task to Ditto Cloud"
- Runs after all build jobs complete
- BrowserStack tests depend on seed-ditto-cloud + build jobs

Changes:
- kotlin-multiplatform-ci.yml: Renamed seed-task-data → seed-ditto-cloud
- dotnet-maui-ci.yml: Renamed seed-task-data → seed-ditto-cloud

Remaining workflows with inline seeding will be updated in follow-up commits.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
…kotlin

Standardized android-kotlin-ci.yml to follow the pattern:
1. Lint runs first
2. Build job (renamed from build-and-test, removed seed step and output)
3. seed-ditto-cloud job runs after build completes
4. BrowserStack tests depend on both [build, seed-ditto-cloud]

Changes:
- Renamed build-and-test job → build
- Removed inline seed step (lines 90-96) from build job
- Removed document-title output from build job
- Created new seed-ditto-cloud job after build
- Updated browserstack-test needs: [build, seed-ditto-cloud]
- Updated all references: needs.build-and-test → needs.build and needs.seed-ditto-cloud
- Updated summary job dependencies

This ensures seeding only happens after successful build,
and BrowserStack tests only run after both build and seed complete.

Part of standardizing all 16 CI workflows to use consistent seed pattern.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
…java and android-cpp

- Remove inline seed steps from browserstack-test job
- Create separate seed-ditto-cloud job after build
- Update browserstack job to depend on [build, seed-ditto-cloud]
- Standardize output reference: test_task_title
- Update summary job dependencies

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
Swift:
- Extract inline seed from browserstack job
- Create separate seed-ditto-cloud job after builds
- Update browserstack job to depend on [build-ios, seed-ditto-cloud]
- Update references to needs.seed-ditto-cloud.outputs.test_task_title

Flutter:
- Rename seed-data → seed-ditto-cloud
- Rename "Seed Test Data" → "Seed Test Task to Ditto Cloud"
- Update output: test_title → test_task_title
- Update all references

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
- Remove seed step and output from build job
- Create separate seed-ditto-cloud job after build
- Update browserstack-test to depend on [build, seed-ditto-cloud]
- Update all references to needs.seed-ditto-cloud.outputs.test_task_title
- Update summary job dependencies

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
Summary jobs should only depend on the final test jobs (browserstack/maestro),
not on intermediate jobs like lint, build, or seed-ditto-cloud. GitHub Actions
automatically waits for transitive dependencies.

Changes:
- android-cpp: Extract inline seed to separate job, update summary to only depend on browserstack-appium-test
- android-java: Add seed-ditto-cloud to browserstack-test deps, update summary
- android-kotlin: Update summary to only depend on browserstack-test
- dotnet-maui: Update summary to only depend on browserstack jobs
- java-spring: Update summary to only depend on browserstack-test
- kotlin-multiplatform: Update build-summary to only depend on browserstack-android
- swift: Update summary to only depend on browserstack

Pattern now: lint → builds → seed-ditto-cloud → browserstack/maestro → summary

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
The Spring Boot app was being built with DITTO_ENABLE_CLOUD_SYNC=true
but started without it at runtime. This caused sync to be disabled by default.

Also add generic retry-browserstack.sh script for handling BrowserStack
queue full errors with exponential backoff (5 attempts, 1-5min waits).

Changes:
- Add env vars to Spring Boot app startup (including DITTO_ENABLE_CLOUD_SYNC)
- Create .github/scripts/retry-browserstack.sh for generic retry logic
- Update android-java to use generic retry script

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
…tform summary

- Remove retry-browserstack.sh wrapper from android-java-ci.yml
- Fix kotlin-multiplatform build-summary to depend on all jobs it references
- Add paths filter to swift-ci.yml push trigger for consistency

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
- Embed seed-ditto-document step directly in each BrowserStack test job
- Remove standalone seed-ditto-cloud jobs from all workflows
- Update job dependencies to remove seed-ditto-cloud from needs arrays
- Change output references from needs.seed-ditto-cloud.outputs to steps.seed_task.outputs

This ensures that retrying a BrowserStack job re-seeds fresh test data,
preventing task accumulation and improving test isolation.

Workflows updated:
- android-cpp-ci.yml: browserstack-appium-test job
- android-java-ci.yml: browserstack-test job
- android-kotlin-ci.yml: browserstack-test job
- java-spring-ci.yml: browserstack-test job
- kotlin-multiplatform-ci.yml: browserstack-android job
- swift-ci.yml: browserstack job
- dotnet-maui-ci.yml: browserstack-android and browserstack-ios jobs
- flutter-ci.yml: browserstack-android and browserstack-ios jobs

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
…ng summaries

Replace generic BrowserStack dashboard links with specific project+build URLs
to make it easier to find test results for each CI run.

- android-cpp: Use project=Ditto+Android+C%2B%2B&build=Build+#{run_number}
- java-spring: Use project=Ditto+Java+Spring+Tasks&build=Java+Spring+Selenium+Tests+#{run_number}

This matches the pattern used in other workflows (android-java, android-kotlin,
dotnet-maui, kotlin-multiplatform, swift).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
@teodorciuraru teodorciuraru changed the title feat(ci): extract seed document logic into reusable composite action refactor(ci): inline seed steps and add BrowserStack summaries Oct 3, 2025
@teodorciuraru teodorciuraru marked this pull request as ready for review October 3, 2025 08:15
@Copilot Copilot AI review requested due to automatic review settings October 3, 2025 08:15
@teodorciuraru teodorciuraru requested a review from a team as a code owner October 3, 2025 08:15
@teodorciuraru teodorciuraru added the enhancement New feature or request label Oct 3, 2025
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR refactors CI workflows to improve test data isolation and add comprehensive GitHub Step Summary reporting with direct BrowserStack links. The changes consolidate inline seeding functionality and standardize reporting across all workflows.

  • Moves test document seeding inline into BrowserStack jobs using a reusable composite action
  • Adds consistent GitHub Step Summary reporting across all CI workflows
  • Standardizes BrowserStack links and reporting format

Reviewed Changes

Copilot reviewed 21 out of 21 changed files in this pull request and generated no comments.

Show a summary per file
File Description
rust-tui/src/tui/todolist.rs Updates SQL query ordering from _id to title ASC
javascript-web/src/App.tsx Updates SQL query ordering from done to title ASC
.github/workflows/swift-ci.yml Refactors to use inline seeding and adds step summary reporting
.github/workflows/rust-tui-ci.yml Migrates to composite action seeding and adds CI summary
.github/workflows/react-native-expo-ci.yml Updates to use seed action outputs
.github/workflows/react-native-ci.yml Updates to use seed action outputs
.github/workflows/kotlin-multiplatform-ci.yml Inline seeding and BrowserStack link addition
.github/workflows/javascript-web-ci.yml Migrates to composite action with CI summary
.github/workflows/javascript-tui-ci.yml Updates seeding and adds CI reporting
.github/workflows/java-spring-ci.yml Inline seeding migration and summary reporting
.github/workflows/flutter-ci.yml Removes separate seed job, moves inline to test jobs
.github/workflows/dotnet-winforms-ci.yml Composite action migration and CI summary
.github/workflows/dotnet-tui-ci.yml Seeding refactor and summary addition
.github/workflows/dotnet-maui-ci.yml Removes separate seed job, inline seeding per test job
.github/workflows/cpp-tui-ci.yml Composite action migration and CI reporting
.github/workflows/android-kotlin-ci.yml Inline seeding and BrowserStack link addition
.github/workflows/android-java-ci.yml Seeding refactor and summary reporting
.github/workflows/android-cpp-ci.yml Composite action migration and CI summary
.github/scripts/retry-browserstack.sh New retry wrapper for BrowserStack API calls
.github/scripts/browserstack-test.py Updates document matching logic for exact ID matching
.github/actions/seed-ditto-document/action.yml New composite action for standardized document seeding

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

teodorciuraru added a commit that referenced this pull request Oct 6, 2025
Flutter iOS fixes:
- Align paths with PR #181's working structure
- Use relative paths: output="../build/ios_integration"
- Navigate from flutter_app/ios directory
- Upload path: @$product/ios_test_package.zip

BrowserStack wait loop improvements:
- Add device-level status checking (not just build-level)
- Exit loop when all device sessions complete (passed/failed)
- Prevents waiting 18 minutes when tests fail immediately
- Check device.sessions[].status for completion states

This allows CI to detect BrowserStack test failures faster instead
of waiting for the full timeout period.
teodorciuraru added a commit that referenced this pull request Oct 6, 2025
Replace retry approach with PR #181's proven working structure:
- Use composite action for seeding (outside build)
- Separate steps for: seed, build, upload app, upload test, execute, wait
- Keep DITTO_CLOUD_TASK_TITLE variable name (not TASK_TO_FIND)
- Keep device-level status checking in wait loop
- Keep iOS path fix for devices JSON

This matches PR #181's approach which was working reliably.
teodorciuraru added a commit that referenced this pull request Oct 6, 2025
Both Android and iOS now use PR #181's proven approach:
- Separate seed step (composite action)
- Separate build step
- Separate upload step(s)
- Separate test execution step
- Separate wait loop step

Key differences from PR #181:
- Uses DITTO_CLOUD_TASK_TITLE (not TASK_TO_FIND)
- Device-level status checking in wait loops
- Reads devices from .github/browserstack-devices.json
- Debug logging in integration_test/app_test.dart

This removes the retry mechanism that was causing shell variable
scope issues where TASK_TITLE wasn't visible to subprocesses
(GitHub Actions -> shell -> Gradle -> Flutter -> Dart compiler).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
@teodorciuraru teodorciuraru merged commit b430663 into main Oct 6, 2025
1189 of 1493 checks passed
@teodorciuraru teodorciuraru deleted the teodorciuraru/extract-seed-document-composite-action branch October 6, 2025 14:10
teodorciuraru added a commit that referenced this pull request Oct 6, 2025
PR #181 (merged to main) uses TASK_TO_FIND in both workflow and test.
We had changed to DITTO_CLOUD_TASK_TITLE which caused mismatch.

Reverted to TASK_TO_FIND to match merged code exactly.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
teodorciuraru added a commit that referenced this pull request Oct 6, 2025
PR #181 had INTEGRATION_TEST_MODE=true passed to dart-defines but we
accidentally removed it during refactoring.

Android: Added back SU5URUdSQVRJT05fVEVTVF9NT0RFPXRydWU= (base64) to dart-defines
iOS: Added back --dart-define=INTEGRATION_TEST_MODE=true

This flag is needed to properly run integration tests.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
teodorciuraru added a commit that referenced this pull request Oct 7, 2025
This script was added in PR #181 but was never actually used by any workflow.
All workflows now use nick-fields/retry@v3 action for retry logic instead.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants