




















@@ -245,6 +245,24 @@ jobs:
245245 - name: Build Mantis harness
246246run: pnpm build
247247248+ - name: Setup Go for Crabbox CLI
249+uses: actions/setup-go@v6
250+with:
251+go-version: "1.26.x"
252+cache: false
253+254+ - name: Install Crabbox CLI
255+shell: bash
256+run: |
257+ set -euo pipefail
258+ install_dir="${RUNNER_TEMP}/crabbox"
259+ mkdir -p "$install_dir" "$HOME/.local/bin"
260+ git clone --depth 1 https://github.com/openclaw/crabbox.git "$install_dir/src"
261+ go build -C "$install_dir/src" -o "$HOME/.local/bin/crabbox" ./cmd/crabbox
262+ echo "$HOME/.local/bin" >> "$GITHUB_PATH"
263+ "$HOME/.local/bin/crabbox" --version
264+ "$HOME/.local/bin/crabbox" warmup --help 2>&1 | grep -q -- "-desktop"
265+248266 - name: Prepare baseline and candidate worktrees
249267shell: bash
250268env:
@@ -307,6 +325,14 @@ jobs:
307325OPENCLAW_QA_CONVEX_SECRET_CI: ${{ secrets.OPENCLAW_QA_CONVEX_SECRET_CI }}
308326OPENCLAW_QA_REDACT_PUBLIC_METADATA: "1"
309327OPENCLAW_QA_DISCORD_CAPTURE_CONTENT: "1"
328+MANTIS_DISCORD_VIEWER_CHROME_PROFILE_TGZ_B64: ${{ secrets.MANTIS_DISCORD_VIEWER_CHROME_PROFILE_TGZ_B64 }}
329+MANTIS_DISCORD_VIEWER_CHROME_PROFILE_DIR: ${{ vars.MANTIS_DISCORD_VIEWER_CHROME_PROFILE_DIR }}
330+CRABBOX_COORDINATOR: ${{ secrets.CRABBOX_COORDINATOR }}
331+CRABBOX_COORDINATOR_TOKEN: ${{ secrets.CRABBOX_COORDINATOR_TOKEN }}
332+OPENCLAW_QA_MANTIS_CRABBOX_COORDINATOR: ${{ secrets.OPENCLAW_QA_MANTIS_CRABBOX_COORDINATOR }}
333+OPENCLAW_QA_MANTIS_CRABBOX_COORDINATOR_TOKEN: ${{ secrets.OPENCLAW_QA_MANTIS_CRABBOX_COORDINATOR_TOKEN }}
334+CRABBOX_ACCESS_CLIENT_ID: ${{ secrets.CRABBOX_ACCESS_CLIENT_ID }}
335+CRABBOX_ACCESS_CLIENT_SECRET: ${{ secrets.CRABBOX_ACCESS_CLIENT_SECRET }}
310336CANDIDATE_SHA: ${{ needs.validate_candidate.outputs.candidate_revision }}
311337BASELINE_LABEL: ${{ needs.resolve_request.outputs.baseline_ref }}
312338run: |
@@ -331,7 +357,14 @@ jobs:
331357 local lane="$1"
332358 local repo_root="${GITHUB_WORKSPACE}/${worktree_root}/${lane}"
333359 local output_dir=".artifacts/qa-e2e/mantis/discord-thread-attachment/${lane}"
334- pnpm --dir "$repo_root" openclaw qa discord \
360+ local lane_env=()
361+ if [[ "$lane" == "candidate" ]]; then
362+ lane_env=(
363+ OPENCLAW_QA_DISCORD_CAPTURE_UI_METADATA=1
364+ OPENCLAW_QA_DISCORD_KEEP_THREADS=1
365+ )
366+ fi
367+ env "${lane_env[@]}" pnpm --dir "$repo_root" openclaw qa discord \
335368 --repo-root "$repo_root" \
336369 --output-dir "$output_dir" \
337370 --provider-mode mock-openai \
@@ -347,6 +380,73 @@ jobs:
347380 run_lane baseline
348381 run_lane candidate
349382383+ capture_candidate_discord_web() {
384+ if [[ -z "${MANTIS_DISCORD_VIEWER_CHROME_PROFILE_TGZ_B64:-}" && -z "${MANTIS_DISCORD_VIEWER_CHROME_PROFILE_DIR:-}" ]]; then
385+ echo "::notice::No Mantis Discord viewer browser profile is configured; skipping logged-in Discord Web video."
386+ return 0
387+ fi
388+ CRABBOX_COORDINATOR="${CRABBOX_COORDINATOR:-${OPENCLAW_QA_MANTIS_CRABBOX_COORDINATOR:-}}"
389+ CRABBOX_COORDINATOR_TOKEN="${CRABBOX_COORDINATOR_TOKEN:-${OPENCLAW_QA_MANTIS_CRABBOX_COORDINATOR_TOKEN:-}}"
390+ export CRABBOX_COORDINATOR CRABBOX_COORDINATOR_TOKEN
391+ if [[ -z "${CRABBOX_COORDINATOR_TOKEN:-}" ]]; then
392+ echo "::warning::Crabbox coordinator token missing; skipping logged-in Discord Web video."
393+ return 0
394+ fi
395+396+ local ui_json="$root/candidate/discord-thread-reply-filepath-attachment-ui.json"
397+ if [[ ! -f "$ui_json" ]]; then
398+ echo "::warning::Candidate Discord UI metadata is missing; skipping logged-in Discord Web video."
399+ return 0
400+ fi
401+ local discord_url
402+ discord_url="$(jq -r '.discordWebUrl // empty' "$ui_json")"
403+ if [[ -z "$discord_url" ]]; then
404+ echo "::warning::Candidate Discord UI URL is empty; skipping logged-in Discord Web video."
405+ return 0
406+ fi
407+408+ local desktop_dir="$root/candidate/discord-web"
409+ local profile_args=()
410+ if [[ -n "${MANTIS_DISCORD_VIEWER_CHROME_PROFILE_TGZ_B64:-}" ]]; then
411+ profile_args+=(--browser-profile-archive-env MANTIS_DISCORD_VIEWER_CHROME_PROFILE_TGZ_B64)
412+ fi
413+ if [[ -n "${MANTIS_DISCORD_VIEWER_CHROME_PROFILE_DIR:-}" ]]; then
414+ profile_args+=(--browser-profile-dir "$MANTIS_DISCORD_VIEWER_CHROME_PROFILE_DIR")
415+ fi
416+ pnpm openclaw qa mantis desktop-browser-smoke \
417+ --browser-url "$discord_url" \
418+ "${profile_args[@]}" \
419+ --video-duration 24 \
420+ --output-dir "$desktop_dir" \
421+ --provider hetzner \
422+ --class standard \
423+ --idle-timeout 30m \
424+ --ttl 90m
425+426+ cp "$desktop_dir/desktop-browser-smoke.png" "$root/candidate/discord-thread-reply-filepath-attachment-discord-web.png"
427+ if [[ -f "$desktop_dir/desktop-browser-smoke.mp4" ]]; then
428+ cp "$desktop_dir/desktop-browser-smoke.mp4" "$root/candidate/discord-thread-reply-filepath-attachment-discord-web.mp4"
429+ fi
430+431+ if [[ -f "$root/candidate/discord-thread-reply-filepath-attachment-discord-web.mp4" ]]; then
432+ if ! command -v ffmpeg >/dev/null 2>&1 || ! command -v ffprobe >/dev/null 2>&1; then
433+ sudo apt-get update && sudo apt-get install -y ffmpeg || true
434+ fi
435+ crabbox media preview \
436+ --input "$root/candidate/discord-thread-reply-filepath-attachment-discord-web.mp4" \
437+ --output "$root/candidate/discord-thread-reply-filepath-attachment-discord-web-preview.gif" \
438+ --trimmed-video-output "$root/candidate/discord-thread-reply-filepath-attachment-discord-web-change.mp4" \
439+ --json > "$root/candidate/discord-thread-reply-filepath-attachment-discord-web-preview.json" || {
440+ rm -f "$root/candidate/discord-thread-reply-filepath-attachment-discord-web-preview.gif"
441+ rm -f "$root/candidate/discord-thread-reply-filepath-attachment-discord-web-change.mp4"
442+ rm -f "$root/candidate/discord-thread-reply-filepath-attachment-discord-web-preview.json"
443+ echo "::warning::Could not generate logged-in Discord Web motion preview; keeping screenshot/full MP4."
444+ }
445+ fi
446+ }
447+448+ capture_candidate_discord_web
449+350450 baseline_status="$(jq -r '.scenarios[] | select(.id == "discord-thread-reply-filepath-attachment") | .status' "$root/baseline/discord-qa-summary.json")"
351451 candidate_status="$(jq -r '.scenarios[] | select(.id == "discord-thread-reply-filepath-attachment") | .status' "$root/candidate/discord-qa-summary.json")"
352452 comparison_status="fail"
@@ -380,6 +480,18 @@ jobs:
380480 echo "- Result: \`${comparison_status}\`"
381481 echo "- Baseline screenshot: \`baseline/discord-thread-reply-filepath-attachment-attachment.png\`"
382482 echo "- Candidate screenshot: \`candidate/discord-thread-reply-filepath-attachment-attachment.png\`"
483+ if [[ -f "$root/candidate/discord-thread-reply-filepath-attachment-discord-web.png" ]]; then
484+ echo "- Candidate logged-in Discord Web screenshot: \`candidate/discord-thread-reply-filepath-attachment-discord-web.png\`"
485+ fi
486+ if [[ -f "$root/candidate/discord-thread-reply-filepath-attachment-discord-web-preview.gif" ]]; then
487+ echo "- Candidate logged-in Discord Web preview: \`candidate/discord-thread-reply-filepath-attachment-discord-web-preview.gif\`"
488+ fi
489+ if [[ -f "$root/candidate/discord-thread-reply-filepath-attachment-discord-web-change.mp4" ]]; then
490+ echo "- Candidate logged-in Discord Web change clip: \`candidate/discord-thread-reply-filepath-attachment-discord-web-change.mp4\`"
491+ fi
492+ if [[ -f "$root/candidate/discord-thread-reply-filepath-attachment-discord-web.mp4" ]]; then
493+ echo "- Candidate logged-in Discord Web video: \`candidate/discord-thread-reply-filepath-attachment-discord-web.mp4\`"
494+ fi
383495 } > "$root/mantis-report.md"
384496385497 jq -n \
@@ -402,6 +514,12 @@ jobs:
402514 artifacts: [
403515 { kind: "timeline", lane: "baseline", label: "Baseline missing filePath attachment", path: "baseline/discord-thread-reply-filepath-attachment-attachment.png", targetPath: "baseline.png", alt: "Baseline Discord thread reply without filePath attachment", width: 420 },
404516 { kind: "timeline", lane: "candidate", label: "Candidate includes filePath attachment", path: "candidate/discord-thread-reply-filepath-attachment-attachment.png", targetPath: "candidate.png", alt: "Candidate Discord thread reply with filePath attachment", width: 420 },
517+ { kind: "desktopScreenshot", lane: "candidate", label: "Candidate logged-in Discord Web", path: "candidate/discord-thread-reply-filepath-attachment-discord-web.png", targetPath: "candidate-discord-web.png", alt: "Logged-in Discord Web showing the candidate thread attachment", width: 560, required: false, inline: true },
518+ { kind: "motionPreview", lane: "candidate", label: "Candidate logged-in Discord Web motion", path: "candidate/discord-thread-reply-filepath-attachment-discord-web-preview.gif", targetPath: "candidate-discord-web-preview.gif", alt: "Animated logged-in Discord Web proof for the candidate thread attachment", width: 560, required: false, inline: true },
519+ { kind: "motionClip", lane: "candidate", label: "Candidate logged-in Discord Web change MP4", path: "candidate/discord-thread-reply-filepath-attachment-discord-web-change.mp4", targetPath: "candidate-discord-web-change.mp4", required: false },
520+ { kind: "fullVideo", lane: "candidate", label: "Candidate logged-in Discord Web MP4", path: "candidate/discord-thread-reply-filepath-attachment-discord-web.mp4", targetPath: "candidate-discord-web.mp4", required: false },
521+ { kind: "metadata", lane: "candidate", label: "Candidate logged-in Discord Web preview metadata", path: "candidate/discord-thread-reply-filepath-attachment-discord-web-preview.json", targetPath: "candidate-discord-web-preview.json", required: false },
522+ { kind: "metadata", lane: "candidate", label: "Candidate Discord UI metadata", path: "candidate/discord-thread-reply-filepath-attachment-ui.json", targetPath: "candidate-discord-ui.json", required: false },
405523 { kind: "metadata", lane: "run", label: "Comparison JSON", path: "comparison.json", targetPath: "comparison.json" },
406524 { kind: "report", lane: "run", label: "Mantis report", path: "mantis-report.md", targetPath: "mantis-report.md" }
407525 ]
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。