Skip to content

Conversation

teodorciuraru
Copy link
Contributor

@teodorciuraru teodorciuraru commented Oct 3, 2025

Summary

Refactored all 11 BrowserStack CI workflows to handle BROWSERSTACK_ALL_PARALLELS_IN_USE capacity errors through comprehensive retry mechanisms and centralized configuration.

What Changed

Retry Mechanism

Added 5-attempt retry with 15-minute waits to all BrowserStack workflows. Each retry performs the complete test lifecycle (seed → build → upload → execute → wait) to ensure test documents exist in Ditto Cloud.

Extended Timeouts

Increased job timeouts to 150 minutes to support full retry cycles without premature cancellation.

Centralized Device Configuration

Created .github/browserstack-devices.yml with comprehensive inline comments explaining device selection criteria, OS coverage, and links to BrowserStack documentation. All 11 workflows use yq for config parsing.

Test Reliability Improvements

  • Device-level status checking (not just build-level)
  • Auto-grant permissions to prevent potential issues
  • Standardized timeout polling patterns using MAX_WAIT_TIME (18 min) instead of iteration loops

Standardization

  • Consistent timeout values (150 min) across all BrowserStack jobs
  • Consistent wait times (18 min) for polling using MAX_WAIT_TIME pattern
  • Consistent workflow naming ("{Platform} CI")

CI Triggers

All workflows use pull_request and workflow_dispatch triggers only. They run on PR updates but NOT on merge to main to save BS capacity.

BrowserStack Dashboard Integration

Created reusable composite action .github/actions/generate-browserstack-names that auto-derives BrowserStack project names from workflow context. All 11 workflows now use this centralized action.

Project Name Auto-Derivation

  • Pattern: Workflow name → quickstart - {Platform}
  • Example: "JavaScript Web CI" → quickstart - JavaScript Web
  • Zero config: No hardcoded project names needed
  • Eliminated: 11+ hardcoded project-name inputs across workflows

Build Name Status

  • Status: Currently returns empty string (documented with FIXME)
  • Issue: Build name generation using GitHub CLI/event context is unreliable; we couldn't get it to work in time.
  • TODO: Needs proper implementation in future PR

Benefits

  • Single source of truth for project naming
  • Automatic consistency across all workflows
  • Less maintenance (action renamed from get-browserstack-build-info)
  • Clear documentation of what works vs. what needs fixing

Shortcomings (WIP)

  • We still want the Build Names on BrowserStack to reflect the PR title and commit message for easier identification.
  • We still want all BS workflows to have a link to the exact BS build.

teodorciuraru and others added 18 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]>
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]>
Standardize project names and build names across all CI workflows with BrowserStack integration:

**Build Name Standardization:**
- Unified all build names to "CI Build #N" format
- Previously used inconsistent names like "Build #N", "Android Build #N", "iOS Build #N", "Java Spring Selenium Tests #N"
- Consistent format improves recognition and dashboard filtering

**Project Name Standardization:**
- Changed all project names from "Ditto [Platform]" to "QuickStart [Platform]" format
- Updated 10 workflows: Android (C++, Java, Kotlin), .NET MAUI, Flutter, Java Spring, Kotlin Multiplatform, React Native, React Native Expo, Swift
- Aligns with repository naming convention

**Dashboard URL Standardization:**
- Updated all BrowserStack dashboard URLs to use standardized project and build names
- Proper URL encoding for special characters (e.g., "QuickStart+Android+C%2B%2B")
- Consistent format makes test session tracking easier

This improves organization and consistency across the BrowserStack dashboard for all platforms.

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

Co-Authored-By: Claude <[email protected]>
@teodorciuraru teodorciuraru changed the title feat(ci): standardize BrowserStack naming refactor(ci): standardize BrowserStack naming Oct 3, 2025
@teodorciuraru teodorciuraru self-assigned this Oct 3, 2025
teodorciuraru and others added 10 commits October 3, 2025 22:19
Allow CI workflows to run on all branches, not just main:
- Removed 'branches: [main]' restrictions from push and pull_request triggers
- Workflows still filtered by path changes for efficiency
- Enables testing on feature branches and PRs from any branch

