Skip unrelated required checks without losing their names (#2542)

* fix(ci): skip unrelated required checks cleanly

Matrix jobs had to start no-op runners to preserve interpolated required-check names. Static named jobs let GitHub report genuine skipped conclusions while keeping those names stable.

* fix(ci): gate changes to install patching script

* fix(ci): route cross-package test contracts narrowly

* fix(ci): keep routed contracts merge-blocking

* fix(server): exclude nested test utilities from builds

* fix(ci): cover app-owned native and browser domains

* refactor(ci): align tests with runtime domains

Own browser specs, desktop specs, and Electron-only app code by stable directories so PR routing does not depend on filename conventions. Keep desktop integration coverage inside the required desktop check.

* fix(ci): keep routing and desktop suites isolated

The routing regression must run before dependency installation, and desktop Vitest must not collect Playwright-owned specs.

* fix(ci): isolate desktop e2e runtime

* perf(test): isolate Playwright workers

* perf(test): parallelize Playwright within specs

* fix(test): keep Playwright file scheduling

* fix(test): share dynamic Metro fixture

* fix(test): preserve own-host restart fixtures

* fix(ci): preserve routed contracts after rebase

* Stabilize Playwright wheel-scroll assertions
This commit is contained in:
Mohamed Boudra
2026-08-02 00:56:05 +08:00
committed by GitHub
parent 429155b536
commit 5a30affd7f
256 changed files with 2693 additions and 2674 deletions
@@ -1,94 +0,0 @@
import AsyncStorage from "@react-native-async-storage/async-storage";
import { BrowserAutomationBrowserIdSchema } from "@getpaseo/protocol/browser-automation/rpc-schemas";
import { create } from "zustand";
import { createJSONStorage, persist } from "zustand/middleware";
import {
applyBrowserPatch,
type BrowserIndexState,
type BrowserRecord,
type BrowserRecordPatch,
createBrowserRecord,
normalizeBrowserUrl,
removeBrowserFromIndex,
sanitizeBrowsersForPersist,
trimNonEmpty,
} from "./state";
export type { BrowserRecord } from "./state";
interface BrowserStoreState extends BrowserIndexState {
createBrowser: (input?: { initialUrl?: string }) => string;
updateBrowser: (browserId: string, patch: BrowserRecordPatch) => void;
removeBrowser: (browserId: string) => void;
}
function createBrowserId(): string {
let browserId: string;
if (typeof globalThis.crypto?.randomUUID === "function") {
browserId = globalThis.crypto.randomUUID();
} else {
const randomSuffix = Math.random().toString(16).slice(2) || "0";
browserId = `${Date.now()}-${randomSuffix}`;
}
return BrowserAutomationBrowserIdSchema.parse(browserId);
}
export const useBrowserStore = create<BrowserStoreState>()(
persist(
(set) => ({
browsersById: {},
createBrowser: (input) => {
const browserId = createBrowserId();
const record = createBrowserRecord({
browserId,
initialUrl: input?.initialUrl,
now: Date.now(),
});
set((state) => ({
browsersById: {
...state.browsersById,
[browserId]: record,
},
}));
return browserId;
},
updateBrowser: (browserId, patch) => {
set((state) => applyBrowserPatch(state, browserId, patch));
},
removeBrowser: (browserId) => {
set((state) => removeBrowserFromIndex(state, browserId));
},
}),
{
name: "workspace-browser-store",
storage: createJSONStorage(() => AsyncStorage),
partialize: (state) => sanitizeBrowsersForPersist(state),
},
),
);
export function getBrowserRecord(browserId: string): BrowserRecord | null {
const normalizedBrowserId = trimNonEmpty(browserId);
if (!normalizedBrowserId) {
return null;
}
return useBrowserStore.getState().browsersById[normalizedBrowserId] ?? null;
}
export function createWorkspaceBrowser(input?: { initialUrl?: string }): {
browserId: string;
url: string;
} {
const browserId = useBrowserStore.getState().createBrowser(input);
const record = getBrowserRecord(browserId);
return {
browserId,
url: record?.url ?? normalizeBrowserUrl(input?.initialUrl),
};
}
export function normalizeWorkspaceBrowserUrl(value: string | null | undefined): string {
return normalizeBrowserUrl(value);
}
@@ -1,148 +0,0 @@
import { describe, expect, it } from "vitest";
import {
applyBrowserPatch,
type BrowserIndexState,
createBrowserRecord,
normalizeBrowserUrl,
removeBrowserFromIndex,
sanitizeBrowsersForPersist,
} from "./state";
function withRecords(records: ReturnType<typeof createBrowserRecord>[]): BrowserIndexState {
return {
browsersById: Object.fromEntries(records.map((record) => [record.browserId, record])),
};
}
describe("normalizeBrowserUrl", () => {
it("normalizes local development hosts to http by default", () => {
expect(normalizeBrowserUrl("localhost:8081")).toBe("http://localhost:8081");
expect(normalizeBrowserUrl("localhost/path")).toBe("http://localhost/path");
expect(normalizeBrowserUrl("127.0.0.1:3000/path")).toBe("http://127.0.0.1:3000/path");
expect(normalizeBrowserUrl("192.168.0.8")).toBe("http://192.168.0.8");
expect(normalizeBrowserUrl("[::1]:5173")).toBe("http://[::1]:5173");
});
it("normalizes public hosts to https by default", () => {
expect(normalizeBrowserUrl("example.com")).toBe("https://example.com");
expect(normalizeBrowserUrl("//example.com/path")).toBe("https://example.com/path");
});
it("keeps explicit protocols unchanged", () => {
expect(normalizeBrowserUrl("http://localhost:8081")).toBe("http://localhost:8081");
expect(normalizeBrowserUrl("https://localhost:8081")).toBe("https://localhost:8081");
expect(normalizeBrowserUrl("file:///tmp/example.html")).toBe("file:///tmp/example.html");
});
it("falls back to a default URL when input is blank", () => {
expect(normalizeBrowserUrl(null)).toBe("https://example.com");
expect(normalizeBrowserUrl(" ")).toBe("https://example.com");
});
});
describe("createBrowserRecord", () => {
it("normalizes the initial URL and starts with idle state", () => {
const record = createBrowserRecord({
browserId: "b1",
initialUrl: "localhost:8081",
now: 1000,
});
expect(record).toEqual({
browserId: "b1",
url: "http://localhost:8081",
title: "",
isLoading: false,
canGoBack: false,
canGoForward: false,
faviconUrl: null,
lastError: null,
createdAt: 1000,
});
});
});
describe("applyBrowserPatch", () => {
it("normalizes URL updates", () => {
const initial = withRecords([
createBrowserRecord({ browserId: "b1", initialUrl: "https://a.test", now: 0 }),
]);
const next = applyBrowserPatch(initial, "b1", { url: "example.com/path" });
expect(next.browsersById.b1?.url).toBe("https://example.com/path");
});
it("returns the same state reference when nothing changes", () => {
const initial = withRecords([
createBrowserRecord({ browserId: "b1", initialUrl: "https://a.test", now: 0 }),
]);
const next = applyBrowserPatch(initial, "b1", { url: "https://a.test", title: "" });
expect(next).toBe(initial);
});
it("returns the same state when the browser id is unknown", () => {
const initial = withRecords([
createBrowserRecord({ browserId: "b1", initialUrl: "https://a.test", now: 0 }),
]);
const next = applyBrowserPatch(initial, "missing", { title: "x" });
expect(next).toBe(initial);
});
it("returns the same state when the browser id is blank", () => {
const initial = withRecords([
createBrowserRecord({ browserId: "b1", initialUrl: "https://a.test", now: 0 }),
]);
expect(applyBrowserPatch(initial, " ", { title: "x" })).toBe(initial);
});
});
describe("removeBrowserFromIndex", () => {
it("removes the named browser", () => {
const initial = withRecords([
createBrowserRecord({ browserId: "b1", initialUrl: "https://a.test", now: 0 }),
createBrowserRecord({ browserId: "b2", initialUrl: "https://b.test", now: 0 }),
]);
const next = removeBrowserFromIndex(initial, "b1");
expect(Object.keys(next.browsersById)).toEqual(["b2"]);
});
it("returns the same state when the browser id is unknown", () => {
const initial = withRecords([
createBrowserRecord({ browserId: "b1", initialUrl: "https://a.test", now: 0 }),
]);
expect(removeBrowserFromIndex(initial, "missing")).toBe(initial);
});
it("returns the same state when the browser id is blank", () => {
const initial = withRecords([
createBrowserRecord({ browserId: "b1", initialUrl: "https://a.test", now: 0 }),
]);
expect(removeBrowserFromIndex(initial, " ")).toBe(initial);
});
});
describe("sanitizeBrowsersForPersist", () => {
it("clears transient fields on every record", () => {
const base = createBrowserRecord({ browserId: "b1", initialUrl: "https://a.test", now: 0 });
const state: BrowserIndexState = {
browsersById: {
b1: { ...base, isLoading: true, lastError: "network down" },
},
};
const persisted = sanitizeBrowsersForPersist(state);
expect(persisted.browsersById.b1?.isLoading).toBe(false);
expect(persisted.browsersById.b1?.lastError).toBe(null);
});
});
@@ -1,130 +0,0 @@
export interface BrowserRecord {
browserId: string;
url: string;
title: string;
isLoading: boolean;
canGoBack: boolean;
canGoForward: boolean;
faviconUrl: string | null;
lastError: string | null;
createdAt: number;
}
export type BrowserRecordPatch = Partial<Omit<BrowserRecord, "browserId" | "createdAt">>;
export interface BrowserIndexState {
browsersById: Record<string, BrowserRecord>;
}
export function trimNonEmpty(value: string | null | undefined): string | null {
if (typeof value !== "string") {
return null;
}
const trimmed = value.trim();
return trimmed.length > 0 ? trimmed : null;
}
export function normalizeBrowserUrl(value: string | null | undefined): string {
const trimmed = trimNonEmpty(value);
if (!trimmed) {
return "https://example.com";
}
if (/^(localhost|\d{1,3}(?:\.\d{1,3}){3}|\[[\da-fA-F:.]+])(?::\d+)?(?:[/?#]|$)/.test(trimmed)) {
return `http://${trimmed}`;
}
if (/^[a-zA-Z][a-zA-Z\d+.-]*:/.test(trimmed)) {
return trimmed;
}
if (trimmed.startsWith("//")) {
return `https:${trimmed}`;
}
return `https://${trimmed}`;
}
export function createBrowserRecord(input: {
browserId: string;
initialUrl: string | null | undefined;
now: number;
}): BrowserRecord {
return {
browserId: input.browserId,
url: normalizeBrowserUrl(input.initialUrl),
title: "",
isLoading: false,
canGoBack: false,
canGoForward: false,
faviconUrl: null,
lastError: null,
createdAt: input.now,
};
}
export function applyBrowserPatch<S extends BrowserIndexState>(
state: S,
browserId: string,
patch: BrowserRecordPatch,
): S {
const normalizedBrowserId = trimNonEmpty(browserId);
if (!normalizedBrowserId) {
return state;
}
const existing = state.browsersById[normalizedBrowserId];
if (!existing) {
return state;
}
const nextRecord: BrowserRecord = {
...existing,
...patch,
url: normalizeBrowserUrl(patch.url ?? existing.url),
};
if (
nextRecord.url === existing.url &&
nextRecord.title === existing.title &&
nextRecord.isLoading === existing.isLoading &&
nextRecord.canGoBack === existing.canGoBack &&
nextRecord.canGoForward === existing.canGoForward &&
nextRecord.faviconUrl === existing.faviconUrl &&
nextRecord.lastError === existing.lastError
) {
return state;
}
return {
...state,
browsersById: {
...state.browsersById,
[normalizedBrowserId]: nextRecord,
},
};
}
export function removeBrowserFromIndex<S extends BrowserIndexState>(
state: S,
browserId: string,
): S {
const normalizedBrowserId = trimNonEmpty(browserId);
if (!normalizedBrowserId) {
return state;
}
if (!state.browsersById[normalizedBrowserId]) {
return state;
}
const next = { ...state.browsersById };
delete next[normalizedBrowserId];
return { ...state, browsersById: next };
}
export function sanitizeBrowsersForPersist(state: BrowserIndexState): {
browsersById: Record<string, BrowserRecord>;
} {
return {
browsersById: Object.fromEntries(
Object.entries(state.browsersById).map(([browserId, browser]) => [
browserId,
{ ...browser, isLoading: false, lastError: null },
]),
),
};
}