Merge remote-tracking branch 'origin/master' into fix/coverage-fork-exit-order
This commit is contained in:
commit
838c1e5f25
3 files changed
+38
-13
No files matched your search
@@ -153,11 +153,15 @@ jobs:
|
||||
retention-days: 7
|
||||
|
||||
# Blacksmith x64 CI builds use 2 vCPU for compilation, bundling, and wheel smokes.
|
||||
# Release macOS builds use larger GitHub runners; ordinary CI and direct
|
||||
# builder dispatches retain the standard native target matrix.
|
||||
build:
|
||||
needs: [plan, sdk-wheel]
|
||||
name: ${{ matrix.target }}
|
||||
runs-on: >-
|
||||
${{ inputs.ci && !inputs.release && matrix.target == 'node24-linux-x64'
|
||||
${{ inputs.release && matrix.target == 'node24-macos-x64' && 'macos-15-large'
|
||||
|| inputs.release && matrix.target == 'node24-macos-arm64' && 'macos-15-xlarge'
|
||||
|| inputs.ci && !inputs.release && matrix.target == 'node24-linux-x64'
|
||||
&& vars.DSH_CI_FAILOVER_LINUX == 'blacksmith' && 'blacksmith-2vcpu-ubuntu-2404'
|
||||
|| inputs.ci && !inputs.release && matrix.target == 'node24-win-x64'
|
||||
&& vars.DSH_CI_FAILOVER_WINDOWS == 'blacksmith' && 'blacksmith-2vcpu-windows-2025'
|
||||
|
||||
@@ -111,6 +111,8 @@ interface ScrollWorld {
|
||||
|
||||
interface ScrollWorldOptions {
|
||||
readonly failureShot: string
|
||||
/** Install a controllable browser clock before boot; omitted worlds use real time. */
|
||||
readonly controlledClock?: boolean
|
||||
readonly paceMs?: number
|
||||
readonly replay?: ReplayOverrideDoc
|
||||
readonly seeds: readonly { fixture: ChatScrollFixture; id: string }[]
|
||||
@@ -206,6 +208,7 @@ async function launchScrollWorld(options: ScrollWorldOptions): Promise<ScrollWor
|
||||
scaffold.ctx.on('session/event', (_session, event: SessionEvent) => { events.push(event) })
|
||||
scaffold.ctx.on('agent/assistant-stream', ({ frame }) => { assistantFrames.push(frame) })
|
||||
page = await newEnglishPage(browser, 900)
|
||||
if (options.controlledClock) await page.clock.install()
|
||||
const tripwire = watchConsole(page)
|
||||
await page.goto(scaffold.authenticatedUrl, { waitUntil: 'load' })
|
||||
await page.waitForSelector('[class*="frame"]', { timeout: 30_000 })
|
||||
@@ -590,8 +593,10 @@ describe('web e2e: long Chat scroll contract', () => {
|
||||
const artifactRoot = fileURLToPath(new URL('../../../.artifacts/screenshots/visible-fold/', import.meta.url))
|
||||
await mkdir(artifactRoot, { recursive: true })
|
||||
const evidence = await mkdtemp(join(artifactRoot, `${scenario.name}-`))
|
||||
const controlledClock = scenario.name === 'content-growth-during-fold' || scenario.name === 'cancel-all-during-fold'
|
||||
await withScrollWorld({
|
||||
failureShot: `visible-fold-${scenario.name}`,
|
||||
controlledClock,
|
||||
replay: [replayEntry(textStream('VISIBLE_FOLD_REPLY', 'VISIBLE_FOLD_DONE', 2))],
|
||||
seeds: [{ fixture, id: `visible-fold-${scenario.name}` }],
|
||||
}, async (world) => {
|
||||
@@ -727,6 +732,7 @@ describe('web e2e: long Chat scroll contract', () => {
|
||||
raceApplied = true
|
||||
column.style.paddingBottom = '320px'
|
||||
}
|
||||
if (raceApplied) host.setAttribute('data-fold-race-applied', '')
|
||||
}
|
||||
const message = [...column.querySelectorAll<HTMLElement>('[data-submission-echo], [data-chat-flow-kind="user"]')]
|
||||
.find(element => element.textContent?.includes(marker))
|
||||
@@ -743,6 +749,7 @@ describe('web e2e: long Chat scroll contract', () => {
|
||||
host.addEventListener('dsh-test-fold-stop', () => {
|
||||
cancelAnimationFrame(frame); sample()
|
||||
host.removeEventListener('dsh-test-fold-growth', markGrowth)
|
||||
host.removeAttribute('data-fold-race-applied')
|
||||
host.removeAttribute('data-fold-probe-ready'); resolveTrace(samples)
|
||||
}, { once: true })
|
||||
sample(); host.setAttribute('data-fold-probe-ready', ''); frame = requestAnimationFrame(tick)
|
||||
@@ -752,11 +759,25 @@ describe('web e2e: long Chat scroll contract', () => {
|
||||
let samples: Awaited<typeof trace> = []
|
||||
try {
|
||||
settled = world.scaffold.whenTurnSettled(30_000)
|
||||
if (scenario.name === 'cancel-all-during-fold') {
|
||||
await page.getByRole('button', { name: 'Send message', exact: true }).evaluate((button) => {
|
||||
if (!(button instanceof HTMLButtonElement)) throw new Error('Send control is not a button')
|
||||
button.click()
|
||||
})
|
||||
if (controlledClock) {
|
||||
// Advance every animation frame so the race cannot miss the intermediate fold height.
|
||||
await page.clock.pauseAt(await page.evaluate(() => Date.now() + 1000))
|
||||
try {
|
||||
await page.getByRole('button', { name: 'Send message', exact: true }).evaluate((button) => {
|
||||
if (!(button instanceof HTMLButtonElement)) throw new Error('Send control is not a button')
|
||||
button.click()
|
||||
})
|
||||
await expect.poll(async () => {
|
||||
await page.clock.runFor(16)
|
||||
return page.locator('[data-fold-race-applied]').count()
|
||||
}, { timeout: 10_000 }).toBe(1)
|
||||
await expect.poll(async () => {
|
||||
await page.clock.runFor(16)
|
||||
return page.locator('[data-chat-motion="collapse"]').count()
|
||||
}, { timeout: 10_000 }).toBe(0)
|
||||
} finally {
|
||||
await page.clock.resume()
|
||||
}
|
||||
} else await page.getByRole('button', { name: 'Send message', exact: true }).click()
|
||||
await promptBlocked.promise
|
||||
await page.getByText(input, { exact: true }).waitFor()
|
||||
|
||||
@@ -929,19 +929,19 @@ describe('Runtime and LLM e2e Blacksmith routing', () => {
|
||||
it('keeps native release and dispatch builders hosted while routing x64 CI by platform', () => {
|
||||
const workflow = loadWorkflow('.github/workflows/build-exe-for-python-sdk.yml')
|
||||
const build = workflowJob(workflow, 'build')
|
||||
for (const [target, runner, variable, blacksmith] of [
|
||||
['node24-linux-x64', 'ubuntu-latest', 'DSH_CI_FAILOVER_LINUX', 'blacksmith-2vcpu-ubuntu-2404'],
|
||||
['node24-win-x64', 'windows-2025', 'DSH_CI_FAILOVER_WINDOWS', 'blacksmith-2vcpu-windows-2025'],
|
||||
['node24-linux-arm64', 'ubuntu-24.04-arm', 'DSH_CI_FAILOVER_LINUX', 'ubuntu-24.04-arm'],
|
||||
['node24-macos-arm64', 'macos-latest', 'DSH_CI_FAILOVER_LINUX', 'macos-latest'],
|
||||
['node24-macos-x64', 'macos-15-intel', 'DSH_CI_FAILOVER_LINUX', 'macos-15-intel'],
|
||||
for (const [target, runner, variable, blacksmith, releaseRunner] of [
|
||||
['node24-linux-x64', 'ubuntu-latest', 'DSH_CI_FAILOVER_LINUX', 'blacksmith-2vcpu-ubuntu-2404', 'ubuntu-latest'],
|
||||
['node24-win-x64', 'windows-2025', 'DSH_CI_FAILOVER_WINDOWS', 'blacksmith-2vcpu-windows-2025', 'windows-2025'],
|
||||
['node24-linux-arm64', 'ubuntu-24.04-arm', 'DSH_CI_FAILOVER_LINUX', 'ubuntu-24.04-arm', 'ubuntu-24.04-arm'],
|
||||
['node24-macos-arm64', 'macos-latest', 'DSH_CI_FAILOVER_LINUX', 'macos-latest', 'macos-15-xlarge'],
|
||||
['node24-macos-x64', 'macos-15-intel', 'DSH_CI_FAILOVER_LINUX', 'macos-15-intel', 'macos-15-large'],
|
||||
] as const) {
|
||||
for (const ci of [false, true]) {
|
||||
for (const release of [false, true]) {
|
||||
for (const mode of ['', 'selfhosted', 'unexpected', 'blacksmith']) {
|
||||
const vars = { DSH_CI_FAILOVER_LINUX: 'blacksmith', DSH_CI_FAILOVER_WINDOWS: 'blacksmith', [variable]: mode }
|
||||
expect(evaluateRunsOn(build['runs-on'], { inputs: { ci, release }, vars, matrix: { target, runner } }), `${target} ci=${ci} release=${release} mode=${mode}`)
|
||||
.toBe(ci && !release && mode === 'blacksmith' ? blacksmith : runner)
|
||||
.toBe(release ? releaseRunner : ci && mode === 'blacksmith' ? blacksmith : runner)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user