Updated 11 workflow files to run on all branches.

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

Co-Authored-By: Claude <[email protected]>
- Update Python test script to use "QuickStart JavaScript Web" project name
- Update Python test script to use "CI Build #N" build name format
- Remove branch restrictions (allow all branches, not just main/sdk-*)
- Fix workflow file path references (javascript-web-browserstack.yml → javascript-web-ci.yml)
- Update dashboard link to point to specific build instead of generic dashboard
- Now all 11 CI workflows have links to exact BrowserStack builds

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

Co-Authored-By: Claude <[email protected]>
- Remove separate seed-ditto-cloud job from both workflows
- Add seed-ditto-document step as first step in each BrowserStack test job
- Update job dependencies to only depend on build jobs
- Change references from needs.seed-ditto-cloud.outputs to steps.seed-document.outputs

Benefits:
- Each test job is now self-contained and retryable
- Test jobs seed their own documents on retry
- Parallel test execution starts immediately after builds complete

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

Co-Authored-By: Claude <[email protected]>
- Split build-and-test job into separate lint, build, browserstack-test, summary jobs
- Changed workflow name from "javascript-web-browserstack" to "JavaScript Web CI"
- Build job now uploads dist/ artifact for test job to download
- BrowserStack test job now seeds its own document (self-contained, retryable)
- Summary job references all upstream job results for accurate status reporting

Benefits:
- Matches standard structure used by all other CI workflows
- Better separation of concerns (lint, build, test, report)
- Improved artifact handling between jobs
- Self-contained test job can be retried independently

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

Co-Authored-By: Claude <[email protected]>
The browserstack-test job needs Node.js to run npx http-server.
This was missing after the workflow refactoring.

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

Co-Authored-By: Claude <[email protected]>
The issue was that `npx http-server` sometimes took longer than 5
seconds to download and install the package, causing the curl check
to fail. By pre-installing http-server globally, it's immediately
available and starts consistently within the timeout window.

Changes:
- Add step to install http-server globally with npm
- Change command from `npx http-server` to `http-server`
- This eliminates the npx download time race condition

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

Co-Authored-By: Claude <[email protected]>
The BrowserStack Local tunnel needs more time to establish. 10 seconds
was insufficient, causing tests to fail with "local testing through
BrowserStack is not connected". Increasing to 20 seconds should allow
the tunnel to fully establish before tests run.

Note: The http-server changes in the previous commit work perfectly.
This is a separate BS Local timing issue.

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

Co-Authored-By: Claude <[email protected]>
Rename final job to 'summary' with 'CI Report' name for consistency:
- kotlin-multiplatform-ci.yml: build-summary → summary
- react-native-ci.yml: report-results → summary
- react-native-expo-ci.yml: report-results → summary

All 9 BrowserStack CI workflows now follow the standard pattern:
lint → build → browserstack-test → summary

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

Co-Authored-By: Claude <[email protected]>
**High Priority Fixes:**
1. Add BrowserStack capacity management (concurrency control to all 9 workflows)
2. Fix summary job dependencies (add lint, build to needs arrays)
3. Create centralized device configuration (.github/browserstack-devices.json)

**Changes:**
- All BrowserStack test jobs now use shared concurrency group "browserstack-tests"
  with cancel-in-progress: false to queue tests instead of failing
- Fixed 4 workflows with incomplete summary job dependencies:
  - android-cpp-ci.yml: Added [lint, build] to summary needs
  - android-java-ci.yml: Added [lint, build] to summary needs
  - android-kotlin-ci.yml: Added [lint, build] to summary needs
  - flutter-ci.yml: Added all build jobs to summary needs
- Created `.github/browserstack-devices.json` with device lists for:
  - android-espresso (full + compact)
  - android-appium, android-maestro
  - ios-xcuitest (full + compact)
  - ios-appium, ios-maestro
  - web-selenium

