Skip to content

Commit cf25d82

Browse files
authored
Merge branch 'main' into main
2 parents 032d421 + 8f6f261 commit cf25d82

383 files changed

Lines changed: 20735 additions & 3826 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
name: Blacksmith ARM Testbox
2+
on:
3+
workflow_dispatch:
4+
inputs:
5+
testbox_id:
6+
type: string
7+
description: "Testbox session ID"
8+
required: true
9+
pull_request:
10+
paths:
11+
- ".github/workflows/**"
12+
13+
permissions:
14+
contents: read
15+
16+
env:
17+
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
18+
PNPM_CONFIG_STORE_DIR: "/tmp/openclaw-pnpm-store"
19+
PNPM_CONFIG_VERIFY_DEPS_BEFORE_RUN: "false"
20+
21+
jobs:
22+
check-arm:
23+
if: ${{ github.event_name != 'pull_request' || !github.event.pull_request.draft }}
24+
permissions:
25+
contents: read
26+
name: "check-arm"
27+
runs-on: blacksmith-16vcpu-ubuntu-2404-arm
28+
timeout-minutes: 120
29+
steps:
30+
- name: Begin Testbox
31+
uses: useblacksmith/begin-testbox@d0e04585c26905fdd92c94a09c159544c7ee1b67
32+
with:
33+
testbox_id: ${{ inputs.testbox_id }}
34+
- name: Verify ARM runner
35+
shell: bash
36+
run: |
37+
set -euo pipefail
38+
39+
runner_arch="$(uname -m)"
40+
echo "check-arm runner architecture: ${runner_arch}"
41+
case "$runner_arch" in
42+
aarch64 | arm64)
43+
;;
44+
*)
45+
echo "check-arm requires an ARM64 runner; got ${runner_arch}" >&2
46+
exit 1
47+
;;
48+
esac
49+
- name: Checkout
50+
shell: bash
51+
env:
52+
CHECKOUT_REPO: ${{ github.repository }}
53+
CHECKOUT_SHA: ${{ github.sha }}
54+
CHECKOUT_TOKEN: ${{ github.token }}
55+
run: |
56+
set -euo pipefail
57+
58+
workdir="$GITHUB_WORKSPACE"
59+
if [[ -z "$CHECKOUT_TOKEN" ]]; then
60+
echo "checkout token is missing" >&2
61+
exit 1
62+
fi
63+
auth_header="$(printf 'x-access-token:%s' "$CHECKOUT_TOKEN" | base64 | tr -d '\n')"
64+
65+
reset_checkout_dir() {
66+
mkdir -p "$workdir"
67+
find "$workdir" -mindepth 1 -maxdepth 1 -exec rm -rf {} +
68+
}
69+
70+
checkout_attempt() {
71+
local attempt="$1"
72+
73+
reset_checkout_dir
74+
git init "$workdir" >/dev/null
75+
git config --global --add safe.directory "$workdir"
76+
git -C "$workdir" remote add origin "https://github.com/${CHECKOUT_REPO}"
77+
git -C "$workdir" config gc.auto 0
78+
79+
timeout --signal=TERM --kill-after=10s 30s git -C "$workdir" \
80+
-c protocol.version=2 \
81+
-c "http.extraheader=AUTHORIZATION: basic ${auth_header}" \
82+
fetch --no-tags --prune --no-recurse-submodules --depth=1 origin \
83+
"+${CHECKOUT_SHA}:refs/remotes/origin/ci-target" || return 1
84+
85+
git -C "$workdir" checkout --force --detach "$CHECKOUT_SHA" || return 1
86+
test -f "$workdir/.github/actions/setup-node-env/action.yml" || return 1
87+
echo "checkout attempt ${attempt}/5 succeeded"
88+
}
89+
90+
for attempt in 1 2 3 4 5; do
91+
if checkout_attempt "$attempt"; then
92+
exit 0
93+
fi
94+
echo "checkout attempt ${attempt}/5 failed"
95+
sleep $((attempt * 5))
96+
done
97+
98+
echo "checkout failed after 5 attempts" >&2
99+
exit 1
100+
- name: Setup Node environment
101+
uses: ./.github/actions/setup-node-env
102+
with:
103+
install-bun: "false"
104+
- name: Prepare Testbox shell
105+
shell: bash
106+
run: |
107+
set -euo pipefail
108+
109+
timeout --signal=TERM --kill-after=10s 30s git \
110+
-c protocol.version=2 \
111+
fetch --no-tags --prune --no-recurse-submodules --depth=50 origin \
112+
"+refs/heads/main:refs/remotes/origin/main"
113+
114+
node_bin="$(dirname "$(node -p 'process.execPath')")"
115+
sudo ln -sf "$node_bin/node" /usr/local/bin/node
116+
sudo ln -sf "$node_bin/npm" /usr/local/bin/npm
117+
sudo ln -sf "$node_bin/npx" /usr/local/bin/npx
118+
sudo ln -sf "$node_bin/corepack" /usr/local/bin/corepack
119+
sudo tee /usr/local/bin/pnpm >/dev/null <<'PNPM'
120+
#!/usr/bin/env bash
121+
exec /usr/local/bin/corepack pnpm "$@"
122+
PNPM
123+
sudo chmod 0755 /usr/local/bin/pnpm
124+
125+
- name: Hydrate Testbox provider env helper
126+
shell: bash
127+
env:
128+
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
129+
ANTHROPIC_API_KEY_OLD: ${{ secrets.ANTHROPIC_API_KEY_OLD }}
130+
ANTHROPIC_API_TOKEN: ${{ secrets.ANTHROPIC_API_TOKEN }}
131+
CEREBRAS_API_KEY: ${{ secrets.CEREBRAS_API_KEY }}
132+
DEEPINFRA_API_KEY: ${{ secrets.DEEPINFRA_API_KEY }}
133+
FACTORY_API_KEY: ${{ secrets.FACTORY_API_KEY }}
134+
FIREWORKS_API_KEY: ${{ secrets.FIREWORKS_API_KEY }}
135+
GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
136+
GOOGLE_API_KEY: ${{ secrets.GOOGLE_API_KEY }}
137+
GROQ_API_KEY: ${{ secrets.GROQ_API_KEY }}
138+
KIMI_API_KEY: ${{ secrets.KIMI_API_KEY }}
139+
MINIMAX_API_KEY: ${{ secrets.MINIMAX_API_KEY }}
140+
MISTRAL_API_KEY: ${{ secrets.MISTRAL_API_KEY }}
141+
MOONSHOT_API_KEY: ${{ secrets.MOONSHOT_API_KEY }}
142+
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
143+
OPENAI_BASE_URL: ${{ secrets.OPENAI_BASE_URL }}
144+
OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }}
145+
QWEN_API_KEY: ${{ secrets.QWEN_API_KEY }}
146+
TOGETHER_API_KEY: ${{ secrets.TOGETHER_API_KEY }}
147+
XAI_API_KEY: ${{ secrets.XAI_API_KEY }}
148+
ZAI_API_KEY: ${{ secrets.ZAI_API_KEY }}
149+
Z_AI_API_KEY: ${{ secrets.Z_AI_API_KEY }}
150+
run: bash scripts/ci-hydrate-testbox-env.sh
151+
152+
- name: Run Testbox
153+
uses: useblacksmith/run-testbox@5ca05834db1d3813554d1dd109e5f2087a8d7cbc
154+
if: success()
155+
env:
156+
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"

