


























@@ -0,0 +1,335 @@
1+name: OpenClaw Performance
2+3+on:
4+schedule:
5+ - cron: "11 5 * * *"
6+workflow_dispatch:
7+inputs:
8+profile:
9+description: Kova profile to run
10+required: false
11+default: diagnostic
12+type: choice
13+options:
14+ - smoke
15+ - diagnostic
16+ - soak
17+ - release
18+repeat:
19+description: Repeat count for non-profiled Kova runs
20+required: false
21+default: "3"
22+type: string
23+deep_profile:
24+description: Run the deep-profile lane with CPU/heap/trace artifacts
25+required: false
26+default: false
27+type: boolean
28+live_gpt54:
29+description: Run the live OpenAI GPT 5.4 agent-turn lane
30+required: false
31+default: false
32+type: boolean
33+fail_on_regression:
34+description: Fail the workflow when Kova exits non-zero
35+required: false
36+default: false
37+type: boolean
38+kova_ref:
39+description: Kova Git ref to install
40+required: false
41+default: 51947110f5cacb6ab2c0947594ea9628031c9fcf
42+type: string
43+44+permissions:
45+contents: read
46+47+concurrency:
48+group: ${{ github.event_name == 'workflow_dispatch' && format('{0}-{1}', github.workflow, github.run_id) || format('{0}-{1}', github.workflow, github.ref) }}
49+cancel-in-progress: false
50+51+env:
52+FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
53+OCM_VERSION: v0.2.15
54+PERFORMANCE_MODEL_ID: gpt-5.4
55+CLAWGRIT_REPORTS_TOKEN_PRESENT: ${{ secrets.CLAWGRIT_REPORTS_TOKEN != '' && 'true' || 'false' }}
56+57+jobs:
58+kova:
59+name: ${{ matrix.title }}
60+runs-on: blacksmith-16vcpu-ubuntu-2404
61+timeout-minutes: 240
62+strategy:
63+fail-fast: false
64+matrix:
65+include:
66+ - lane: mock-provider
67+title: Kova mock provider performance
68+auth: mock
69+repeat: input
70+deep_profile: "false"
71+live: "false"
72+include_filters: "scenario:fresh-install scenario:gateway-performance scenario:bundled-plugin-startup scenario:bundled-runtime-deps scenario:agent-cold-warm-message"
73+ - lane: mock-deep-profile
74+title: Kova mock provider deep profile
75+auth: mock
76+repeat: "1"
77+deep_profile: "true"
78+live: "false"
79+include_filters: "scenario:fresh-install scenario:gateway-performance scenario:agent-cold-warm-message"
80+ - lane: live-gpt54
81+title: Kova live OpenAI GPT 5.4 agent turn
82+auth: live
83+repeat: "1"
84+deep_profile: "false"
85+live: "true"
86+include_filters: "scenario:agent-cold-warm-message"
87+env:
88+KOVA_REF: ${{ inputs.kova_ref || '51947110f5cacb6ab2c0947594ea9628031c9fcf' }}
89+KOVA_HOME: ${{ github.workspace }}/.artifacts/kova/home/${{ matrix.lane }}
90+REPORT_DIR: ${{ github.workspace }}/.artifacts/kova/reports/${{ matrix.lane }}
91+BUNDLE_DIR: ${{ github.workspace }}/.artifacts/kova/bundles/${{ matrix.lane }}
92+SUMMARY_DIR: ${{ github.workspace }}/.artifacts/kova/summaries
93+LANE_ID: ${{ matrix.lane }}
94+PROFILE: ${{ inputs.profile || 'diagnostic' }}
95+REQUESTED_REPEAT: ${{ inputs.repeat || '3' }}
96+FAIL_ON_REGRESSION: ${{ inputs.fail_on_regression || 'false' }}
97+INCLUDE_FILTERS: ${{ matrix.include_filters }}
98+AUTH_MODE: ${{ matrix.auth }}
99+MATRIX_REPEAT: ${{ matrix.repeat }}
100+MATRIX_DEEP_PROFILE: ${{ matrix.deep_profile }}
101+MATRIX_LIVE: ${{ matrix.live }}
102+steps:
103+ - name: Decide lane
104+id: lane
105+shell: bash
106+run: |
107+ set -euo pipefail
108+ run_lane=true
109+ reason=""
110+ if [[ "$LANE_ID" == "mock-deep-profile" && "${{ github.event_name }}" != "schedule" && "${{ inputs.deep_profile || 'false' }}" != "true" ]]; then
111+ run_lane=false
112+ reason="deep_profile input is false"
113+ fi
114+ if [[ "$LANE_ID" == "live-gpt54" && "${{ github.event_name }}" != "schedule" && "${{ inputs.live_gpt54 || 'false' }}" != "true" ]]; then
115+ run_lane=false
116+ reason="live_gpt54 input is false"
117+ fi
118+ echo "run=$run_lane" >> "$GITHUB_OUTPUT"
119+ if [[ "$run_lane" != "true" ]]; then
120+ echo "Skipping ${LANE_ID}: ${reason}" >> "$GITHUB_STEP_SUMMARY"
121+ fi
122+123+ - name: Checkout OpenClaw
124+if: steps.lane.outputs.run == 'true'
125+uses: actions/checkout@v6
126+with:
127+fetch-depth: 1
128+persist-credentials: false
129+130+ - name: Set up Node environment
131+if: steps.lane.outputs.run == 'true'
132+uses: ./.github/actions/setup-node-env
133+with:
134+install-bun: "false"
135+136+ - name: Install OCM and Kova
137+if: steps.lane.outputs.run == 'true'
138+shell: bash
139+run: |
140+ set -euo pipefail
141+ KOVA_SRC="${RUNNER_TEMP}/kova-src"
142+ echo "KOVA_SRC=$KOVA_SRC" >> "$GITHUB_ENV"
143+ mkdir -p "$HOME/.local/bin" "$(dirname "$KOVA_SRC")"
144+ curl -fsSL https://raw.githubusercontent.com/shakkernerd/ocm/main/install.sh \
145+ | bash -s -- --version "$OCM_VERSION" --prefix "$HOME/.local" --force
146+ git clone --filter=blob:none https://github.com/shakkernerd/Kova.git "$KOVA_SRC"
147+ git -C "$KOVA_SRC" checkout "$KOVA_REF"
148+ cat > "$HOME/.local/bin/kova" <<EOF
149+ #!/usr/bin/env bash
150+ export KOVA_HOME="${KOVA_HOME}"
151+ exec node "${KOVA_SRC}/bin/kova.mjs" "\$@"
152+ EOF
153+ chmod 0755 "$HOME/.local/bin/kova"
154+ echo "$HOME/.local/bin" >> "$GITHUB_PATH"
155+156+ - name: Pin Kova OpenAI model to GPT 5.4
157+if: steps.lane.outputs.run == 'true'
158+shell: bash
159+run: |
160+ set -euo pipefail
161+ node - <<'NODE'
162+ const fs = require("node:fs");
163+ const path = require("node:path");
164+ const root = process.env.KOVA_SRC;
165+ const files = [
166+ "support/configure-openclaw-mock-auth.mjs",
167+ "support/configure-openclaw-live-auth.mjs",
168+ "support/mock-openai-server.mjs",
169+ "states/mock-openai-provider.json"
170+ ];
171+ for (const rel of files) {
172+ const file = path.join(root, rel);
173+ const before = fs.readFileSync(file, "utf8");
174+ const after = before.replaceAll("gpt-5.5", process.env.PERFORMANCE_MODEL_ID);
175+ fs.writeFileSync(file, after, "utf8");
176+ }
177+ NODE
178+179+ - name: Kova self-check
180+if: steps.lane.outputs.run == 'true'
181+run: kova self-check --json
182+183+ - name: Configure live OpenAI auth
184+if: ${{ steps.lane.outputs.run == 'true' && matrix.live == 'true' }}
185+env:
186+OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
187+OPENAI_BASE_URL: ${{ secrets.OPENAI_BASE_URL }}
188+shell: bash
189+run: |
190+ set -euo pipefail
191+ if [[ -z "${OPENAI_API_KEY:-}" ]]; then
192+ echo "OPENAI_API_KEY is not configured; live GPT 5.4 lane will be skipped." >> "$GITHUB_STEP_SUMMARY"
193+ exit 0
194+ fi
195+ kova setup --ci --json
196+ kova setup --non-interactive --auth env-only --provider openai --env-var OPENAI_API_KEY --json
197+198+ - name: Run Kova
199+id: kova
200+if: steps.lane.outputs.run == 'true'
201+env:
202+OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
203+OPENAI_BASE_URL: ${{ secrets.OPENAI_BASE_URL }}
204+shell: bash
205+run: |
206+ set -euo pipefail
207+ mkdir -p "$REPORT_DIR" "$BUNDLE_DIR" "$SUMMARY_DIR"
208+209+ if [[ "$MATRIX_LIVE" == "true" && -z "${OPENAI_API_KEY:-}" ]]; then
210+ echo "skipped=true" >> "$GITHUB_OUTPUT"
211+ exit 0
212+ fi
213+214+ repeat="$REQUESTED_REPEAT"
215+ if [[ "$MATRIX_REPEAT" != "input" ]]; then
216+ repeat="$MATRIX_REPEAT"
217+ fi
218+219+ args=(
220+ matrix run
221+ --profile "$PROFILE"
222+ --target "local-build:${GITHUB_WORKSPACE}"
223+ --auth "$AUTH_MODE"
224+ --parallel 1
225+ --repeat "$repeat"
226+ --report-dir "$REPORT_DIR"
227+ --execute
228+ --json
229+ )
230+231+ for filter in $INCLUDE_FILTERS; do
232+ args+=(--include "$filter")
233+ done
234+235+ if [[ "$MATRIX_DEEP_PROFILE" == "true" ]]; then
236+ args+=(--deep-profile)
237+ fi
238+ if [[ "$FAIL_ON_REGRESSION" == "true" ]]; then
239+ args+=(--gate)
240+ fi
241+242+ log_path="$REPORT_DIR/${LANE_ID}.log"
243+ set +e
244+ kova "${args[@]}" 2>&1 | tee "$log_path"
245+ status=${PIPESTATUS[0]}
246+ set -e
247+248+ report_json="$(find "$REPORT_DIR" -maxdepth 1 -type f -name '*.json' -print | sort | tail -n 1)"
249+ if [[ -z "$report_json" ]]; then
250+ echo "Kova did not write a JSON report." >&2
251+ exit 1
252+ fi
253+ report_md="${report_json%.json}.md"
254+ echo "status=$status" >> "$GITHUB_OUTPUT"
255+ echo "report_json=$report_json" >> "$GITHUB_OUTPUT"
256+ echo "report_md=$report_md" >> "$GITHUB_OUTPUT"
257+258+ kova report bundle "$report_json" --output-dir "$BUNDLE_DIR" --json | tee "$BUNDLE_DIR/bundle.json"
259+260+ ref_slug="$(printf '%s' "${GITHUB_REF_NAME}" | tr -c 'A-Za-z0-9._-' '-')"
261+ run_slug="${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}"
262+ report_url=""
263+ if [[ "$CLAWGRIT_REPORTS_TOKEN_PRESENT" == "true" ]]; then
264+ report_url="https://github.com/openclaw/clawgrit-reports/tree/main/openclaw-performance/${ref_slug}/${run_slug}/${LANE_ID}"
265+ fi
266+ summary_path="$SUMMARY_DIR/${LANE_ID}.md"
267+ node scripts/kova-ci-summary.mjs --report "$report_json" --output "$summary_path" --lane "$LANE_ID" --report-url "$report_url"
268+ cat "$summary_path" >> "$GITHUB_STEP_SUMMARY"
269+270+ if [[ "$FAIL_ON_REGRESSION" == "true" && "$status" != "0" ]]; then
271+ exit "$status"
272+ fi
273+274+ - name: Upload Kova artifacts
275+if: ${{ always() && steps.lane.outputs.run == 'true' }}
276+uses: actions/upload-artifact@v5
277+with:
278+name: openclaw-performance-${{ matrix.lane }}-${{ github.run_id }}-${{ github.run_attempt }}
279+path: |
280+ .artifacts/kova/reports/${{ matrix.lane }}
281+ .artifacts/kova/bundles/${{ matrix.lane }}
282+ .artifacts/kova/summaries/${{ matrix.lane }}.md
283+ if-no-files-found: ignore
284+retention-days: ${{ matrix.deep_profile == 'true' && 14 || 30 }}
285+286+ - name: Checkout clawgrit reports
287+if: ${{ steps.kova.outputs.report_json != '' && env.CLAWGRIT_REPORTS_TOKEN_PRESENT == 'true' }}
288+uses: actions/checkout@v6
289+with:
290+repository: openclaw/clawgrit-reports
291+path: .artifacts/clawgrit-reports
292+token: ${{ secrets.CLAWGRIT_REPORTS_TOKEN }}
293+persist-credentials: true
294+295+ - name: Publish to clawgrit reports
296+if: ${{ steps.kova.outputs.report_json != '' && env.CLAWGRIT_REPORTS_TOKEN_PRESENT == 'true' }}
297+shell: bash
298+run: |
299+ set -euo pipefail
300+ reports_root=".artifacts/clawgrit-reports"
301+ ref_slug="$(printf '%s' "${GITHUB_REF_NAME}" | tr -c 'A-Za-z0-9._-' '-')"
302+ run_slug="${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}"
303+ dest="${reports_root}/openclaw-performance/${ref_slug}/${run_slug}/${LANE_ID}"
304+ mkdir -p "$dest"
305+ cp "${{ steps.kova.outputs.report_json }}" "$dest/report.json"
306+ if [[ -f "${{ steps.kova.outputs.report_md }}" ]]; then
307+ cp "${{ steps.kova.outputs.report_md }}" "$dest/report.md"
308+ fi
309+ cp "$SUMMARY_DIR/${LANE_ID}.md" "$dest/index.md"
310+ if [[ -d "$BUNDLE_DIR" ]]; then
311+ mkdir -p "$dest/bundles"
312+ cp -R "$BUNDLE_DIR"/. "$dest/bundles/"
313+ fi
314+ cat > "${reports_root}/openclaw-performance/${ref_slug}/latest-${LANE_ID}.json" <<EOF
315+ {
316+ "repository": "${GITHUB_REPOSITORY}",
317+ "ref": "${GITHUB_REF_NAME}",
318+ "sha": "${GITHUB_SHA}",
319+ "workflow": "${GITHUB_WORKFLOW}",
320+ "run_id": "${GITHUB_RUN_ID}",
321+ "run_attempt": "${GITHUB_RUN_ATTEMPT}",
322+ "lane": "${LANE_ID}",
323+ "path": "openclaw-performance/${ref_slug}/${run_slug}/${LANE_ID}"
324+ }
325+ EOF
326+327+ git -C "$reports_root" config user.name "openclaw-performance[bot]"
328+ git -C "$reports_root" config user.email "openclaw-performance[bot]@users.noreply.github.com"
329+ git -C "$reports_root" add openclaw-performance
330+ if git -C "$reports_root" diff --cached --quiet; then
331+ echo "No clawgrit report changes to publish."
332+ exit 0
333+ fi
334+ git -C "$reports_root" commit -m "perf: add OpenClaw ${LANE_ID} report ${GITHUB_SHA::12}"
335+ git -C "$reports_root" push
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。