Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
d4c373d
fix(setup): validate current OpenClaw candidate
CassieMei Jul 21, 2026
8e0ab6b
test(setup): preserve node trust recovery proof
CassieMei Jul 21, 2026
3ca0fb7
fix: restore current gateway LKG and pt-PT proofs
CassieMei Jul 21, 2026
a99ed39
test(ci): preserve official gateway E2E lane
CassieMei Jul 22, 2026
a0291b3
test(setup): keep candidate proof fail closed
CassieMei Jul 22, 2026
c6bebbc
docs(testing): select candidate E2E source
CassieMei Jul 22, 2026
e486926
test(ci): keep setup E2E guard fail closed
CassieMei Jul 22, 2026
e776e5f
fix(setup): verify composed gateway packages
CassieMei Jul 23, 2026
8b614c3
fix(setup): align gateway policy and restart ownership
CassieMei Jul 23, 2026
a70fe6f
fix(setup): honor gateway reload mode schemas
CassieMei Jul 23, 2026
58a956a
fix(ci): keep official compatibility canary informational
CassieMei Jul 25, 2026
a2cd416
fix(setup): refresh composed OpenClaw validation
CassieMei Jul 25, 2026
026fd7f
ci: compose merged package fix from main
CassieMei Jul 25, 2026
3e9329f
docs: align legacy gateway allowlist versions
CassieMei Jul 25, 2026
8f9f46c
docs: align gateway schema guidance
CassieMei Jul 25, 2026
b68d6ac
docs: align legacy gateway references
CassieMei Jul 25, 2026
8b3d57f
fix(setup): preserve gateway schema contracts
CassieMei Jul 25, 2026
1f785aa
fix(setup): restore proven gateway default
CassieMei Jul 25, 2026
f5958e2
fix(setup): enforce secure stable gateway floor
CassieMei Jul 26, 2026
278c1bc
fix(ci): compose beta 5 with hosted wizard fix
CassieMei Jul 29, 2026
df5bfeb
fix(setup): handle 2026.7.1 terminal wizard restart
CassieMei Jul 29, 2026
19145d0
fix(ci): scope composed provenance refs to package step
CassieMei Jul 29, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
209 changes: 201 additions & 8 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,130 @@ jobs:
exit 1
fi

gateway-composed:
needs: repo-hygiene
runs-on: ubuntu-latest
timeout-minutes: 45
outputs:
sha256: ${{ steps.package.outputs.sha256 }}
steps:
- name: Fail if repo hygiene failed
if: ${{ needs.repo-hygiene.result != 'success' }}
shell: bash
run: |
echo "repo-hygiene failed; see the repo-hygiene job output." >&2
exit 1

- name: Checkout frozen OpenClaw beta 5 source
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
with:
repository: openclaw/openclaw
ref: ee929dbb857c717a60f3b2b502db5a6dd31b5c11
fetch-depth: 0

- name: Setup Node 24
uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6
with:
node-version: 24

- name: Activate pinned pnpm
shell: bash
run: |
corepack enable
corepack prepare pnpm@11.15.1 --activate

- name: Compose beta 5 with reviewed wizard compatibility fixes
shell: bash
run: |
set -euo pipefail
base_sha=ee929dbb857c717a60f3b2b502db5a6dd31b5c11
wizard_base=ee929dbb857c717a60f3b2b502db5a6dd31b5c11
wizard_head=2a3612054f6cacce893526c16ce37daa94ba9abf
fork_repository=https://github.com/TheAngryPit/openclaw.git
wizard_fetch_ref=refs/heads/codex/beta5-peter-115671-compat-20260729
wizard_paths="$RUNNER_TEMP/hosted-wizard-expected-paths.txt"
staged_paths="$RUNNER_TEMP/staged-paths.txt"
wizard_patch="$RUNNER_TEMP/hosted-wizard.patch"

cat >"$wizard_paths" <<'EOF'
src/gateway/gateway.test.ts
src/gateway/server-methods/wizard.test.ts
src/gateway/server-methods/wizard.ts
src/wizard/setup.finalize.test.ts
src/wizard/setup.finalize.ts
EOF