.github/workflows/ci-check-testbox.yml

Lines changed: 0 additions & 136 deletions
Original file line numberDiff line numberDiff line change
@@ -139,139 +139,3 @@ jobs:
139139
if: success()
140140
env:
141141
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
142-
143-
check-arm:
144-
if: ${{ github.event_name != 'pull_request' || !github.event.pull_request.draft }}
145-
permissions:
146-
contents: read
147-
name: "check-arm"
148-
runs-on: blacksmith-16vcpu-ubuntu-2404-arm
149-
timeout-minutes: 120
150-
steps:
151-
- name: Begin Testbox
152-
uses: useblacksmith/begin-testbox@d0e04585c26905fdd92c94a09c159544c7ee1b67
153-
with:
154-
testbox_id: ${{ inputs.testbox_id }}
155-
- name: Verify ARM runner
156-
shell: bash
157-
run: |
158-
set -euo pipefail
159-
160-
runner_arch="$(uname -m)"
161-
echo "check-arm runner architecture: ${runner_arch}"
162-
case "$runner_arch" in
163-
aarch64 | arm64)
164-
;;
165-
*)
166-
echo "check-arm requires an ARM64 runner; got ${runner_arch}" >&2
167-
exit 1
168-
;;
169-
esac
170-
- name: Checkout
171-
shell: bash
172-
env:
173-
CHECKOUT_REPO: ${{ github.repository }}
174-
CHECKOUT_SHA: ${{ github.sha }}
175-
CHECKOUT_TOKEN: ${{ github.token }}
176-
run: |
177-
set -euo pipefail
178-
179-
workdir="$GITHUB_WORKSPACE"
180-
if [[ -z "$CHECKOUT_TOKEN" ]]; then
181-
echo "checkout token is missing" >&2
182-
exit 1
183-
fi
184-
auth_header="$(printf 'x-access-token:%s' "$CHECKOUT_TOKEN" | base64 | tr -d '\n')"
185-
186-
reset_checkout_dir() {
187-
mkdir -p "$workdir"
188-
find "$workdir" -mindepth 1 -maxdepth 1 -exec rm -rf {} +
189-
}
190-
191-
checkout_attempt() {
192-
local attempt="$1"
193-
194-
reset_checkout_dir
195-
git init "$workdir" >/dev/null
196-
git config --global --add safe.directory "$workdir"
197-
git -C "$workdir" remote add origin "https://github.com/${CHECKOUT_REPO}"
198-
git -C "$workdir" config gc.auto 0
199-
200-
timeout --signal=TERM --kill-after=10s 30s git -C "$workdir" \
201-
-c protocol.version=2 \
202-
-c "http.extraheader=AUTHORIZATION: basic ${auth_header}" \
203-
fetch --no-tags --prune --no-recurse-submodules --depth=1 origin \
204-
"+${CHECKOUT_SHA}:refs/remotes/origin/ci-target" || return 1
205-
206-
git -C "$workdir" checkout --force --detach "$CHECKOUT_SHA" || return 1
207-
test -f "$workdir/.github/actions/setup-node-env/action.yml" || return 1
208-
echo "checkout attempt ${attempt}/5 succeeded"
209-
}
210-
211-
for attempt in 1 2 3 4 5; do
212-
if checkout_attempt "$attempt"; then
213-
exit 0
214-
fi
215-
echo "checkout attempt ${attempt}/5 failed"
216-
sleep $((attempt * 5))
217-
done
218-
219-
echo "checkout failed after 5 attempts" >&2
220-
exit 1
221-
- name: Setup Node environment
222-
uses: ./.github/actions/setup-node-env
223-
with:
224-
install-bun: "false"
225-
- name: Prepare Testbox shell
226-
shell: bash
227-
run: |
228-
set -euo pipefail
229-
230-
timeout --signal=TERM --kill-after=10s 30s git \
231-
-c protocol.version=2 \
232-
fetch --no-tags --prune --no-recurse-submodules --depth=50 origin \
233-
"+refs/heads/main:refs/remotes/origin/main"
234-
235-
node_bin="$(dirname "$(node -p 'process.execPath')")"
236-
sudo ln -sf "$node_bin/node" /usr/local/bin/node
237-
sudo ln -sf "$node_bin/npm" /usr/local/bin/npm
238-
sudo ln -sf "$node_bin/npx" /usr/local/bin/npx
239-
sudo ln -sf "$node_bin/corepack" /usr/local/bin/corepack
240-
sudo tee /usr/local/bin/pnpm >/dev/null <<'PNPM'
241-
#!/usr/bin/env bash
242-
exec /usr/local/bin/corepack pnpm "$@"
243-
PNPM
244-
sudo chmod 0755 /usr/local/bin/pnpm
245-
246-
- name: Hydrate Testbox provider env helper
247-
shell: bash
248-
env:
249-
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
250-
ANTHROPIC_API_KEY_OLD: ${{ secrets.ANTHROPIC_API_KEY_OLD }}
251-
ANTHROPIC_API_TOKEN: ${{ secrets.ANTHROPIC_API_TOKEN }}
252-
CEREBRAS_API_KEY: ${{ secrets.CEREBRAS_API_KEY }}
253-
DEEPINFRA_API_KEY: ${{ secrets.DEEPINFRA_API_KEY }}
254-
FACTORY_API_KEY: ${{ secrets.FACTORY_API_KEY }}
255-
FIREWORKS_API_KEY: ${{ secrets.FIREWORKS_API_KEY }}
256-
GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
257-
GOOGLE_API_KEY: ${{ secrets.GOOGLE_API_KEY }}
258-
GROQ_API_KEY: ${{ secrets.GROQ_API_KEY }}
259-
KIMI_API_KEY: ${{ secrets.KIMI_API_KEY }}
260-
MINIMAX_API_KEY: ${{ secrets.MINIMAX_API_KEY }}
261-
MISTRAL_API_KEY: ${{ secrets.MISTRAL_API_KEY }}
262-
MOONSHOT_API_KEY: ${{ secrets.MOONSHOT_API_KEY }}
263-
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
264-
OPENAI_BASE_URL: ${{ secrets.OPENAI_BASE_URL }}
265-
OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }}
266-
QWEN_API_KEY: ${{ secrets.QWEN_API_KEY }}
267-
TOGETHER_API_KEY: ${{ secrets.TOGETHER_API_KEY }}
268-
XAI_API_KEY: ${{ secrets.XAI_API_KEY }}
269-
ZAI_API_KEY: ${{ secrets.ZAI_API_KEY }}
270-
Z_AI_API_KEY: ${{ secrets.Z_AI_API_KEY }}
271-
run: bash scripts/ci-hydrate-testbox-env.sh
272-
273-
- name: Run Testbox
274-
uses: useblacksmith/run-testbox@5ca05834db1d3813554d1dd109e5f2087a8d7cbc
275-
if: success()
276-
env:
277-
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"

.github/workflows/crabbox-hydrate.yml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,21 @@ jobs:
120120
append_pnpm_option_arg PNPM_CONFIG_MODULES_DIR modules-dir
121121
append_pnpm_option_arg PNPM_CONFIG_NETWORK_CONCURRENCY network-concurrency
122122
append_pnpm_option_arg PNPM_CONFIG_VIRTUAL_STORE_DIR virtual-store-dir
123+
reset_crabbox_pnpm_path() {
124+
local path="$1"
125+
if [ -z "$path" ]; then
126+
return
127+
fi
128+
case "$path" in
129+
/var/tmp/openclaw-pnpm-*) rm -rf "$path" ;;
130+
esac
131+
}
132+
reset_crabbox_pnpm_path "${PNPM_CONFIG_MODULES_DIR:-}"
133+
reset_crabbox_pnpm_path "${PNPM_CONFIG_STORE_DIR:-}"
134+
reset_crabbox_pnpm_path "${PNPM_CONFIG_VIRTUAL_STORE_DIR:-}"
135+
if [ -L node_modules ] && [ "$(readlink node_modules)" = "${PNPM_CONFIG_MODULES_DIR:-}" ]; then
136+
rm -f node_modules
137+
fi
123138
if [ -n "${PNPM_CONFIG_MODULES_DIR:-}" ]; then
124139
mkdir -p "$PNPM_CONFIG_MODULES_DIR"
125140
ln -sfn . "$PNPM_CONFIG_MODULES_DIR/node_modules"

