fix(ci): isolate OpenWebUI release smoke (#103095)

* fix(ci): isolate OpenWebUI release smoke

* docs: format release validation table
This commit is contained in:
Peter Steinberger
2026-07-09 21:38:33 +01:00
committed by GitHub
parent bb16ca50d6
commit 71f7fef7a2
8 changed files with 88 additions and 28 deletions

View File

@@ -432,10 +432,10 @@ the `Verify preinstalled live media dependencies` step before assuming the media
tests themselves slowed down.
The release Docker path intentionally shards the plugin/runtime tail. The
workflow uses `plugins-runtime-plugins`, `plugins-runtime-services`, and
`plugins-runtime-install-a` through `plugins-runtime-install-d`; aggregate
aliases such as `plugins-runtime-core`, `plugins-runtime`, and
`plugins-integrations` remain for manual reruns.
workflow uses `plugins-runtime-plugins`, `plugins-runtime-services`,
`plugins-runtime-install-a` through `plugins-runtime-install-h`, and a
dedicated `openwebui` job; aggregate aliases such as `plugins-runtime-core`,
`plugins-runtime`, and `plugins-integrations` remain for manual reruns.
The release QA parity box is internally split into candidate and baseline lane
jobs, followed by a report job that downloads both artifacts and runs
@@ -499,8 +499,9 @@ Release-path Docker chunks are currently `core`, `package-update-openai`,
`plugins-runtime-plugins`, `plugins-runtime-services`,
`plugins-runtime-install-a`, `plugins-runtime-install-b`,
`plugins-runtime-install-c`, `plugins-runtime-install-d`,
`bundled-channels-core`, `bundled-channels-update-a`,
`bundled-channels-update-b`, and `bundled-channels-contracts`. The aggregate
`plugins-runtime-install-e`, `plugins-runtime-install-f`,
`plugins-runtime-install-g`, `plugins-runtime-install-h`, and the dedicated
`openwebui` job. The aggregate
`bundled-channels`, `plugins-runtime-core`, `plugins-runtime`, and
`plugins-integrations` chunks remain valid for manual one-shot reruns, but
release checks use the split chunks.
@@ -592,13 +593,18 @@ image. Release-path normal mode fans out into smaller Docker chunk jobs:
- `plugins-runtime-install-b`
- `plugins-runtime-install-c`
- `plugins-runtime-install-d`
- `bundled-channels`
- `plugins-runtime-install-e`
- `plugins-runtime-install-f`
- `plugins-runtime-install-g`
- `plugins-runtime-install-h`
- `openwebui`
OpenWebUI is folded into `plugins-runtime-services` for full release-path
coverage and keeps a standalone `openwebui` chunk only for OpenWebUI-only
dispatches. The legacy `package-update`, `plugins-runtime-core`,
OpenWebUI runs as a standalone `openwebui` chunk on a dedicated large-disk
runner whenever stable or full release-path coverage requests it. The legacy
`package-update`, `plugins-runtime-core`,
`plugins-runtime`, and `plugins-integrations` chunks still work as aggregate
aliases for manual reruns, but the release workflow uses the split chunks so
aliases for manual reruns and may still fold in OpenWebUI, but the release
workflow uses the split chunks so
provider installer checks, plugin runtime checks, bundled plugin
install/uninstall shards, and bundled-channel checks can run on separate
machines. The bundled-channel runtime-dependency coverage
@@ -608,8 +614,8 @@ than the serial `bundled-channel-deps` lane, so failures produce cheap targeted
reruns for the exact channel/update scenario. The bundled plugin
install/uninstall sweep is also split into
`bundled-plugin-install-uninstall-0` through
`bundled-plugin-install-uninstall-7`; selecting the legacy
`bundled-plugin-install-uninstall` lane expands to all eight shards.
`bundled-plugin-install-uninstall-23`; selecting the legacy
`bundled-plugin-install-uninstall` lane expands to all 24 shards.
## Package Acceptance

View File

@@ -103,7 +103,7 @@ on:
- stable
- full
use_github_hosted_runners:
description: Use GitHub-hosted runners instead of Blacksmith runners
description: Use GitHub-hosted runners where supported; OpenWebUI always uses a large-disk Blacksmith runner
required: false
default: false
type: boolean
@@ -214,7 +214,7 @@ on:
default: stable
type: string
use_github_hosted_runners:
description: Use GitHub-hosted runners instead of Blacksmith runners
description: Use GitHub-hosted runners where supported; OpenWebUI always uses a large-disk Blacksmith runner
required: false
default: true
type: boolean
@@ -1236,10 +1236,10 @@ jobs:
validate_docker_openwebui:
needs: [validate_selected_ref, prepare_docker_e2e_image]
if: inputs.include_openwebui && !inputs.include_release_path_suites && inputs.docker_lanes == ''
if: inputs.include_openwebui && inputs.docker_lanes == '' && (inputs.release_test_profile == 'stable' || inputs.release_test_profile == 'full')
name: Docker E2E (openwebui)
continue-on-error: ${{ inputs.advisory }}
runs-on: ${{ inputs.use_github_hosted_runners && 'ubuntu-24.04' || 'blacksmith-32vcpu-ubuntu-2404' }}
runs-on: blacksmith-32vcpu-ubuntu-2404
timeout-minutes: 60
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
@@ -1250,6 +1250,7 @@ jobs:
OPENCLAW_DOCKER_E2E_REPO_ROOT: ${{ github.workspace }}
OPENCLAW_DOCKER_E2E_SELECTED_SHA: ${{ needs.validate_selected_ref.outputs.selected_sha }}
OPENCLAW_CURRENT_PACKAGE_TGZ: .artifacts/docker-e2e-package/openclaw-current.tgz
OPENCLAW_DOCKER_ALL_RELEASE_PROFILE: ${{ inputs.release_test_profile }}
OPENCLAW_SKIP_DOCKER_BUILD: "1"
steps:
- name: Checkout selected ref
@@ -1275,7 +1276,9 @@ jobs:
uses: ./.github/actions/setup-node-env
with:
node-version: ${{ env.NODE_VERSION }}
install-bun: "true"
install-bun: "false"
install-deps: "false"
use-actions-cache: "false"
- name: Validate Open WebUI credentials
shell: bash

View File

@@ -483,11 +483,11 @@ The reusable live/E2E workflow asks `scripts/test-docker-all.mjs --plan-json` wh
Release Docker coverage runs smaller chunked jobs with `OPENCLAW_SKIP_DOCKER_BUILD=1` so each chunk pulls only the image kind it needs and executes multiple lanes through the same weighted scheduler:
- `OPENCLAW_DOCKER_ALL_PROFILE=release-path`
- `OPENCLAW_DOCKER_ALL_CHUNK=core | package-update-openai | package-update-anthropic | package-update-core | plugins-runtime-plugins | plugins-runtime-services | plugins-runtime-install-a..h`
- `OPENCLAW_DOCKER_ALL_CHUNK=core | package-update-openai | package-update-anthropic | package-update-core | plugins-runtime-plugins | plugins-runtime-services | plugins-runtime-install-a..h | openwebui`
Current release Docker chunks are `core`, `package-update-openai`, `package-update-anthropic`, `package-update-core`, `plugins-runtime-plugins`, `plugins-runtime-services`, and `plugins-runtime-install-a` through `plugins-runtime-install-h`. `package-update-openai` includes the live Codex plugin package lane, which installs the candidate OpenClaw package, installs the Codex plugin from `codex_plugin_spec` or a same-ref tarball with explicit Codex CLI install approval, runs Codex CLI preflight, then runs multiple same-session OpenClaw agent turns against OpenAI. `plugins-runtime-core`, `plugins-runtime`, and `plugins-integrations` remain aggregate plugin/runtime aliases. The `install-e2e` lane alias remains the aggregate manual rerun alias for both provider installer lanes.
Current release Docker chunks are `core`, `package-update-openai`, `package-update-anthropic`, `package-update-core`, `plugins-runtime-plugins`, `plugins-runtime-services`, `plugins-runtime-install-a` through `plugins-runtime-install-h`, and `openwebui`. `package-update-openai` includes the live Codex plugin package lane, which installs the candidate OpenClaw package, installs the Codex plugin from `codex_plugin_spec` or a same-ref tarball with explicit Codex CLI install approval, runs Codex CLI preflight, then runs multiple same-session OpenClaw agent turns against OpenAI. `plugins-runtime-core`, `plugins-runtime`, and `plugins-integrations` remain aggregate plugin/runtime aliases. The `install-e2e` lane alias remains the aggregate manual rerun alias for both provider installer lanes.
OpenWebUI is folded into `plugins-runtime-services` when full release-path coverage requests it, and keeps a standalone `openwebui` chunk only for OpenWebUI-only dispatches. Bundled-channel update lanes retry once for transient npm network failures.
OpenWebUI runs as a standalone `openwebui` chunk on a dedicated large-disk Blacksmith runner whenever stable or full release-path coverage requests it, even when the reusable workflow routes supported jobs to GitHub-hosted runners. Keeping the external image pull separate prevents the large image from competing with the shared package and plugin images in `plugins-runtime-services`; legacy aggregate plugin/runtime chunks still include OpenWebUI for compatible manual reruns. Bundled-channel update lanes retry once for transient npm network failures.
Each chunk uploads `.artifacts/docker-tests/` with lane logs, timings, `summary.json`, `failures.json`, phase timings, scheduler plan JSON, slow-lane tables, and per-lane rerun commands. The workflow `docker_lanes` input runs selected lanes against the prepared images instead of the chunk jobs, which keeps failed-lane debugging bounded to one targeted Docker job and prepares, downloads, or reuses the package artifact for that run; if a selected lane is a live Docker lane, the targeted job builds the live-test image locally for that rerun. Generated per-lane GitHub rerun commands include `package_artifact_run_id`, `package_artifact_name`, and prepared image inputs when those values exist, so a failed lane can reuse the exact package and images from the failed run.

View File

@@ -371,8 +371,8 @@ Release Docker coverage includes:
- full install smoke with the slow Bun global install smoke enabled
- root Dockerfile smoke image preparation/reuse by target SHA, with QR, root/gateway, and installer/Bun smoke jobs running as separate install-smoke shards
- repository E2E lanes
- release-path Docker chunks: `core`, `package-update-openai`, `package-update-anthropic`, `package-update-core`, `plugins-runtime-plugins`, `plugins-runtime-services`, `plugins-runtime-install-a` through `plugins-runtime-install-h`
- OpenWebUI coverage inside the `plugins-runtime-services` chunk when requested
- release-path Docker chunks: `core`, `package-update-openai`, `package-update-anthropic`, `package-update-core`, `plugins-runtime-plugins`, `plugins-runtime-services`, `plugins-runtime-install-a` through `plugins-runtime-install-h`, and `openwebui`
- OpenWebUI coverage on a dedicated large-disk runner when requested
- split bundled plugin install/uninstall lanes `bundled-plugin-install-uninstall-0` through `bundled-plugin-install-uninstall-23`
- live/E2E provider suites and Docker live model coverage when release checks include live suites

View File

@@ -104,8 +104,9 @@ empty:
| `package-update-anthropic` | Anthropic package install and update behavior. |
| `package-update-core` | Provider-neutral package and update behavior. |
| `plugins-runtime-plugins` | Plugin runtime lanes that exercise plugin behavior. |
| `plugins-runtime-services` | Service-backed and live plugin runtime lanes; includes OpenWebUI when requested. |
| `plugins-runtime-services` | Service-backed and live plugin runtime lanes. |
| `plugins-runtime-install-a` through `plugins-runtime-install-h` | Plugin install/runtime batches split for parallel release validation. |
| `openwebui` | OpenWebUI compatibility smoke isolated on a dedicated large-disk runner when requested. |
Use targeted `docker_lanes=<lane[,lane]>` on the reusable live/E2E workflow when
only one Docker lane failed. The release artifacts include per-lane rerun

View File

@@ -921,8 +921,7 @@ export function releasePathChunkLanes(chunk, options = {}) {
return options.includeOpenWebUI ? [openWebUILane()] : [];
}
if (
(chunk !== "plugins-runtime-services" &&
chunk !== "plugins-runtime-core" &&
(chunk !== "plugins-runtime-core" &&
chunk !== "plugins-runtime" &&
chunk !== "plugins-integrations") ||
!options.includeOpenWebUI
@@ -935,7 +934,6 @@ export function releasePathChunkLanes(chunk, options = {}) {
export function allReleasePathLanes(options = {}) {
const releaseProfile = normalizeReleaseProfile(options.releaseProfile);
return Object.keys(primaryReleasePathChunks)
.filter((chunk) => chunk !== "openwebui")
.flatMap((chunk) =>
releasePathChunkLanes(chunk, {
includeOpenWebUI: options.includeOpenWebUI,

View File

@@ -181,7 +181,7 @@ describe("scripts/lib/docker-e2e-plan", () => {
});
expect(withoutOpenWebUI.lanes.map((lane) => lane.name)).not.toContain("openwebui");
expect(withOpenWebUI.lanes.map((lane) => lane.name)).toContain("openwebui");
expect(withOpenWebUI.lanes.filter((lane) => lane.name === "openwebui")).toHaveLength(1);
});
it("keeps beta release-path coverage to install, provider, and update proof lanes", () => {
@@ -264,6 +264,11 @@ describe("scripts/lib/docker-e2e-plan", () => {
profile: RELEASE_PATH_PROFILE,
releaseChunk: "plugins-runtime-services",
});
const openWebUI = planFor({
includeOpenWebUI: true,
profile: RELEASE_PATH_PROFILE,
releaseChunk: "openwebui",
});
const pluginsRuntimeInstallA = planFor({
includeOpenWebUI: true,
profile: RELEASE_PATH_PROFILE,
@@ -457,6 +462,8 @@ describe("scripts/lib/docker-e2e-plan", () => {
timeoutMs: 1_200_000,
weight: 3,
},
]);
expect(openWebUI.lanes.map(summarizeLane)).toEqual([
{
command:
"OPENCLAW_OPENWEBUI_MODEL=openai/gpt-5.4-mini OPENCLAW_OPENWEBUI_PROVIDER_TIMEOUT_SECONDS=300 OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:openwebui",
@@ -592,6 +599,33 @@ describe("scripts/lib/docker-e2e-plan", () => {
]);
});
it("includes OpenWebUI exactly once in each legacy plugin aggregate", () => {
for (const releaseChunk of [
"plugins-runtime-core",
"plugins-runtime",
"plugins-integrations",
]) {
const withOpenWebUI = planFor({
includeOpenWebUI: true,
profile: RELEASE_PATH_PROFILE,
releaseChunk,
});
const withoutOpenWebUI = planFor({
includeOpenWebUI: false,
profile: RELEASE_PATH_PROFILE,
releaseChunk,
});
expect(
withOpenWebUI.lanes.filter((lane) => lane.name === "openwebui"),
releaseChunk,
).toHaveLength(1);
expect(withoutOpenWebUI.lanes.map((lane) => lane.name), releaseChunk).not.toContain(
"openwebui",
);
}
});
it("expands the published upgrade survivor lane across deduped baselines", () => {
const plan = planFor({
selectedLaneNames: ["published-upgrade-survivor"],

View File

@@ -1745,6 +1745,24 @@ describe("package artifact reuse", () => {
}
});
it("isolates Open WebUI release coverage on a lean large-disk runner", () => {
const job = workflowJob(LIVE_E2E_WORKFLOW, "validate_docker_openwebui");
const setupNode = workflowStep(job, "Setup Node environment");
expect(job.if).toBe(
"inputs.include_openwebui && inputs.docker_lanes == '' && (inputs.release_test_profile == 'stable' || inputs.release_test_profile == 'full')",
);
expect(job["runs-on"]).toBe("blacksmith-32vcpu-ubuntu-2404");
expect(job.env?.OPENCLAW_DOCKER_ALL_RELEASE_PROFILE).toBe(
"${{ inputs.release_test_profile }}",
);
expect(setupNode.with).toMatchObject({
"install-bun": "false",
"install-deps": "false",
"use-actions-cache": "false",
});
});
it("names package acceptance Telegram as artifact-backed package validation", () => {
const workflow = readFileSync(PACKAGE_ACCEPTANCE_WORKFLOW, "utf8");