test "$(git rev-parse HEAD)" = "$base_sha"
git fetch --no-tags "$fork_repository" \
"+${wizard_fetch_ref}:refs/remotes/fork/hosted-wizard"
test "$(git rev-parse refs/remotes/fork/hosted-wizard)" = "$wizard_head"
git merge-base --is-ancestor "$wizard_base" "$wizard_head"
git diff --name-only "$wizard_base" "$wizard_head" | sort | diff -u "$wizard_paths" -
git diff --binary "$wizard_base" "$wizard_head" -- $(cat "$wizard_paths") >"$wizard_patch"
test -s "$wizard_patch"
sha256sum "$wizard_patch" >"$RUNNER_TEMP/hosted-wizard-patch.SHA256SUM"
git apply --index "$wizard_patch"
git diff --cached --name-only | sort >"$staged_paths"
diff -u "$wizard_paths" "$staged_paths"
git diff --cached --check

- name: Build immutable composed gateway package
id: package
shell: bash
run: |
set -euo pipefail
source_sha=ee929dbb857c717a60f3b2b502db5a6dd31b5c11
wizard_base=ee929dbb857c717a60f3b2b502db5a6dd31b5c11
wizard_head=2a3612054f6cacce893526c16ce37daa94ba9abf
test "$(node -p "require('./package.json').version")" = "2026.7.2-beta.5"
pnpm install --frozen-lockfile --ignore-scripts=false --config.engine-strict=false --config.enable-pre-post-scripts=true
node scripts/package-openclaw-for-docker.mjs \
--allow-unreleased-changelog \
--source-dir . \
--output-dir "$RUNNER_TEMP/gateway-composed" \
--output-name openclaw-2026.7.2-beta.5-hosted-wizard.tgz
tarball="$RUNNER_TEMP/gateway-composed/openclaw-2026.7.2-beta.5-hosted-wizard.tgz"
sha256="$(sha256sum "$tarball" | awk '{print $1}')"
packaged_version="$(tar -xOf "$tarball" package/package.json | node -e "let s='';process.stdin.on('data',c=>s+=c).on('end',()=>process.stdout.write(JSON.parse(s).version))")"
test "$packaged_version" = "2026.7.2-beta.5"
wizard_patch_sha256="$(awk '{print $1}' "$RUNNER_TEMP/hosted-wizard-patch.SHA256SUM")"
test "${#sha256}" -eq 64
test "${#wizard_patch_sha256}" -eq 64
printf '%s %s\n' "$sha256" "$(basename "$tarball")" >"$RUNNER_TEMP/gateway-composed/SHA256SUMS"
printf '{"source_ref":"v2026.7.2-beta.5","source_sha":"%s","fixes":[{"upstream_pr":115671,"upstream_commit":"c6b4e912eb103fe8ceb89ffc2a60411624163b4b"},{"compatibility_commit":"%s"}],"compatibility_base":"%s","compatibility_head":"%s","fetch_repository":"TheAngryPit/openclaw","fetch_ref":"codex/beta5-peter-115671-compat-20260729","patch_sha256":"%s","changed_paths":["src/gateway/gateway.test.ts","src/gateway/server-methods/wizard.test.ts","src/gateway/server-methods/wizard.ts","src/wizard/setup.finalize.test.ts","src/wizard/setup.finalize.ts"],"package_version":"%s","package_sha256":"%s"}\n' \
"$source_sha" \
"$wizard_head" \
"$wizard_base" \
"$wizard_head" \
"$wizard_patch_sha256" \
"$packaged_version" \
"$sha256" >"$RUNNER_TEMP/gateway-composed/provenance.json"
node -e '
const fs = require("node:fs");
const provenance = JSON.parse(fs.readFileSync(process.argv[1], "utf8"));
if (
provenance.fixes[1]?.compatibility_commit !== process.argv[2]
|| provenance.compatibility_base !== process.argv[3]
|| provenance.compatibility_head !== process.argv[2]
|| provenance.package_sha256 !== process.argv[4]
) {
throw new Error("composed package provenance does not match frozen inputs");
}
' \
"$RUNNER_TEMP/gateway-composed/provenance.json" \
"$wizard_head" \
"$wizard_base" \
"$sha256"
echo "sha256=$sha256" >>"$GITHUB_OUTPUT"