.github/workflows/docker-release.yml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ on:
44
push:
55
tags:
66
- "v*"
7+
- "!v*-alpha.*"
78
paths-ignore:
89
- "docs/**"
910
- "**/*.md"
@@ -38,7 +39,11 @@ jobs:
3839
RELEASE_TAG: ${{ inputs.tag }}
3940
run: |
4041
set -euo pipefail
41-
if [[ ! "${RELEASE_TAG}" =~ ^v[0-9]{4}\.[1-9][0-9]*\.[1-9][0-9]*(-(alpha|beta)\.[1-9][0-9]*)?$ ]]; then
42+
if [[ "${RELEASE_TAG}" == *"-alpha."* ]]; then
43+
echo "Docker alpha image publishing is disabled."
44+
exit 1
45+
fi
46+
if [[ ! "${RELEASE_TAG}" =~ ^v[0-9]{4}\.[1-9][0-9]*\.[1-9][0-9]*(-beta\.[1-9][0-9]*)?$ ]]; then
4247
echo "Invalid release tag: ${RELEASE_TAG}"
4348
exit 1
4449
fi

CHANGELOG.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,41 @@ Docs: https://docs.openclaw.ai
4747

4848
- Agents/providers: avoid loading owner plugin runtimes for explicitly configured custom provider models during OpenAI-compatible transport setup.
4949
- Release/CI/E2E: fail early when Crabbox sparse-sync full checkouts do not have enough local disk, with guidance for moving the sync root.
50+
- Release/CI/E2E: reset shared Crabbox pnpm hydrate state before installs so stale `/var/tmp` stores cannot leave `pnpm install` spinning after completion.
51+
- Release/CI/E2E: print heartbeat progress during centralized Docker builds while keeping successful build logs quiet.
52+
- Release/CI/E2E: avoid heartbeat-tail delays in Docker E2E log wrappers while reporting captured log bytes during long runs.
53+
- Release/CI/E2E: keep release user-journey logs and temporary plugin fixtures under per-run scratch roots so parallel runs cannot collide or leak artifacts.
54+
- Release/CI/E2E: bound release candidate GitHub API calls so stalled network requests cannot wedge workflow and artifact polling.
55+
- Release/CI/E2E: bound Discord smoke API calls in cross-OS release checks so host-side round trips cannot hang on stalled fetches.
56+
- Release/CI/E2E: bound RPC RTT gateway readiness probes so a half-open local HTTP response cannot stall cleanup past the readiness deadline.
57+
- Release/CI/E2E: stop RPC RTT gateway process groups so pnpm wrapper children cannot survive measurement cleanup.
58+
- Release/CI/E2E: fail the kitchen-sink RPC walk when command RSS sampling captures no process samples.
59+
- Release/CI/E2E: force-stop memory/fd repro gateway children that survive listener cleanup.
60+
- Release/CI/E2E: remove fallback ClawHub skill-install home directories when proof runs fail.
61+
- Installers: fail the PowerShell installer when interactive onboarding exits non-zero.
62+
- Scripts/UI: stop descendant processes from wrapped non-interactive commands when `run-with-env` receives shutdown signals.
63+
- Release/CI/E2E: write multi-node update Docker artifacts to unique per-run directories by default so parallel runs cannot overwrite evidence.
64+
- Release/CI/E2E: write package Telegram Docker artifacts to unique per-run directories by default so parallel live/RTT runs cannot overwrite evidence.
65+
- Release/CI/E2E: keep plugin lifecycle matrix resource artifacts under a unique per-run scratch root so parallel runs cannot overwrite tarballs or inspect output.
66+
- Release/CI/E2E: bound mock OpenAI readiness probes in web-search and Telegram RTT Docker smokes so stalled HTTP accepts cannot hang cleanup or fall through.
67+
- Tooling: cancel oversized pnpm audit advisory responses before failing so registry error paths do not leave response bodies open.
68+
- Release/CI/E2E: stop tracked gateway and mock service process groups so descendant helpers do not survive E2E cleanup.
69+
- Release/CI/E2E: exit Telegram credential proof wrappers promptly after forwarded shutdown signals while keeping the descendant force-kill guard armed.
70+
- Release/CI/E2E: reject oversized ClickClack fixture request bodies before release journey smokes can accumulate unbounded payloads.
71+
- Release/CI/E2E: reject oversized OpenAI image-auth mock request bodies before Docker proof runs can accumulate unbounded payloads.
72+
- Release/CI/E2E: require the Kitchen Sink RPC walk to prove every expected plugin tool is cataloged and effective before invoking tool fixtures.
73+
- Release/CI/E2E: stop tracked Docker build commands when centralized build wrappers receive shutdown signals.
74+
- Release/CI/E2E: cover MCP channel pairing reconnects by asserting the same temporary client state is reused across reconnects.
75+
- Release/CI/E2E: require QA channel baseline and reconnect scenarios to assert their scenario markers instead of accepting any outbound reply.
76+
- Release/CI/E2E: fail secret-provider proof runs when temporary state cleanup still fails after retries instead of hiding the cleanup error.
77+
- Release/CI/E2E: fail package-candidate ref proofs when temporary source worktree cleanup fails instead of leaving stale worktrees behind.
78+
- Release/CI/E2E: remove package tarball extract directories when tar extraction fails before validation can continue.
79+
- Release/CI/E2E: retry generated temp-state cleanup after removal failures and route plugin lifecycle measurement edits to their owner tests.
80+
- Release/CI/E2E: close parent gateway log handles after spawning RPC RTT probes so repeated measurements do not leak file descriptors.
81+
- Release/CI/E2E: fail RPC RTT probes when temporary state cleanup fails instead of hiding leftover scratch directories.
82+
- Release/CI/E2E: fail Kitchen Sink RPC walks when temporary state cleanup still fails after retries instead of silently preserving scratch roots.
83+
- Control UI: lazy-load the usage view so the initial app bundle stays below the chunk warning threshold.
84+
- Build: keep Baileys optional image backends external so source builds do not warn about missing `jimp` or `sharp`.
5085
- Build: render independent CLI startup metadata help snapshots concurrently to cut cold build-all metadata time.
5186
- Plugins: stop timed-out package-boundary prep steps by process group so descendant TypeScript/helper processes do not survive local check cleanup.
5287
- Control UI: serve static assets asynchronously after safe-open checks so large UI files do not block Gateway request handling.

0 commit comments

Comments
 (0)