mirror of
https://github.com/feder-cr/invisible_playwright.git
synced 2026-06-13 08:55:12 +02:00
ci: macOS gate tolerates the runner's missing WebGL; add verify-cloak
The firefox-10 build gated green on all 5 targets but both macOS gate legs failed. The cloak/webgl guards hard-required a live WebGL context, and macOS GitHub runners expose none in the CI session (no software-GL fallback, unlike Linux llvmpipe and Windows WARP). The cloak renders fine there anyway, which the non-blank screenshot proves, so on the mac legs the WebGL-present check now self-skips and the cocoa cloak is validated via the screenshot plus CGWindowAlpha. The gamma masking guard skips on mac too (platform-agnostic C++, covered on Linux and Windows). verify-cloak.yml re-runs these guards against a prior build run's artifacts with no rebuild, so a test-only fix like this is validated against the real binaries in minutes instead of a 3h rebuild.
This commit is contained in:
parent
d4db15d37b
commit
a950537f0a
4 changed files with 131 additions and 7 deletions
15
.github/workflows/release.yml
vendored
15
.github/workflows/release.yml
vendored
|
|
@ -344,11 +344,16 @@ jobs:
|
|||
# CLOAK + WEBGL-MASKING GUARDS — run the wrapper's e2e cloak/gamma checks
|
||||
# against THIS leg's freshly-built artifact, on its native runner. The
|
||||
# wrapper's headless=True is headed+hidden (cloak on Win/macOS, its own
|
||||
# Xvfb on Linux), so software-GL rendering works on the GPU-less hosts.
|
||||
# test_cloak asserts the window is hidden (Windows DWMWA_CLOAKED / macOS
|
||||
# CGWindowAlpha) AND still renders — the macOS leg is the only place the
|
||||
# cocoa cloak patch gets RUN. The webgl guard catches a regression of the
|
||||
# gamma readPixels noise back to the pixelscan-maskable ±1 spike form.
|
||||
# Xvfb on Linux). Linux (Xvfb + llvmpipe) and Windows (WARP) give a
|
||||
# software WebGL context on the GPU-less hosts, so the WebGL-dependent
|
||||
# assertions run there. macOS GitHub runners expose NO WebGL in the CI
|
||||
# session at all (even vanilla Firefox; macOS has no software-GL fallback),
|
||||
# so on the mac legs the WebGL checks self-skip and the cloak is validated
|
||||
# via its non-blank screenshot + CGWindowAlpha == 0. test_cloak asserts the
|
||||
# window is hidden (Windows DWMWA_CLOAKED / macOS CGWindowAlpha) AND still
|
||||
# renders — the macOS leg is the only place the cocoa cloak patch gets RUN.
|
||||
# The webgl guard catches a regression of the gamma readPixels noise back to
|
||||
# the pixelscan-maskable ±1 spike form (covered on Linux + Windows).
|
||||
- name: Install pyobjc Quartz (macOS — to read the cloak window alpha)
|
||||
if: matrix.kind == 'mac'
|
||||
run: python -m pip install --quiet pyobjc-framework-Quartz
|
||||
|
|
|
|||
103
.github/workflows/verify-cloak.yml
vendored
Normal file
103
.github/workflows/verify-cloak.yml
vendored
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
# verify-cloak.yml — re-runnable CLOAK + WEBGL-MASKING GUARDS for an EXISTING
|
||||
# build run's artifacts, WITHOUT rebuilding Firefox (~3h on the mac legs).
|
||||
#
|
||||
# release.yml runs these same guards in its `gate` job against each freshly-built
|
||||
# artifact. This re-runs them against the artifacts of a PRIOR build run (input
|
||||
# `run_id`) using the CURRENT wrapper code on the default branch — so a test-only
|
||||
# fix (e.g. making the macOS leg tolerant of the runner's missing WebGL) can be
|
||||
# validated against the real binaries in ~10 min instead of paying a full rebuild.
|
||||
#
|
||||
# Same guard command as release.yml's gate. Headed-but-cloaked; zero proxy / zero
|
||||
# secrets. The macOS legs are the only place the cocoa cloak patch actually RUNS.
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
name: verify-cloak
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
run_id:
|
||||
description: 'build run id whose asset-* artifacts to re-gate (e.g. 27346856197)'
|
||||
required: true
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
actions: read # download-artifact needs this to read another run's artifacts
|
||||
|
||||
jobs:
|
||||
guard:
|
||||
name: guard-${{ matrix.leg }}
|
||||
runs-on: ${{ matrix.runner }}
|
||||
timeout-minutes: 25
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
# Same legs/runners/assets as release.yml's gate matrix.
|
||||
include:
|
||||
- leg: linux-x86_64
|
||||
runner: ubuntu-24.04
|
||||
kind: linux
|
||||
asset: firefox-150.0.1-stealth-linux-x86_64.tar.gz
|
||||
- leg: linux-arm64
|
||||
runner: ubuntu-24.04-arm
|
||||
kind: linux
|
||||
asset: firefox-150.0.1-stealth-linux-arm64.tar.gz
|
||||
- leg: win-x86_64
|
||||
runner: windows-latest
|
||||
kind: win
|
||||
asset: firefox-150.0.1-stealth-win-x86_64.zip
|
||||
- leg: macos-arm64
|
||||
runner: macos-15
|
||||
kind: mac
|
||||
asset: firefox-150.0.1-stealth-macos-arm64.tar.gz
|
||||
- leg: macos-x86_64
|
||||
runner: macos-15-intel
|
||||
kind: mac
|
||||
asset: firefox-150.0.1-stealth-macos-x86_64.tar.gz
|
||||
steps:
|
||||
- name: Checkout wrapper (current default branch — the FIXED tests)
|
||||
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
|
||||
with: { fetch-depth: 1 }
|
||||
- name: Download build asset from the prior run (no rebuild)
|
||||
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
|
||||
with:
|
||||
name: asset-${{ matrix.leg }}
|
||||
path: art
|
||||
run-id: ${{ github.event.inputs.run_id }}
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
|
||||
with: { python-version: '3.11' }
|
||||
- name: Install Playwright driver (no bundled browser — we override executable_path)
|
||||
# Single-source pin (see release.yml); the wrapper enforces juggler compat.
|
||||
shell: bash
|
||||
run: python -m pip install --quiet "playwright==$(cat scripts/playwright_pin.txt)"
|
||||
- name: Linux system deps for headless firefox
|
||||
if: matrix.kind == 'linux'
|
||||
run: sudo "$(which python)" -m playwright install-deps firefox
|
||||
- name: Extract + locate firefox binary
|
||||
shell: bash
|
||||
run: |
|
||||
set -e
|
||||
mkdir -p ff
|
||||
A="art/${{ matrix.asset }}"
|
||||
case "${{ matrix.kind }}" in
|
||||
win) python -c "import zipfile; zipfile.ZipFile('$A').extractall('ff')"; EXE="ff/firefox.exe";;
|
||||
linux) tar xzf "$A" -C ff; EXE="ff/firefox";;
|
||||
mac) tar xzf "$A" -C ff; EXE="ff/Firefox.app/Contents/MacOS/firefox";;
|
||||
esac
|
||||
[ -e "$EXE" ] || { echo "ERROR: firefox binary not found at $EXE"; exit 1; }
|
||||
chmod +x "$EXE" 2>/dev/null || true
|
||||
echo "FF_EXE=$EXE" >> "$GITHUB_ENV"
|
||||
echo "located: $EXE"
|
||||
- name: Install pyobjc Quartz (macOS — to read the cloak window alpha)
|
||||
if: matrix.kind == 'mac'
|
||||
run: python -m pip install --quiet pyobjc-framework-Quartz
|
||||
- name: Cloak + WebGL-masking guards (headed)
|
||||
shell: bash
|
||||
run: |
|
||||
python -m pip install --quiet ".[dev]"
|
||||
INVPW_BINARY_PATH="$FF_EXE" python -m pytest \
|
||||
tests/test_cloak.py \
|
||||
"tests/test_fingerprint_surface.py::test_webgl_readpixels_no_masking_signature" \
|
||||
-m e2e -o addopts='' -q
|
||||
|
|
@ -91,9 +91,18 @@ def test_cloak_hides_window_but_keeps_rendering(firefox_binary):
|
|||
shot = page.screenshot()
|
||||
assert len(shot) > 3000, "cloaked window produced a blank screenshot (rendering paused)"
|
||||
|
||||
# 2) real WebGL present (native headless has none) -> headed pipeline intact.
|
||||
# 2) headed pipeline intact: a real WebGL context (Playwright's native
|
||||
# headless has none). Linux (Xvfb + llvmpipe) and Windows (WARP) give a
|
||||
# software context on the GPU-less runners, so a missing context there
|
||||
# is a real regression -> hard fail. macOS GitHub runners expose NO
|
||||
# WebGL in the CI session at all (even vanilla Firefox), and macOS has
|
||||
# no software-GL fallback; the cloak's "still rendering" property is
|
||||
# already proven by the non-blank screenshot above, so we don't also
|
||||
# require a live WebGL context there.
|
||||
renderer = page.evaluate(_WEBGL_RENDERER)
|
||||
assert renderer and renderer != "NO-WEBGL", f"no real WebGL under cloak: {renderer!r}"
|
||||
webgl_ok = bool(renderer) and renderer != "NO-WEBGL"
|
||||
if not (sys.platform == "darwin" and not webgl_ok):
|
||||
assert webgl_ok, f"no real WebGL under cloak: {renderer!r}"
|
||||
|
||||
# 3) the window is actually hidden (per-platform).
|
||||
if sys.platform == "win32":
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ Run only this file:
|
|||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
import sys
|
||||
|
||||
import pytest
|
||||
|
||||
|
|
@ -296,6 +297,12 @@ def test_webgl_readpixels_no_masking_signature(page):
|
|||
~300+ 'spikes' and pixelscan flagged it as masking; the gamma remap leaves
|
||||
the gradient smooth (~0 spikes). Regression guard for the gamma fix."""
|
||||
res = _ev(page, _WEBGL_MASKING_PROBE)
|
||||
if res.get("error") == "no-webgl" and sys.platform == "darwin":
|
||||
pytest.skip(
|
||||
"macOS CI runners expose no WebGL (no software-GL fallback); the gamma "
|
||||
"readPixels remap is platform-agnostic C++ and is exercised by the Linux "
|
||||
"(Xvfb/llvmpipe) and Windows (WARP) gates."
|
||||
)
|
||||
assert "error" not in res, f"WebGL probe failed: {res}"
|
||||
# genuine / gamma -> ~0; the rejected +-1 algorithm produced ~320.
|
||||
assert res["spikes"] < 30, (
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue