Skip to content

feat(report): support mobile steps and player views (#3155) #10716

feat(report): support mobile steps and player views (#3155)

feat(report): support mobile steps and player views (#3155) #10716

Workflow file for this run

name: CI
on:
push:
branches:
- main
paths-ignore:
- '**/*.md'
- 'apps/site/**'
- '.changeset/**'
- 'docs/**'
pull_request:
paths-ignore:
- '**/*.md'
- 'apps/site/**'
- '.changeset/**'
- 'docs/**'
workflow_dispatch:
permissions:
contents: read
jobs:
rdp-native:
runs-on: ubuntu-24.04
timeout-minutes: 10
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
- name: Setup Node.js and pnpm
uses: ./.github/actions/setup-node-pnpm
- name: Restore pnpm store
id: rdp-pnpm-cache
uses: ./.github/actions/pnpm-cache/restore
- name: Install dependencies
run: pnpm install --frozen-lockfile --ignore-scripts
- name: Save pnpm store
if: steps.rdp-pnpm-cache.outputs.cache-hit != 'true'
uses: ./.github/actions/pnpm-cache/save
- name: Install RDP build dependencies
run: |
sudo apt-get update
sudo apt-get install -y \
cmake dbus-x11 pkg-config python3-tk \
freerdp3-dev xorgxrdp xrdp
- name: Build RDP helper and native tests
run: |
cmake -S packages/computer/native/rdp -B /tmp/midscene-rdp-build \
-DBUILD_TESTING=ON -DRDP_HELPER_OUTPUT_DIR=/tmp/midscene-rdp-build/bin
cmake --build /tmp/midscene-rdp-build --parallel 2
install -Dm755 /tmp/midscene-rdp-build/bin/rdp-helper \
packages/computer/bin/linux/rdp-helper
- name: Build report and computer packages
run: >-
pnpm exec nx run-many --target=build
--projects="@midscene/report,@midscene/computer" --skip-nx-cache
- name: Test RDP capture and connection policies
run: ctest --test-dir /tmp/midscene-rdp-build --output-on-failure
- name: Start a local RDP desktop
env:
MIDSCENE_XRDP_USERNAME: midscene-rdp-ci
MIDSCENE_XRDP_PASSWORD: midscene-rdp-ci-password
run: |
sudo useradd --create-home --shell /bin/bash "$MIDSCENE_XRDP_USERNAME"
echo "$MIDSCENE_XRDP_USERNAME:$MIDSCENE_XRDP_PASSWORD" | sudo chpasswd
sudo install -o "$MIDSCENE_XRDP_USERNAME" -g "$MIDSCENE_XRDP_USERNAME" \
packages/computer/native/rdp/tests/xrdp_desktop.py \
"/home/$MIDSCENE_XRDP_USERNAME/xrdp_desktop.py"
sudo tee "/home/$MIDSCENE_XRDP_USERNAME/.xsession" >/dev/null <<'EOF'
#!/bin/sh
exec python3 "$HOME/xrdp_desktop.py"
EOF
sudo chown -R "$MIDSCENE_XRDP_USERNAME:$MIDSCENE_XRDP_USERNAME" \
"/home/$MIDSCENE_XRDP_USERNAME"
sudo chmod +x "/home/$MIDSCENE_XRDP_USERNAME/.xsession"
sudo systemctl restart xrdp
for attempt in {1..20}; do
if nc -z 127.0.0.1 3389; then exit 0; fi
sleep 1
done
sudo journalctl -u xrdp -u xrdp-sesman --no-pager
exit 1
- name: Test Midscene RDP end to end against xrdp
env:
AI_TEST_TYPE: computer-rdp
MIDSCENE_XRDP_CI_E2E: '1'
MIDSCENE_XRDP_USERNAME: midscene-rdp-ci
MIDSCENE_XRDP_PASSWORD: midscene-rdp-ci-password
MIDSCENE_REPORT_QUIET: 'true'
MIDSCENE_RUN_DIR: ${{ github.workspace }}/midscene_run
run: >-
pnpm exec nx test @midscene/computer --skip-nx-cache --
tests/ai/rdp/xrdp-ci-e2e.test.ts --retry=0
- name: Print xrdp diagnostics
if: failure()
run: sudo journalctl -u xrdp -u xrdp-sesman --no-pager
- name: Upload Midscene RDP E2E report
if: always()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
if-no-files-found: warn
name: rdp-midscene-report
path: midscene_run/report/rdp-xrdp-ci-e2e.html
main:
# The viewport e2e relies on the hosted image's Chrome window behavior.
runs-on: ubuntu-22.04
strategy:
matrix:
node-version: [24.13.0]
# do NOT provide API keys here. The test cases should not rely on any API keys.
# env:
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
- name: Setup pnpm
uses: pnpm/action-setup@eae0cfeb286e66ffb5155f1a79b90583a127a68b # v2.4.1
with:
version: 9.3.0
- name: Setup Node.js
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: '24.13.0'
- name: Cache Puppeteer dependencies
uses: ./.github/actions/cache/restore
id: cache-puppeteer
with:
path: ~/.cache/puppeteer
key: ${{ runner.os }}-puppeteer-${{ hashFiles('pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-puppeteer-
- name: Install dependencies
run: pnpm install --frozen-lockfile --ignore-scripts
- name: Install puppeteer dependencies
run: |
cd packages/web-integration
npx puppeteer browsers install chrome
- name: Save Puppeteer cache
if: steps.cache-puppeteer.outputs.cache-hit != 'true'
uses: ./.github/actions/cache/save
with:
path: ~/.cache/puppeteer
key: ${{ runner.os }}-puppeteer-${{ hashFiles('pnpm-lock.yaml') }}
- name: Check tsconfig references
run: pnpm run check:references
- name: Build project
run: pnpm run build
- name: Check Report build feedback loop
run: pnpm run check:report-build-feedback-loop
- name: Check CLI CJS bundle on minimum supported Node
run: |
node - <<'EOF'
const { readdirSync, readFileSync, statSync } = require('node:fs');
const { join } = require('node:path');
const root = 'packages/cli/dist/lib';
const files = [];
const collectJsFiles = (dir) => {
for (const entry of readdirSync(dir)) {
const file = join(dir, entry);
if (statSync(file).isDirectory()) {
collectJsFiles(file);
} else if (file.endsWith('.js')) {
files.push(file);
}
}
};
collectJsFiles(root);
const staticRequirePatterns = [
{
name: '@rstest/core',
pattern: /require\((['"])@rstest\/core(?:\/[^'"]*)?\1\)/,
},
{
name: '@rsbuild/core',
pattern: /require\((['"])@rsbuild\/core(?:\/[^'"]*)?\1\)/,
},
];
for (const file of files) {
const content = readFileSync(file, 'utf8');
for (const { name, pattern } of staticRequirePatterns) {
if (pattern.test(content)) {
throw new Error(`${file} contains a static require("${name}")`);
}
}
}
EOF
npx -y node@20.19.0 packages/cli/dist/lib/index.js --version
- name: Type check tests
run: pnpm run type-check:tests
- name: Run tests with coverage
run: pnpm run test:coverage
# Run the Chrome/YAML batch after full-workspace coverage so it does not compete
# with the other Nx projects for runner resources.
- name: Run CLI shared-browser YAML e2e
timeout-minutes: 5
run: pnpm --filter @midscene/cli test:e2e:shared-browser
- name: Upload coverage reports
id: upload-coverage
if: always()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: coverage
path: coverage
if-no-files-found: ignore
- name: Write coverage summary
if: always()
env:
COVERAGE_ARTIFACT_URL: ${{ steps.upload-coverage.outputs.artifact-url }}
run: node scripts/github-coverage-summary.js