- name: Upload composed gateway package
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: openclaw-beta5-hosted-wizard-composed
path: ${{ runner.temp }}/gateway-composed/
if-no-files-found: error
retention-days: 7

test:
needs: repo-hygiene
if: ${{ !cancelled() }}
Expand Down Expand Up @@ -338,29 +462,52 @@ jobs:
majorMinorPatch: ${{ steps.gitversion.outputs.majorMinorPatch }}

e2etests:
needs: repo-hygiene
if: ${{ !cancelled() }}
needs: [repo-hygiene, gateway-composed]
if: ${{ needs.repo-hygiene.result == 'success' && needs.gateway-composed.result == 'success' }}
runs-on: windows-latest
continue-on-error: ${{ matrix.continue_on_error || false }}
timeout-minutes: ${{ matrix.timeout_minutes }}
strategy:
fail-fast: false
matrix:
include:
- name: setup-connect
- name: lkg-setup-connect
gateway_source: lkg
gateway_version: ""
scenario: setup-connect
timeout_minutes: 45
filter: "FullyQualifiedName~OpenClaw.E2ETests.Setup.SetupAndConnectTests|FullyQualifiedName~OpenClaw.E2ETests.Setup.MxcSetupAndConnectTests"
- name: official-beta5-setup-connect
gateway_source: official
gateway_version: 2026.7.2-beta.5
scenario: setup-connect
continue_on_error: true
timeout_minutes: 45
filter: "FullyQualifiedName~OpenClaw.E2ETests.Setup.SetupAndConnectTests|FullyQualifiedName~OpenClaw.E2ETests.Setup.MxcSetupAndConnectTests"
- name: revocation-recovery
- name: composed-setup-connect
gateway_source: composed
gateway_version: ""
scenario: setup-connect
timeout_minutes: 45
filter: "FullyQualifiedName~OpenClaw.E2ETests.Setup.SetupAndConnectTests|FullyQualifiedName~OpenClaw.E2ETests.Setup.MxcSetupAndConnectTests"
- name: composed-revocation-recovery
gateway_source: composed
gateway_version: ""
scenario: revocation-recovery
timeout_minutes: 25
filter: FullyQualifiedName~OpenClaw.E2ETests.Setup.RevocationAndRecoveryTests
- name: network-recovery
- name: composed-network-recovery
gateway_source: composed
gateway_version: ""
scenario: network-recovery
timeout_minutes: 25
filter: FullyQualifiedName~OpenClaw.E2ETests.Setup.NetworkRecoveryTests
steps:
- name: Fail if repo hygiene failed
if: ${{ needs.repo-hygiene.result != 'success' }}
if: ${{ needs.repo-hygiene.result != 'success' || needs.gateway-composed.result != 'success' }}
shell: pwsh
run: |
Write-Error "repo-hygiene failed; see the repo-hygiene job output."
Write-Error "A prerequisite failed; see repo-hygiene and gateway-composed job output."
exit 1

- uses: actions/checkout@v7
Expand Down Expand Up @@ -395,9 +542,46 @@ jobs:
- name: Build E2E Tests
run: dotnet build tests/OpenClaw.E2ETests -c Debug -r win-x64