**Impact:**
- Prevents BrowserStack "all parallels in use" queue errors
- Ensures summary jobs have access to all job results they reference
- Centralizes device configuration for future maintenance

**Still TODO (per REFACTOR_PLAN.md):**
- Standardize job names to browserstack-{platform}
- Parameterize device lists (use browserstack-devices.json)
- Standardize instrumentationOptions keys
- Standardize wait times across workflows

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

Co-Authored-By: Claude <[email protected]>
Changed device configuration structure from framework-based (espresso, appium, maestro)
to SDK/app-based (android-java, flutter, react-native, etc.).

Multi-platform SDKs have nested android/ios objects for better organization.

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

Co-Authored-By: Claude <[email protected]>
teodorciuraru and others added 7 commits October 9, 2025 12:44
… info

Replaced duplicate PR fetching and sanitization logic across all 10
BrowserStack workflows with centralized composite action.

Changes:
- Added composite action step before retry blocks in all workflows
- Removed ~306 lines of duplicate code (PR_INFO, sanitization, truncation)
- Replaced PROJECT_NAME/BUILD_NAME variables with composite action outputs
- Fixed Python script build name format (removed # symbol)

Workflows migrated:
✅ android-cpp-ci.yml - single platform
✅ android-java-ci.yml - single platform
✅ android-kotlin-ci.yml - single platform
✅ dotnet-maui-ci.yml - multi-platform (Android + iOS)
✅ flutter-ci.yml - multi-platform (Android + iOS)
✅ java-spring-ci.yml - single platform (uses browserstack.yml config)
✅ kotlin-multiplatform-ci.yml - single platform
✅ react-native-ci.yml - multi-platform (Android + iOS)
✅ react-native-expo-ci.yml - multi-platform (Android + iOS)
✅ swift-ci.yml - single platform

Benefits:
- Single source of truth for build name generation
- Consistent sanitization and truncation logic
- Easy to maintain and update in one place
- No more duplicate BUILD_NAME if/else blocks

Multi-platform workflows use:
- Distinct step IDs: build-info-android, build-info-ios
- Platform suffixes: ' (Android)', ' (iOS)'
- Shorter lengths: title-max-length=90, commit-max-length=130

Single-platform workflows use:
- Step ID: build-info
- No platform suffix
- Default lengths: title-max-length=100, commit-max-length=140
…UILD_ID

Updated 4 workflows to use direct build links instead of project filter:
- android-java-ci.yml
- android-kotlin-ci.yml
- kotlin-multiplatform-ci.yml
- swift-ci.yml

Changes:
- Added job outputs to expose build_id from BrowserStack API response
- Added echo "build_id=$BUILD_ID" >> "$GITHUB_OUTPUT" after extraction
- Updated summary links from project filter to direct build URL

Before: https://app-automate.browserstack.com/builds?project=quickstart+-+{Platform}
After:  https://app-automate.browserstack.com/dashboard/v2/builds/$BUILD_ID

Benefits:
- Direct link to specific build session (more accurate)
- No need to search/filter on BrowserStack dashboard
- Consistent with Flutter, React Native, React Native Expo workflows

Summary link approaches across all workflows:
✅ Dynamic BUILD_ID (7 workflows): android-java, android-kotlin,
   kotlin-multiplatform, swift, flutter, react-native, react-native-expo
✅ Project filter (4 workflows): android-cpp, dotnet-maui, java-spring,
   javascript-web (these don't expose BUILD_ID from their test frameworks)
Added BUILD_ID extraction by querying BrowserStack API after tests complete
for 4 workflows that use SDK/WebDriver (android-cpp, dotnet-maui, java-spring,
javascript-web).

All 11 BrowserStack workflows now use direct BUILD_ID links in summaries with
fallback to project filter for reliability.

Changes:
- Query BrowserStack API after tests to get build_id
- Add job outputs for build_id
- Update summary links to use BUILD_ID with fallback logic
- Use correct API endpoints (app-automate vs automate)

Result: All BrowserStack summary links now route directly to specific build
sessions for maximum accuracy.

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

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

Standardized all BrowserStack workflows to use consistent link format
and fixed project/build naming issues across all workflows.

Changes:
- Standardized all BrowserStack links to use trailing slash format:
  https://[app-]automate.browserstack.com/dashboard/v2/builds/$BUILD_ID/
- Removed fallback links (only show link when BUILD_ID is available)
- Fixed Android CPP project name: "Android C++" → "Android CPP"
- Fixed .NET MAUI project name: "MAUI" → ".NET MAUI"
- Fixed Java Spring to use composite action's build name (removed hardcoded override)
- Fixed Java Spring summary to include lint and build jobs
- Fixed React Native Expo to output build_id and use job result instead of non-existent status output
- Standardized all workflows (android-java, android-kotlin, kotlin-multiplatform, swift, flutter, dotnet-maui) to use trailing slash

Result: All 11 BrowserStack workflows now have:
- Consistent link format with trailing slash
- Correct project names
- Build names using composite action (includes PR title/commit message)
- Working summary links that route to correct build sessions

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

Co-Authored-By: Claude <[email protected]>
Fixed JavaScript Web and Java Spring workflows to only display the
BrowserStack Session section when build_id is available, preventing
empty sections with headers but no links.

Changes:
- JavaScript Web: wrapped entire BrowserStack section in build_id check
- Java Spring: combined not-skipped and build_id checks in single condition

Result: Clean summaries that only show BrowserStack info when links are available
Root cause: composite action was missing GH_TOKEN, causing gh pr view
to fail silently and fall back to 'Build-XXX' format.

Changes:
1. Composite action (.github/actions/get-browserstack-build-info):
   - Added GH_TOKEN env var so gh pr view can authenticate
   - Added debug output to show fetched PR info
   - This fixes ALL 10 workflows using this action

2. .NET MAUI workflow:
   - Changed to separate platform-specific links
   - Removed aggregated 'View All Sessions' link
   - Each platform now links directly to its build ID

3. Android Kotlin workflow:
   - Pass BUILD_NAME/PROJECT_NAME via env vars to retry action
   - Use jq to properly escape values for JSON payload
   - Fixes buildName not being passed to BrowserStack API

4. Kotlin Multiplatform workflow:
   - Same fix as Android Kotlin for proper JSON escaping
   - Ensures PR title shows in BrowserStack build name

5. Test workflow (test-build-info-action.yml):
   - New workflow to test composite action in isolation
   - Shows all outputs in step summary for verification
Improvements to composite action:
1. Replaced sed with tr for character filtering (more portable)
2. Added reference link to BrowserStack docs
3. Added 255 character limit enforcement
4. Better documentation of allowed characters

Character handling:
- Allowed: A-Z a-z 0-9 . : - [ ] / @ & ' _
- Using tr -cd (complement delete) for reliable filtering
- Single quote escaped properly: '\''

Reference: https://www.browserstack.com/docs/automate/selenium/organize-tests
@teodorciuraru teodorciuraru marked this pull request as draft October 9, 2025 19:36
pvditto added a commit that referenced this pull request Oct 10, 2025
@teodorciuraru teodorciuraru force-pushed the teodorciuraru/standardize-browserstack-ci branch from a230ba5 to 81dcf7f Compare October 13, 2025 08:46
JavaScript Web workflow now uses the centralized get-browserstack-build-info
action, making it consistent with all other BrowserStack workflows.

Changes:
- Added build-info action step to javascript-web-ci.yml
- Removed duplicate PR/build name logic from browserstack-test.py (13 lines)
- Pass project and build names via environment variables
- Improved string sanitization (now handled by build-info action)

Benefits:
- Consistent naming across all 11 BrowserStack workflows
- Proper character sanitization for BrowserStack requirements
- Centralized logic for easier maintenance
- More reliable PR info fetching via GitHub CLI

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

Co-Authored-By: Claude <[email protected]>
pvditto added a commit that referenced this pull request Oct 13, 2025
teodorciuraru and others added 2 commits October 13, 2025 13:13
…ntext

Renamed action from get-browserstack-build-info to generate-browserstack-names
and made it auto-derive the project name from the workflow name instead of
requiring it as input.

Changes:
- Renamed action directory and updated metadata
- Project name now auto-derived: "JavaScript Web CI" → "quickstart - JavaScript Web"
- Removed project-name input from all 11 BrowserStack workflows
- Added special case for "Android C++" → "Android CPP"
- Added FIXME comments: build-name generation is broken, returns empty string
- Simplified action: removed unused PR fetching logic, sanitization, etc.

Benefits:
- Zero configuration needed - workflows just call the action
- Eliminates hardcoded project names across 11 workflows
- Ensures naming consistency automatically (follows pattern)
- Less chance for typos/mistakes
- Single source of truth for project naming

Build name generation status:
- FIXME: Currently returns empty string (broken)
- TODO: Needs proper implementation in future PR
- Documented limitations in action comments

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

Co-Authored-By: Claude <[email protected]>
Kotlin Multiplatform only runs Android tests on BrowserStack, so it needs
the ' (Android)' platform suffix to distinguish it from potential iOS tests
in the future.

This ensures the BrowserStack project name will be:
'quickstart - Kotlin Multiplatform (Android)'

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

Co-Authored-By: Claude <[email protected]>
@teodorciuraru
Copy link
Contributor Author

Resuming

Clicking the "view test results" link here doesn't take me to the JavaScript Web results page. Is it the same for you @teodorciuraru ?

Yes. We'll move making links work in summaries to a follow-up ticket.

@teodorciuraru teodorciuraru marked this pull request as ready for review October 13, 2025 10:56
@teodorciuraru
Copy link
Contributor Author

Taking this PR to In Review. It has both WIP but also refactorings that will help on main. We'll tackle the WIP via follow-up tickets, while pointing out the shortcomings in the PR description.

@teodorciuraru teodorciuraru requested a review from Copilot October 13, 2025 11:01
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

Copilot reviewed 48 out of 49 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (1)

.github/actions/generate-browserstack-names/action.yml:1

  • The build name functionality is intentionally disabled with a FIXME comment. This incomplete implementation should be tracked and completed, as build names are important for identifying test runs in BrowserStack.
name: 'Generate BrowserStack Names'

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

Copy link
Contributor

@pvditto pvditto left a comment

Choose a reason for hiding this comment

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

LGTM

@teodorciuraru teodorciuraru enabled auto-merge (squash) October 16, 2025 12:12
@teodorciuraru
Copy link
Contributor Author

  • Waiting on code owner review from busec0, konstantinbe, kristopherjohnson, and/or phatblat.

Yep, we're missing several of these. We'll follow-up with fixes later.

@teodorciuraru teodorciuraru merged commit 3a35a9d into main Oct 16, 2025
62 checks passed
@teodorciuraru teodorciuraru deleted the teodorciuraru/standardize-browserstack-ci branch October 16, 2025 13:08
pvditto added a commit that referenced this pull request Oct 16, 2025
* fix: use correct Flutter version format in update-sdk-versions workflow

The workflow was using flutter-version: "stable" which caused the action
to interpret "stable" as both the version and channel, resulting in the
error "Unable to determine Flutter version for channel: stable version: stable".

Fixed by using flutter-version: '3.x' with channel: 'stable', matching
the pattern used in the flutter-ci.yml workflow.

* Bump version to 4.12.3

* refactor(ci): standardize workflows and add retry mechanisms and centralized config (#185)

* Revert "refactor(ci): standardize workflows and add retry mechanisms and centralized config (#185)"

This reverts commit 5108d49.

* Align Flutter CI with small-peers-ci
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.

5 participants