Ver código fonte

ci: route runtime and LLM e2e through Blacksmith failover

turtle1999 1 semana atrás
pai
commit
fd0dce2f20

+ 12 - 3
.github/workflows/build-exe-for-python-sdk.yml

@@ -63,7 +63,9 @@ jobs:
   plan:
     name: plan targets
     if: inputs.ci || inputs.release || github.event_name == 'workflow_dispatch'
-    runs-on: ubuntu-latest
+    runs-on: >-
+      ${{ inputs.ci && !inputs.release && vars.DSH_CI_FAILOVER_LINUX == 'blacksmith'
+          && 'blacksmith-4vcpu-ubuntu-2404' || 'ubuntu-latest' }}
     timeout-minutes: 5
     outputs:
       matrix: ${{ steps.plan.outputs.matrix }}
@@ -123,7 +125,9 @@ jobs:
   sdk-wheel:
     needs: plan
     name: deepseek_harness_sdk-${{ needs.plan.outputs.version }}-py3-none-any.whl
-    runs-on: ubuntu-latest
+    runs-on: >-
+      ${{ inputs.ci && !inputs.release && vars.DSH_CI_FAILOVER_LINUX == 'blacksmith'
+          && 'blacksmith-4vcpu-ubuntu-2404' || 'ubuntu-latest' }}
     timeout-minutes: 5
     steps:
       - uses: actions/checkout@v6
@@ -151,7 +155,12 @@ jobs:
   build:
     needs: [plan, sdk-wheel]
     name: ${{ matrix.target }}
-    runs-on: ${{ matrix.runner }}
+    runs-on: >-
+      ${{ inputs.ci && !inputs.release && matrix.target == 'node24-linux-x64'
+          && vars.DSH_CI_FAILOVER_LINUX == 'blacksmith' && 'blacksmith-16vcpu-ubuntu-2404'
+          || inputs.ci && !inputs.release && matrix.target == 'node24-win-x64'
+          && vars.DSH_CI_FAILOVER_WINDOWS == 'blacksmith' && 'blacksmith-16vcpu-windows-2025'
+          || matrix.runner }}
     timeout-minutes: 45
     strategy:
       fail-fast: false

+ 3 - 1
.github/workflows/e2e.yml

@@ -53,7 +53,9 @@ env:
 
 jobs:
   e2e:
-    runs-on: ubuntu-latest
+    runs-on: >-
+      ${{ vars.DSH_CI_FAILOVER_LINUX == 'blacksmith'
+          && 'blacksmith-4vcpu-ubuntu-2404' || 'ubuntu-latest' }}
     name: e2e
     # Run on every trusted event. Skip untrusted PRs (forks + Dependabot) where
     # the secret is withheld — they would otherwise hard-fail the preflight.

+ 51 - 3
scripts/ci-workflow.spec.ts

@@ -4,6 +4,11 @@ import { runInNewContext } from 'node:vm'
 import * as yaml from 'js-yaml'
 import { describe, expect, it } from 'vitest'
 
+function evaluateRunsOn(selector: unknown, context: Record<string, unknown>): unknown {
+  if (typeof selector !== 'string') throw new TypeError('Runner selector must be a string')
+  return runInNewContext(selector.trim().slice(3, -2), context, { timeout: 1000 })
+}
+
 const root = resolve(import.meta.dirname, '..')
 const runnerPrivatePnpmDestination = /^\$\{\{ runner\.temp \}\}\/setup-pnpm-\$\{\{ github\.run_id \}\}-\$\{\{ github\.run_attempt \}\}$/
 const nativeWindowsPnpmDestination = '${{ runner.temp }}/setup-pnpm-js-${{ github.run_id }}-${{ github.run_attempt }}-${{ github.job }}'
@@ -329,12 +334,11 @@ describe('CI workflow', () => {
       windows: windowsBuild['runs-on'] as string,
     }
     const evaluate = (expression: string, vars: Record<string, string>, login = 'maintainer'): unknown => {
-      const body = expression.trim().slice(3, -2)
-      return runInNewContext(body, {
+      return evaluateRunsOn(expression, {
         vars,
         fromJSON: JSON.parse,
         github: { event: { pull_request: { user: { login } } } },
-      }, { timeout: 1000 })
+      })
     }
     for (const [name, selector, variable, pool, hosted] of [
       ['linux gates', selectors.linux, 'DSH_CI_FAILOVER_LINUX', ['self-hosted', 'linux', 'x64', 'vm-backup'], 'dsh-ubuntu-24-04-16core'],
@@ -580,6 +584,50 @@ describe('CI workflow', () => {
   })
 })
 
+describe('Runtime and LLM e2e Blacksmith routing', () => {
+  it('routes DeepSeek e2e only through the Linux Blacksmith switch', () => {
+    const job = workflowJob(loadWorkflow('.github/workflows/e2e.yml'), 'e2e')
+    for (const mode of ['', 'selfhosted', 'unexpected', 'blacksmith']) {
+      expect(evaluateRunsOn(job['runs-on'], { vars: { DSH_CI_FAILOVER_LINUX: mode, DSH_CI_FAILOVER_WINDOWS: 'blacksmith' } }))
+        .toBe(mode === 'blacksmith' ? 'blacksmith-4vcpu-ubuntu-2404' : 'ubuntu-latest')
+    }
+  })
+
+  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-16vcpu-ubuntu-2404'],
+      ['node24-win-x64', 'windows-2025', 'DSH_CI_FAILOVER_WINDOWS', 'blacksmith-16vcpu-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'],
+    ] 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)
+          }
+        }
+      }
+    }
+  })
+
+  it.each(['plan', 'sdk-wheel'])('routes runtime %s only for non-release CI', (name) => {
+    const job = workflowJob(loadWorkflow('.github/workflows/build-exe-for-python-sdk.yml'), name)
+    for (const ci of [false, true]) {
+      for (const release of [false, true]) {
+        for (const mode of ['', 'selfhosted', 'unexpected', 'blacksmith']) {
+          expect(evaluateRunsOn(job['runs-on'], { inputs: { ci, release }, vars: { DSH_CI_FAILOVER_LINUX: mode } }))
+            .toBe(ci && !release && mode === 'blacksmith' ? 'blacksmith-4vcpu-ubuntu-2404' : 'ubuntu-latest')
+        }
+      }
+    }
+  })
+})
+
 describe('DeepSeek e2e workflow', () => {
   it('prepares bubblewrap from the pinned payload without a package transaction', () => {
     const workflow = loadWorkflow('.github/workflows/e2e.yml')