- name: Run gateway package selector tests
if: ${{ matrix.name == 'official-beta5-setup-connect' }}
shell: pwsh
run: |
dotnet test tests/OpenClaw.E2ETests `
--no-build `
-c Debug `
-r win-x64 `
--verbosity normal `
--filter "FullyQualifiedName~OpenClaw.E2ETests.Setup.GatewayE2EPackageSpecTests"
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }

- name: Download composed gateway package
if: ${{ matrix.gateway_source == 'composed' }}
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
with:
name: openclaw-beta5-hosted-wizard-composed
path: TestResults/GatewayComposed

- name: Start disposable WSL package host
if: ${{ matrix.gateway_source == 'composed' }}
id: gateway_package_host
shell: pwsh
run: |
.\scripts\Start-E2EGatewayPackageHost.ps1 `
-PackagePath "TestResults\GatewayComposed\openclaw-2026.7.2-beta.5-hosted-wizard.tgz" `
-ExpectedSha256 "${{ needs.gateway-composed.outputs.sha256 }}" `
-DistroName "OpenClawE2EPackageHost-${{ matrix.name }}" `
-InstallLocation "${{ runner.temp }}\OpenClawE2EPackageHost-${{ matrix.name }}" `
-OwnershipToken "${{ github.run_id }}-${{ github.run_attempt }}-${{ matrix.name }}" `
-GitHubOutput $env:GITHUB_OUTPUT

- name: Run E2E Tests (${{ matrix.name }})
env:
OPENCLAW_RUN_E2E: 1
OPENCLAW_E2E_GATEWAY_SOURCE: ${{ matrix.gateway_source }}
OPENCLAW_E2E_GATEWAY_VERSION: ${{ matrix.gateway_version }}
OPENCLAW_E2E_GATEWAY_PACKAGE_SPEC: ${{ matrix.gateway_source == 'composed' && steps.gateway_package_host.outputs.package_spec || '' }}
OPENCLAW_E2E_GATEWAY_PACKAGE_SHA256: ${{ matrix.gateway_source == 'composed' && steps.gateway_package_host.outputs.package_sha256 || '' }}
OPENCLAW_E2E_GATEWAY_PACKAGE_HOST_DISTRO: ${{ matrix.gateway_source == 'composed' && steps.gateway_package_host.outputs.distro_name || '' }}
shell: pwsh
run: |
dotnet test tests/OpenClaw.E2ETests `
Expand All @@ -417,7 +601,7 @@ jobs:
Write-Error "E2E shard '${{ matrix.name }}' executed zero tests. Check OPENCLAW_RUN_E2E gating/filter before merging."
exit 1
}
if ("${{ matrix.name }}" -eq "setup-connect") {
if ("${{ matrix.scenario }}" -eq "setup-connect") {
$mxcProofNames = @(
"RealGateway_SystemRun_ExecutesThroughWindowsNodeMxcSandbox",
"RealGateway_SystemRun_BlocksWritesToTrayDataDirectoryInMxcSandbox"
Expand Down Expand Up @@ -448,6 +632,15 @@ jobs:
}
}

- name: Stop disposable WSL package host
if: ${{ always() && matrix.gateway_source == 'composed' }}
shell: pwsh
run: |
.\scripts\Stop-E2EGatewayPackageHost.ps1 `
-DistroName "OpenClawE2EPackageHost-${{ matrix.name }}" `
-InstallLocation "${{ runner.temp }}\OpenClawE2EPackageHost-${{ matrix.name }}" `
-OwnershipToken "${{ github.run_id }}-${{ github.run_attempt }}-${{ matrix.name }}"

- name: Upload E2E Test Results & Logs
if: always()
uses: actions/upload-artifact@v7
Expand Down
58 changes: 43 additions & 15 deletions .github/workflows/gateway-lkg-update.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ jobs:
if not match:
raise SystemExit("Could not parse LkgVersion constant from GatewayLkgVersion.cs")
pinned = match.group(1)
if not re.fullmatch(r'[0-9]+\.[0-9]+\.[0-9]+([.\-+][A-Za-z0-9.\-]+)*', pinned):
raise SystemExit(f"Pinned LkgVersion has unexpected format: {pinned}")
if not re.fullmatch(r'[0-9]+\.[0-9]+\.[0-9]+', pinned):
raise SystemExit(f"Pinned LkgVersion must be an exact stable version: {pinned}")
print(pinned)
PY
)"
Expand All @@ -45,8 +45,8 @@ jobs:
with urllib.request.urlopen('https://registry.npmjs.org/openclaw/latest', timeout=30) as r:
payload = json.load(r)
latest = payload['version']
if not re.fullmatch(r'[0-9]+\.[0-9]+\.[0-9]+([.\-+][A-Za-z0-9.\-]+)*', latest):
raise SystemExit(f"Resolved npm latest version has unexpected format: {latest}")
if not re.fullmatch(r'[0-9]+\.[0-9]+\.[0-9]+', latest):
raise SystemExit(f"Resolved npm latest must be an exact stable version: {latest}")
print(latest)
PY
)"
Expand All @@ -56,7 +56,13 @@ jobs:
echo "latest=${latest}"
} >> "$GITHUB_OUTPUT"

if [[ "$pinned" != "$latest" ]]; then
if python3 - "$pinned" "$latest" <<'PY'
import sys
pinned = tuple(map(int, sys.argv[1].split(".")))
latest = tuple(map(int, sys.argv[2].split(".")))
raise SystemExit(0 if latest > pinned else 1)
PY
then
echo "drifted=true" >> "$GITHUB_OUTPUT"
else
echo "drifted=false" >> "$GITHUB_OUTPUT"
Expand Down Expand Up @@ -84,27 +90,47 @@ jobs:
import os
import pathlib, re
latest = os.environ["LATEST_VERSION"]
path = pathlib.Path("src/OpenClaw.SetupEngine/GatewayLkgVersion.cs")
source = path.read_text(encoding="utf-8")
pattern = r'(LkgVersion\s*=\s*")([^"]+)(")'
updated, count = re.subn(pattern, lambda m: f"{m.group(1)}{latest}{m.group(3)}", source, count=1)
if count != 1:
raise SystemExit("Failed to rewrite LkgVersion constant")
path.write_text(updated, encoding="utf-8")
replacements = (
(
pathlib.Path("src/OpenClaw.SetupEngine/GatewayLkgVersion.cs"),
r'(LkgVersion\s*=\s*")([^"]+)(")',
"LkgVersion constant",
),
(
pathlib.Path("tests/OpenClaw.SetupEngine.Tests/GatewayLkgVersionTests.cs"),
r'(ExpectedLkgVersion\s*=\s*")([^"]+)(")',
"ExpectedLkgVersion constant",
),
)
for path, pattern, label in replacements:
source = path.read_text(encoding="utf-8")
updated, count = re.subn(
pattern,
lambda m: f"{m.group(1)}{latest}{m.group(3)}",
source,
count=1,
)
if count != 1:
raise SystemExit(f"Failed to rewrite {label}")
path.write_text(updated, encoding="utf-8")
PY

- name: Commit and push branch
if: ${{ steps.versions.outputs.drifted == 'true' }}
shell: bash
run: |
if git diff --quiet -- src/OpenClaw.SetupEngine/GatewayLkgVersion.cs; then
update_paths=(
src/OpenClaw.SetupEngine/GatewayLkgVersion.cs
tests/OpenClaw.SetupEngine.Tests/GatewayLkgVersionTests.cs
)
if git diff --quiet -- "${update_paths[@]}"; then
echo "No LKG change detected after update write."
exit 0
fi

git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add src/OpenClaw.SetupEngine/GatewayLkgVersion.cs
git add "${update_paths[@]}"
git commit -m "chore(setup): bump gateway LKG to ${{ steps.versions.outputs.latest }}"
git push --force-with-lease origin "${BRANCH_NAME}"

Expand All @@ -121,7 +147,9 @@ jobs:

- Previous pinned LKG: \`${{ steps.versions.outputs.pinned }}\`
- Candidate latest: \`${{ steps.versions.outputs.latest }}\`
- Updated file: \`src/OpenClaw.SetupEngine/GatewayLkgVersion.cs\`
- Updated files: LKG source and its contract test

The automation only proposes exact stable versions newer than the current pin.

This is the standing automation PR used to review and validate gateway LKG bumps before merge.
EOF
Expand Down
Loading
Loading