fix(test): preserve aiActContext when injecting workflow history #711
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: iOS Simulator | |
| on: | |
| pull_request: | |
| paths: | |
| - '.github/workflows/ios-simulator.yml' | |
| - 'apps/report/**' | |
| - 'packages/ios/**' | |
| - 'packages/webdriver/**' | |
| - 'packages/core/**' | |
| - 'packages/shared/**' | |
| - 'scripts/report-template-utils.mjs' | |
| - 'scripts/validate-core-report-template.mjs' | |
| - 'nx.json' | |
| - 'package.json' | |
| - 'pnpm-lock.yaml' | |
| - 'pnpm-workspace.yaml' | |
| workflow_dispatch: | |
| inputs: | |
| branch: | |
| description: 'Branch to checkout' | |
| required: false | |
| default: 'main' | |
| type: string | |
| permissions: | |
| contents: read | |
| concurrency: | |
| group: ios-simulator-${{ github.event.pull_request.number || inputs.branch || github.ref }} | |
| cancel-in-progress: ${{ github.event_name == 'pull_request' }} | |
| jobs: | |
| ios-simulator: | |
| runs-on: ${{ fromJSON(vars.MAC_SELF_HOSTED_RUNNER_LABELS || '"macos-latest"') }} | |
| timeout-minutes: 70 | |
| env: | |
| CI: '1' | |
| FORCE_COLOR: '0' | |
| MIDSCENE_MODEL_API_KEY: ${{ secrets.MIDSCENE_MODEL_API_KEY }} | |
| MIDSCENE_MODEL_BASE_URL: ${{ vars.MIDSCENE_MODEL_BASE_URL }} | |
| MIDSCENE_MODEL_NAME: ${{ vars.MIDSCENE_MODEL_NAME }} | |
| MIDSCENE_MODEL_FAMILY: ${{ vars.MIDSCENE_MODEL_FAMILY }} | |
| MIDSCENE_MODEL_RETRY_COUNT: '2' | |
| MIDSCENE_MODEL_RETRY_INTERVAL: '60000' | |
| MIDSCENE_REPORT_QUIET: 'true' | |
| MIDSCENE_RUN_DIR: ${{ github.workspace }}/midscene_run | |
| MIDSCENE_IOS_DIAGNOSTICS_DIR: ${{ github.workspace }}/midscene_run/ios-simulator-diagnostics | |
| steps: | |
| - name: Checkout source | |
| uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 | |
| with: | |
| ref: ${{ inputs.branch || github.ref }} | |
| - name: Checkout WebDriverAgent 15.1.6 | |
| uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 | |
| with: | |
| repository: appium/WebDriverAgent | |
| ref: 5f8280e761dc0b5b9b28368e63a8f0cc8d868346 | |
| path: .ci/WebDriverAgent | |
| persist-credentials: false | |
| - name: Inspect iOS runner | |
| shell: bash | |
| run: | | |
| mkdir -p "$MIDSCENE_IOS_DIAGNOSTICS_DIR" | |
| { | |
| sw_vers | |
| uname -a | |
| xcodebuild -version | |
| xcode-select -p | |
| xcrun simctl list runtimes | |
| xcrun simctl list devices available | |
| } 2>&1 | tee "$MIDSCENE_IOS_DIAGNOSTICS_DIR/runner-preflight.log" | |
| - name: Setup Node.js and pnpm | |
| uses: ./.github/actions/setup-node-pnpm | |
| - name: Cache pnpm store | |
| id: pnpm-cache | |
| uses: ./.github/actions/pnpm-cache/restore | |
| - name: Install dependencies | |
| run: pnpm install --frozen-lockfile --ignore-scripts | |
| - name: Save pnpm store | |
| if: steps.pnpm-cache.outputs.cache-hit != 'true' | |
| uses: ./.github/actions/pnpm-cache/save | |
| - name: Build report and iOS packages | |
| id: build | |
| continue-on-error: true | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| pnpm exec nx run-many --target=build --projects="@midscene/report,@midscene/ios" --skip-nx-cache 2>&1 | | |
| tee "$MIDSCENE_IOS_DIAGNOSTICS_DIR/build.log" | |
| node scripts/validate-core-report-template.mjs | |
| - name: Validate iOS package outputs | |
| id: package-smoke | |
| continue-on-error: true | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| node -e "const mod=require('./packages/ios/dist/lib/index.js'); if(typeof mod.IOSDevice!=='function'||typeof mod.IOSAgent!=='function') throw new Error('invalid CJS exports')" | |
| node --input-type=module -e "const mod=await import('./packages/ios/dist/es/index.mjs'); if(typeof mod.IOSDevice!=='function'||typeof mod.IOSAgent!=='function') throw new Error('invalid ESM exports')" | |
| test -f packages/ios/dist/types/index.d.ts | |
| actual_cli_version=$(node packages/ios/bin/midscene-ios --version) | |
| package_version=$(node -p "require('./packages/ios/package.json').version") | |
| expected_cli_version="midscene-ios v${package_version}" | |
| if [[ "$actual_cli_version" != "$expected_cli_version" ]]; then | |
| echo "Unexpected CLI version '$actual_cli_version'; expected '$expected_cli_version'." >&2 | |
| exit 1 | |
| fi | |
| pack_dir="$RUNNER_TEMP/midscene-ios-pack" | |
| mkdir -p "$pack_dir" | |
| pnpm --dir packages/ios pack --pack-destination "$pack_dir" | |
| archive=$(find "$pack_dir" -name '*.tgz' -type f | head -n 1) | |
| test -n "$archive" | |
| tar -tf "$archive" > "$MIDSCENE_IOS_DIAGNOSTICS_DIR/package-files.txt" | |
| for required in \ | |
| package/package.json \ | |
| package/bin/midscene-ios \ | |
| package/dist/lib/cli.js \ | |
| package/dist/lib/index.js \ | |
| package/dist/es/index.mjs \ | |
| package/dist/types/index.d.ts; do | |
| grep -Fxq "$required" "$MIDSCENE_IOS_DIAGNOSTICS_DIR/package-files.txt" | |
| done | |
| - name: Run iOS unit tests | |
| id: unit-tests | |
| continue-on-error: true | |
| shell: bash | |
| run: | | |
| set -o pipefail | |
| pnpm exec nx test @midscene/ios --skip-nx-cache 2>&1 | | |
| tee "$MIDSCENE_IOS_DIAGNOSTICS_DIR/unit-tests.log" | |
| - name: Run iOS Simulator smoke, IOSAppSwitcher AI E2E, and TodoMVC tests | |
| id: simulator-tests | |
| continue-on-error: true | |
| timeout-minutes: 50 | |
| shell: bash | |
| run: bash packages/ios/scripts/run-simulator-ci-smokes.sh | |
| - name: Collect step outcomes | |
| if: always() | |
| shell: bash | |
| env: | |
| BUILD_OUTCOME: ${{ steps.build.outcome }} | |
| PACKAGE_OUTCOME: ${{ steps.package-smoke.outcome }} | |
| UNIT_OUTCOME: ${{ steps.unit-tests.outcome }} | |
| SIMULATOR_OUTCOME: ${{ steps.simulator-tests.outcome }} | |
| run: | | |
| mkdir -p "$MIDSCENE_IOS_DIAGNOSTICS_DIR" | |
| node -e ' | |
| const fs = require("node:fs"); | |
| const path = require("node:path"); | |
| const outcomes = { | |
| build: process.env.BUILD_OUTCOME, | |
| packageSmoke: process.env.PACKAGE_OUTCOME, | |
| unitTests: process.env.UNIT_OUTCOME, | |
| simulatorTests: process.env.SIMULATOR_OUTCOME, | |
| }; | |
| fs.writeFileSync( | |
| path.join(process.env.MIDSCENE_IOS_DIAGNOSTICS_DIR, "host-step-outcomes.json"), | |
| `${JSON.stringify(outcomes, null, 2)}\n`, | |
| ); | |
| ' | |
| - name: Upload iOS Simulator smoke report | |
| if: always() | |
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 | |
| with: | |
| name: ios-simulator-smoke-report | |
| path: midscene_run/report/ios-simulator-smoke.html | |
| if-no-files-found: error | |
| retention-days: 7 | |
| - name: Upload IOSAppSwitcher AI E2E report | |
| if: always() | |
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 | |
| with: | |
| name: ios-app-switcher-ai-e2e-report | |
| path: midscene_run/report/ios-app-switcher-ai-e2e.html | |
| if-no-files-found: error | |
| retention-days: 7 | |
| - name: Upload iOS TodoMVC report | |
| if: always() | |
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 | |
| with: | |
| name: ios-todo-mvc-report | |
| path: midscene_run/report/todo-mvc-ios.html | |
| if-no-files-found: warn | |
| retention-days: 7 | |
| - name: Upload iOS Simulator diagnostics | |
| if: always() | |
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 | |
| with: | |
| name: ios-simulator-diagnostics | |
| path: midscene_run/ios-simulator-diagnostics | |
| if-no-files-found: error | |
| retention-days: 7 | |
| - name: Check iOS validation results | |
| if: always() | |
| shell: bash | |
| run: | | |
| failed=() | |
| [[ '${{ steps.build.outcome }}' == success ]] || failed+=(build) | |
| [[ '${{ steps.package-smoke.outcome }}' == success ]] || failed+=("package smoke") | |
| [[ '${{ steps.unit-tests.outcome }}' == success ]] || failed+=("unit tests") | |
| [[ '${{ steps.simulator-tests.outcome }}' == success ]] || failed+=("simulator tests") | |
| if ((${#failed[@]} > 0)); then | |
| printf 'iOS validation failed: %s\n' "${failed[*]}" >&2 | |
| exit 1 | |
| fi |