mirror of
https://github.com/block/buzz.git
synced 2026-11-08 18:31:56 +00:00
Without a Builderlab session, mobile can't tell which agents run on Builderbot, so the Agents page labeled every agent "Manage on desktop", including remote ones. Now, when the community supports remote agents and there's no Builderlab session: - The Agents page shows "Sign in to Builderlab to manage remote agents" with a **Sign in** button (the same reconnect flow as Add). - Agent cards and the navigation subtitle drop the "Manage on desktop" label. - An agent's profile says to sign in to see whether it runs on Builderbot or desktop. ### Before / after iOS simulator, signed in to the remote-agent-pilot community with no Builderlab session. | Before (main) | After (this PR) | | --- | --- | | <img src="https://raw.githubusercontent.com/block/buzz/9be9cebedc8f5ff172e97a3df2cbf505a90e41c4/pr-8907--before-agents.png" width="300"> | <img src="https://raw.githubusercontent.com/block/buzz/9be9cebedc8f5ff172e97a3df2cbf505a90e41c4/pr-8907--after-agents.png" width="300"> | ### Validation - New widget test `agents_signed_out_prompt_test.dart` (runs with `BUZZ_AUTH_DOMAINS`, added to the CI list). - `just mobile-check` and the mobile test suite pass. - Checked the signed-out Agents page in the iOS simulator. buzz-review-completed (manual testing waived by Tom) 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Signed-off-by: Tom Brow <tomb@squareup.com> Co-authored-by: Tom Brow <tomb@squareup.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
289 lines
12 KiB
YAML
289 lines
12 KiB
YAML
name: CI / Clients
|
|
on:
|
|
workflow_call:
|
|
inputs:
|
|
web:
|
|
required: true
|
|
type: boolean
|
|
mobile:
|
|
required: true
|
|
type: boolean
|
|
lane:
|
|
required: true
|
|
type: string
|
|
outputs:
|
|
web_result:
|
|
value: ${{ jobs.results.outputs.web_result }}
|
|
mobile_result:
|
|
value: ${{ jobs.results.outputs.mobile_result }}
|
|
|
|
env:
|
|
CARGO_TERM_COLOR: always
|
|
BUZZ_TEST_POSTGRES_PASSWORD: buzz_dev
|
|
PLAYWRIGHT_BROWSERS_PATH: ${{ github.workspace }}/.cache/ms-playwright
|
|
|
|
jobs:
|
|
web:
|
|
name: Web
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 15
|
|
if: inputs.lane == 'required' && (github.event_name == 'push' || inputs.web)
|
|
permissions:
|
|
contents: read
|
|
steps:
|
|
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
|
with:
|
|
fetch-depth: 2
|
|
- uses: cashapp/activate-hermit@cea9af7913204a965fd488637a8d1811bba2e616 # v1
|
|
- name: Get pnpm store directory
|
|
id: pnpm-cache
|
|
run: echo "STORE_PATH=$(pnpm store path --silent)" >> "$GITHUB_OUTPUT"
|
|
- name: Restore pnpm store cache
|
|
uses: actions/cache/restore@caa296126883cff596d87d8935842f9db880ef25 # v5
|
|
with:
|
|
path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
|
|
key: pnpm-${{ runner.os }}-${{ hashFiles('**/pnpm-lock.yaml') }}
|
|
restore-keys: pnpm-${{ runner.os }}-
|
|
- name: Install dependencies
|
|
run: pnpm install --frozen-lockfile
|
|
- name: Web lint and format
|
|
run: just web-check
|
|
- name: Web build
|
|
run: just web-build
|
|
- name: Save pnpm store cache
|
|
if: github.event_name == 'push'
|
|
uses: actions/cache/save@caa296126883cff596d87d8935842f9db880ef25 # v5
|
|
with:
|
|
path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
|
|
key: pnpm-${{ runner.os }}-${{ hashFiles('**/pnpm-lock.yaml') }}
|
|
|
|
# Mobile lanes run in parallel; the required check reads the combined
|
|
# matrix result. Test shards split files, so each compiles only its own.
|
|
mobile:
|
|
name: Mobile (${{ matrix.name }})
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 30
|
|
if: inputs.lane == 'required' && (github.event_name == 'push' || inputs.mobile)
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
include:
|
|
- name: Checks
|
|
lane: checks
|
|
- name: Tests 1/3
|
|
lane: test
|
|
shard: 0
|
|
- name: Tests 2/3
|
|
lane: test
|
|
shard: 1
|
|
- name: Tests 3/3
|
|
lane: test
|
|
shard: 2
|
|
- name: Android
|
|
lane: android
|
|
permissions:
|
|
contents: read
|
|
steps:
|
|
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
|
with:
|
|
fetch-depth: 2
|
|
- uses: cashapp/activate-hermit@cea9af7913204a965fd488637a8d1811bba2e616 # v1
|
|
- name: Compute Hermit cache key
|
|
id: hermit-bin-hash
|
|
run: |
|
|
hash="$(find ./bin ! -type d | sort | xargs openssl sha256 | openssl sha256 -r | cut -d' ' -f1)"
|
|
echo "hash=$hash" >> "$GITHUB_OUTPUT"
|
|
- name: Restore Hermit package cache
|
|
id: hermit-cache
|
|
uses: actions/cache/restore@caa296126883cff596d87d8935842f9db880ef25 # v5
|
|
with:
|
|
path: ~/.cache/hermit/pkg
|
|
key: ${{ runner.os }}-hermit-cache-${{ steps.hermit-bin-hash.outputs.hash }}
|
|
restore-keys: ${{ runner.os }}-hermit-cache-
|
|
- name: Prime Flutter SDK
|
|
run: flutter --version
|
|
- name: Save Hermit package cache
|
|
if: always() && steps.hermit-cache.outputs.cache-hit != 'true'
|
|
uses: actions/cache/save@caa296126883cff596d87d8935842f9db880ef25 # v5
|
|
continue-on-error: true
|
|
with:
|
|
path: ~/.cache/hermit/pkg
|
|
key: ${{ runner.os }}-hermit-cache-${{ steps.hermit-bin-hash.outputs.hash }}
|
|
- name: Restore pub cache
|
|
id: pub-cache
|
|
uses: actions/cache/restore@caa296126883cff596d87d8935842f9db880ef25 # v5
|
|
with:
|
|
path: ~/.pub-cache
|
|
key: pub-${{ runner.os }}-${{ hashFiles('mobile/pubspec.lock') }}
|
|
restore-keys: pub-${{ runner.os }}-
|
|
- name: Install dependencies
|
|
run: cd mobile && flutter pub get
|
|
- name: Save pub cache
|
|
if: always() && steps.pub-cache.outputs.cache-hit != 'true'
|
|
uses: actions/cache/save@caa296126883cff596d87d8935842f9db880ef25 # v5
|
|
continue-on-error: true
|
|
with:
|
|
path: ~/.pub-cache
|
|
key: pub-${{ runner.os }}-${{ hashFiles('mobile/pubspec.lock') }}
|
|
- name: Format check
|
|
if: matrix.lane == 'checks'
|
|
run: cd mobile && dart format --output=none --set-exit-if-changed .
|
|
- name: Analyze
|
|
if: matrix.lane == 'checks'
|
|
run: cd mobile && flutter analyze
|
|
- name: Test
|
|
if: matrix.lane == 'test'
|
|
run: /bin/bash scripts/mobile-test-shard.sh ${{ matrix.shard }} 3 --dart-define=BUZZ_PUSH_GATEWAY_URL=https://push.example
|
|
- name: Test native secp256k1 package
|
|
if: matrix.lane == 'checks'
|
|
run: cd mobile/packages/buzz_secp256k1 && dart pub get && dart test
|
|
- name: Test configured authentication domains
|
|
if: matrix.lane == 'checks'
|
|
run: >-
|
|
cd mobile && flutter test
|
|
--dart-define=BUZZ_PUSH_GATEWAY_URL=https://push.example
|
|
--dart-define=BUZZ_AUTH_DOMAINS=buzz.xyz,builderlab.xyz,builderlabstaging.xyz
|
|
test/shared/auth/community_entry_requirements_test.dart
|
|
test/features/invites/invite_join_provider_test.dart
|
|
test/features/onboarding/onboarding_entry_routes_test.dart
|
|
test/shared/hosted/hosted_environment_test.dart
|
|
test/shared/hosted/self_hosted_entry_test.dart
|
|
test/features/agents/agents_signed_out_prompt_test.dart
|
|
test/features/agents/agents_restore_prompt_test.dart
|
|
test/shared/hosted/relay_auth_isolation_test.dart
|
|
test/features/onboarding/hosted_app_gate_environment_test.dart
|
|
test/features/onboarding/hosted_journeys_test.dart
|
|
test/features/onboarding/hosted_communities_test.dart
|
|
test/features/pairing/pairing_hosted_handoff_test.dart
|
|
test/shared/agents/remote_agents_test.dart
|
|
test/features/agents
|
|
- name: Test mobile without push configuration
|
|
if: matrix.lane == 'checks'
|
|
run: cd mobile && flutter test test/shared/push/push_unconfigured_build_test.dart
|
|
- name: Test mobile recipe argument forwarding
|
|
if: matrix.lane == 'checks'
|
|
run: /bin/bash scripts/test-mobile-gateway-recipes.sh
|
|
# ubuntu-latest (26.04) defaults to JDK 25, which Gradle 8.14 does not
|
|
# support. Pin the JDK 17 the 24.04 image used.
|
|
- name: Set up JDK 17
|
|
if: matrix.lane == 'android'
|
|
uses: actions/setup-java@b843ebf9b913146b38da2eaa7aeddf76074ae1ad # v6.1.0
|
|
with:
|
|
distribution: temurin
|
|
java-version: "17"
|
|
- name: Restore Gradle cache
|
|
if: matrix.lane == 'android'
|
|
uses: actions/cache/restore@caa296126883cff596d87d8935842f9db880ef25 # v5
|
|
with:
|
|
path: |
|
|
~/.gradle/caches
|
|
~/.gradle/wrapper
|
|
key: gradle-${{ runner.os }}-${{ hashFiles('mobile/android/**/*.gradle*', 'mobile/android/gradle/wrapper/gradle-wrapper.properties', 'mobile/pubspec.lock') }}
|
|
restore-keys: gradle-${{ runner.os }}-
|
|
# The Hermit package cache above holds only Flutter, so the build's first
|
|
# just and cmake calls download them.
|
|
- name: Fetch Hermit tools
|
|
if: matrix.lane == 'android'
|
|
run: |
|
|
scripts/ci-hermit-retry.sh ./bin/just --version
|
|
scripts/ci-hermit-retry.sh ./bin/cmake --version
|
|
# SDK component and plugin downloads intermittently fail on hosted
|
|
# runners; retry once only for those, so real build failures still fail.
|
|
- name: Build Android debug APK
|
|
if: matrix.lane == 'android'
|
|
run: |
|
|
set -o pipefail
|
|
log="$RUNNER_TEMP/android-build.log"
|
|
if ! just mobile-build-android 2>&1 | tee "$log"; then
|
|
grep -qE 'InstallFailedException|Could not (resolve|GET|download)' "$log"
|
|
just mobile-build-android
|
|
fi
|
|
- name: Test Android JVM units
|
|
if: matrix.lane == 'android'
|
|
run: cd mobile/android && ./gradlew :app:testDebugUnitTest --console=plain
|
|
- name: Save Gradle cache
|
|
if: matrix.lane == 'android' && github.event_name == 'push'
|
|
uses: actions/cache/save@caa296126883cff596d87d8935842f9db880ef25 # v5
|
|
continue-on-error: true
|
|
with:
|
|
path: |
|
|
~/.gradle/caches
|
|
~/.gradle/wrapper
|
|
key: gradle-${{ runner.os }}-${{ hashFiles('mobile/android/**/*.gradle*', 'mobile/android/gradle/wrapper/gradle-wrapper.properties', 'mobile/pubspec.lock') }}
|
|
|
|
# The unsigned release build needs nothing from the native lane, so it runs
|
|
# beside it instead of after the simulator tests.
|
|
mobile-swift:
|
|
name: Mobile Swift (${{ matrix.name }})
|
|
runs-on: macos-latest
|
|
timeout-minutes: 45
|
|
if: inputs.lane == 'mobile-swift' && inputs.mobile
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
include:
|
|
- name: Native
|
|
lane: native
|
|
- name: Release
|
|
lane: release
|
|
steps:
|
|
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
|
- uses: cashapp/activate-hermit@cea9af7913204a965fd488637a8d1811bba2e616 # v1
|
|
- name: Install Flutter dependencies
|
|
run: cd mobile && flutter pub get
|
|
# `swift test` builds BuzzPushKit; the Release lane covers its release build.
|
|
- name: Test
|
|
if: matrix.lane == 'native'
|
|
run: swift test --package-path mobile/ios/BuzzPushKit
|
|
- name: Test native pagination geometry
|
|
if: matrix.lane == 'native'
|
|
run: /bin/bash scripts/test-mobile-pagination.sh
|
|
- name: Generate iOS build configuration
|
|
if: matrix.lane == 'native'
|
|
run: cd mobile && flutter build ios --simulator --debug --no-pub --config-only
|
|
# Build the complete simulator app and RunnerTests once, in the
|
|
# background, while the simulator boots and runs the native-control
|
|
# scripts. The build also guards Apple Silicon simulator linking (#7646).
|
|
- name: Test native controls and Runner unit tests
|
|
if: matrix.lane == 'native'
|
|
run: |
|
|
device=$(xcrun simctl create "Native tests" "iPhone 16")
|
|
trap 'xcrun simctl shutdown "$device"; xcrun simctl delete "$device"' EXIT
|
|
xcode=(xcodebuild -workspace mobile/ios/Runner.xcworkspace -scheme Runner
|
|
-configuration Debug -destination "platform=iOS Simulator,id=$device"
|
|
CODE_SIGNING_ALLOWED=NO)
|
|
build_log="$RUNNER_TEMP/runner-build.log"
|
|
"${xcode[@]}" build-for-testing > "$build_log" 2>&1 &
|
|
build=$!
|
|
xcrun simctl boot "$device"
|
|
xcrun simctl bootstatus "$device" -b
|
|
/bin/bash scripts/test-mobile-pagination-accessibility.sh "$device"
|
|
/bin/bash scripts/test-mobile-carousel.sh "$device"
|
|
/bin/bash scripts/test-mobile-member-picker.sh "$device"
|
|
/bin/bash scripts/test-mobile-me-agent-accessibility.sh "$device"
|
|
if ! wait "$build"; then
|
|
cat "$build_log"
|
|
exit 1
|
|
fi
|
|
tail -n 5 "$build_log"
|
|
"${xcode[@]}" -parallel-testing-enabled NO -only-testing:RunnerTests \
|
|
test-without-building
|
|
- name: Build complete unsigned iOS release
|
|
if: matrix.lane == 'release'
|
|
run: |
|
|
/bin/bash scripts/test-mobile-gateway-recipes.sh
|
|
cd mobile && flutter build ios --release --no-codesign --no-pub
|
|
|
|
results:
|
|
name: Results
|
|
if: ${{ always() }}
|
|
needs: [web, mobile, mobile-swift]
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 5
|
|
permissions: {}
|
|
outputs:
|
|
web_result: ${{ needs.web.result }}
|
|
mobile_result: ${{ needs.mobile.result }}
|
|
steps:
|
|
- run: echo "Captured client job results"
|