惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

D
Docker
B
Blog RSS Feed
Microsoft Security Blog
Microsoft Security Blog
Y
Y Combinator Blog
N
Netflix TechBlog - Medium
M
MIT News - Artificial intelligence
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
B
Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
C
Check Point Blog
The GitHub Blog
The GitHub Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
P
Proofpoint News Feed
Martin Fowler
Martin Fowler
大猫的无限游戏
大猫的无限游戏
GbyAI
GbyAI
博客园_首页
A
About on SuperTechFans
Blog — PlanetScale
Blog — PlanetScale
人人都是产品经理
人人都是产品经理
T
Tailwind CSS Blog
aimingoo的专栏
aimingoo的专栏
T
The Blog of Author Tim Ferriss
The Cloudflare Blog

Recent Commits to openclaw:main

test: merge chat side-result checks · openclaw/openclaw@ddd2c2a test: merge cron history checks · openclaw/openclaw@f7eb746 test: merge responsive navigation shell checks · openclaw/openclaw@c2e4b47 docs(changelog): add codex oauth fixes · openclaw/openclaw@628e6cd test: merge navigation routing cases · openclaw/openclaw@5d8cecb Tests: mock channel registry bundled fallback · openclaw/openclaw@2b08233 Secrets: avoid broad web search discovery for single plugin config · openclaw/openclaw@a464f59 test: merge config view browser checks · openclaw/openclaw@20cf511 fix(status): align oauth health with runtime · openclaw/openclaw@eed7116 feat: add macOS screen snapshots for monitor preview (#67954) thanks … · openclaw/openclaw@f377db1 fix: report shared auth scopes in hello-ok (#67810) thanks @BunsDev · openclaw/openclaw@0b6c39b Auto-reply: avoid eager bundled route fallback · openclaw/openclaw@3ea1bf4 Tests: narrow session binding contract setup · openclaw/openclaw@54e4e16 fix(macOS): enable undo/redo in webchat composer text input (#34962) · openclaw/openclaw@00951dc Tests: speed up channel setup promotion · openclaw/openclaw@82b529a Docs: refresh agent instructions · openclaw/openclaw@5775fe2 fix(auth): serialize OAuth refresh across agents to fix #26322 (#67876) · openclaw/openclaw@8e79080 test: allow ollama public surface boundary test · openclaw/openclaw@7d4f1a6 Docs: add test performance guardrails · openclaw/openclaw@89706d3 Tests: restore context-engine usage proof · openclaw/openclaw@e4c4f95 Tests: slim context engine runtime coverage · openclaw/openclaw@74c198f ci: retry failed custom checkouts · openclaw/openclaw@0ee5baf test: trim duplicate provider auth onboarding cases · openclaw/openclaw@1ffc02e matrix: fix sessions_spawn --thread subagent session spawning (#67643) · openclaw/openclaw@1ce2596 test: reduce auth choice fixture churn · openclaw/openclaw@857b9cd test: mock health status config boundaries · openclaw/openclaw@9d5ab4a test: mock onboard config io boundary · openclaw/openclaw@299694d test: mock legacy state plugin boundaries · openclaw/openclaw@2713089 test: mock channel install boundaries · openclaw/openclaw@b945248 test: mock doctor preview channel boundaries · openclaw/openclaw@b1a3ad4
ci(release): streamline beta publish verification · openc...
steipete · 2026-05-21 · via Recent Commits to openclaw:main

@@ -348,6 +348,7 @@ jobs:

348348

needs: [resolve_release_target]

349349

runs-on: ubuntu-latest

350350

timeout-minutes: 60

351+

environment: npm-release

351352

steps:

352353

- name: Checkout release SHA

353354

uses: actions/checkout@v6

@@ -450,7 +451,7 @@ jobs:

450451451452

pending_json="$(gh api -X GET "repos/${GITHUB_REPOSITORY}/actions/runs/${run_id}/pending_deployments" 2>/dev/null || true)"

452453

if [[ -z "${pending_json}" ]] || ! printf '%s' "${pending_json}" | jq -e 'length > 0' >/dev/null 2>&1; then

453-

return 0

454+

return 1

454455

fi

455456456457

approved=0

@@ -462,13 +463,15 @@ jobs:

462463

gh api -X POST "repos/${GITHUB_REPOSITORY}/actions/runs/${run_id}/pending_deployments" \

463464

-F "environment_ids[]=${env_id}" \

464465

-f state=approved \

465-

-f comment="Approve release gate from OpenClaw Release Publish wrapper" >/dev/null

466+

-f comment="Approve child release gate after parent release approval" >/dev/null

466467

approved=1

467468

done < <(printf '%s' "${pending_json}" | jq -r '.[] | select(.current_user_can_approve == true) | [.environment.id, .environment.name] | @tsv')

468469469470

if [[ "${approved}" == "1" ]]; then

470471

echo "${workflow}: approved available pending environment gates"

472+

return 0

471473

fi

474+

return 1

472475

}

473476474477

print_failed_run_summary() {

@@ -511,7 +514,7 @@ jobs:

511514

if [[ "$state" != "$last_state" ]]; then

512515

echo "${workflow} still ${status} (updated ${updated_at}): ${url}"

513516

print_pending_deployments "${workflow}" "${run_id}"

514-

approve_pending_deployments "${workflow}" "${run_id}"

517+

approve_pending_deployments "${workflow}" "${run_id}" || true

515518

last_state="$state"

516519

fi

517520

sleep 30

@@ -558,6 +561,85 @@ jobs:

558561

wait_run_pid="$!"

559562

}

560563564+

wait_for_job_success() {

565+

local workflow="$1"

566+

local run_id="$2"

567+

local job_name="$3"

568+

local jobs_json job_json run_status run_conclusion status conclusion url deadline

569+570+

deadline=$((SECONDS + 900))

571+

while true; do

572+

jobs_json="$(gh run view --repo "$GITHUB_REPOSITORY" "$run_id" --json status,conclusion,jobs)"

573+

run_status="$(printf '%s' "$jobs_json" | jq -r '.status')"

574+

run_conclusion="$(printf '%s' "$jobs_json" | jq -r '.conclusion // ""')"

575+

job_json="$(printf '%s' "$jobs_json" | jq -c --arg name "$job_name" '.jobs[]? | select(.name == $name) | {status, conclusion, url}' | head -n 1)"

576+

if [[ -n "$job_json" ]]; then

577+

status="$(printf '%s' "$job_json" | jq -r '.status')"

578+

conclusion="$(printf '%s' "$job_json" | jq -r '.conclusion // ""')"

579+

url="$(printf '%s' "$job_json" | jq -r '.url // ""')"

580+

if [[ "$status" == "completed" ]]; then

581+

if [[ "$conclusion" == "success" || "$conclusion" == "skipped" ]]; then

582+

echo "${workflow} ${job_name} ${conclusion}: ${url}"

583+

echo "- ${workflow} ${job_name}: ${conclusion} (${url})" >> "$GITHUB_STEP_SUMMARY"

584+

return 0

585+

fi

586+

echo "${workflow} ${job_name} failed: ${conclusion} ${url}" >&2

587+

print_failed_run_summary "${run_id}"

588+

return 1

589+

fi

590+

echo "${workflow} ${job_name} still ${status}: ${url}"

591+

elif [[ "$run_status" == "completed" ]]; then

592+

if [[ "$run_conclusion" == "success" ]]; then

593+

echo "${workflow} completed before ${job_name} was needed."

594+

echo "- ${workflow} ${job_name}: not needed" >> "$GITHUB_STEP_SUMMARY"

595+

return 0

596+

fi

597+

echo "${workflow} completed before ${job_name} with ${run_conclusion}." >&2

598+

print_failed_run_summary "${run_id}"

599+

return 1

600+

else

601+

echo "${workflow} waiting for ${job_name} to start: https://github.com/${GITHUB_REPOSITORY}/actions/runs/${run_id}"

602+

fi

603+

if (( SECONDS >= deadline )); then

604+

echo "${workflow} ${job_name} did not complete within 15 minutes." >&2

605+

return 1

606+

fi

607+

sleep 10

608+

done

609+

}

610+611+

approve_child_publish_environment() {

612+

local workflow="$1"

613+

local run_id="$2"

614+

local run_json status conclusion deadline

615+616+

deadline=$((SECONDS + 900))

617+

while true; do

618+

if approve_pending_deployments "${workflow}" "${run_id}"; then

619+

echo "- ${workflow}: child environment gate approved" >> "$GITHUB_STEP_SUMMARY"

620+

return 0

621+

fi

622+

run_json="$(gh run view --repo "$GITHUB_REPOSITORY" "$run_id" --json status,conclusion,url)"

623+

status="$(printf '%s' "$run_json" | jq -r '.status')"

624+

conclusion="$(printf '%s' "$run_json" | jq -r '.conclusion // ""')"

625+

if [[ "$status" == "completed" ]]; then

626+

if [[ "$conclusion" == "success" ]]; then

627+

echo "${workflow}: completed before child environment approval was needed"

628+

return 0

629+

fi

630+

echo "${workflow}: completed before child environment approval with ${conclusion}" >&2

631+

print_failed_run_summary "${run_id}"

632+

return 1

633+

fi

634+

if (( SECONDS >= deadline )); then

635+

echo "${workflow}: child environment approval was not available within 15 minutes." >&2

636+

print_pending_deployments "${workflow}" "${run_id}"

637+

return 1

638+

fi

639+

sleep 10

640+

done

641+

}

642+561643

create_or_update_github_release() {

562644

local release_version notes_version title notes_file changelog_file latest_arg prerelease_args

563645

release_version="${RELEASE_TAG#v}"

@@ -679,12 +761,81 @@ jobs:

679761

} >> "$GITHUB_STEP_SUMMARY"

680762

}

681763764+

append_release_proof_to_github_release() {

765+

local release_version body_file notes_file tarball integrity telegram_line clawhub_line

766+767+

release_version="${RELEASE_TAG#v}"

768+

body_file="${RUNNER_TEMP}/release-body.md"

769+

notes_file="${RUNNER_TEMP}/release-notes-with-proof.md"

770+

tarball="$(npm view "openclaw@${release_version}" dist.tarball --json | jq -r '.')"

771+

integrity="$(npm view "openclaw@${release_version}" dist.integrity --json | jq -r '.')"

772+

gh release view "${RELEASE_TAG}" --repo "$GITHUB_REPOSITORY" --json body --jq .body > "${body_file}"

773+774+

if [[ -n "${NPM_TELEGRAM_RUN_ID// }" ]]; then

775+

telegram_line="- npm Telegram beta E2E: https://github.com/${GITHUB_REPOSITORY}/actions/runs/${NPM_TELEGRAM_RUN_ID}"

776+

else

777+

telegram_line="- npm Telegram beta E2E: not supplied"

778+

fi

779+

if [[ "${WAIT_FOR_CLAWHUB}" == "true" ]]; then

780+

clawhub_line="- plugin ClawHub publish: https://github.com/${GITHUB_REPOSITORY}/actions/runs/${plugin_clawhub_run_id}"

781+

else

782+

clawhub_line="- plugin ClawHub publish: dispatched separately, not awaited by this proof: https://github.com/${GITHUB_REPOSITORY}/actions/runs/${plugin_clawhub_run_id}"

783+

fi

784+785+

RELEASE_BODY_FILE="${body_file}" \

786+

RELEASE_NOTES_FILE="${notes_file}" \

787+

RELEASE_VERSION="${release_version}" \

788+

RELEASE_TAG="${RELEASE_TAG}" \

789+

RELEASE_REPO="${GITHUB_REPOSITORY}" \

790+

RELEASE_TARBALL="${tarball}" \

791+

RELEASE_INTEGRITY="${integrity}" \

792+

RELEASE_PUBLISH_RUN_ID="${GITHUB_RUN_ID}" \

793+

PREFLIGHT_RUN_ID="${PREFLIGHT_RUN_ID}" \

794+

FULL_RELEASE_VALIDATION_RUN_ID="${FULL_RELEASE_VALIDATION_RUN_ID}" \

795+

PLUGIN_NPM_RUN_ID="${plugin_npm_run_id}" \

796+

OPENCLAW_NPM_RUN_ID="${openclaw_npm_run_id}" \

797+

CLAWHUB_LINE="${clawhub_line}" \

798+

TELEGRAM_LINE="${telegram_line}" \

799+

node --input-type=module <<'NODE'

800+

import { readFileSync, writeFileSync } from "node:fs";

801+802+

const bodyFile = process.env.RELEASE_BODY_FILE;

803+

const notesFile = process.env.RELEASE_NOTES_FILE;

804+

if (!bodyFile || !notesFile) {

805+

throw new Error("Missing release notes file paths.");

806+

}

807+808+

const body = readFileSync(bodyFile, "utf8").trimEnd();

809+

const section = [

810+

"### Release verification",

811+

"",

812+

`- npm package: https://www.npmjs.com/package/openclaw/v/${process.env.RELEASE_VERSION}`,

813+

`- registry tarball: ${process.env.RELEASE_TARBALL}`,

814+

`- integrity: \`${process.env.RELEASE_INTEGRITY}\``,

815+

`- release publish: https://github.com/${process.env.RELEASE_REPO}/actions/runs/${process.env.RELEASE_PUBLISH_RUN_ID}`,

816+

`- npm preflight: https://github.com/${process.env.RELEASE_REPO}/actions/runs/${process.env.PREFLIGHT_RUN_ID}`,

817+

`- full release validation: https://github.com/${process.env.RELEASE_REPO}/actions/runs/${process.env.FULL_RELEASE_VALIDATION_RUN_ID}`,

818+

`- plugin npm publish: https://github.com/${process.env.RELEASE_REPO}/actions/runs/${process.env.PLUGIN_NPM_RUN_ID}`,

819+

process.env.CLAWHUB_LINE,

820+

`- OpenClaw npm publish: https://github.com/${process.env.RELEASE_REPO}/actions/runs/${process.env.OPENCLAW_NPM_RUN_ID}`,

821+

process.env.TELEGRAM_LINE,

822+

].join("\n");

823+824+

const withoutOldProof = body.replace(/\n?### Release verification\n[\s\S]*?(?=\n### |\n## |$)/, "");

825+

writeFileSync(notesFile, `${withoutOldProof.trimEnd()}\n\n${section}\n`);

826+

NODE

827+828+

gh release edit "${RELEASE_TAG}" --repo "$GITHUB_REPOSITORY" --notes-file "${notes_file}"

829+

echo "- Release proof: appended to GitHub release" >> "$GITHUB_STEP_SUMMARY"

830+

}

831+682832

{

683833

echo "### Publish sequence"

684834

echo

685835

echo "- Workflow ref: \`${CHILD_WORKFLOW_REF}\`"

686836

echo "- Release tag: \`${RELEASE_TAG}\`"

687837

echo "- Release SHA: \`${TARGET_SHA}\`"

838+

echo "- Release approval: this workflow job"

688839

echo "- Plugin npm and ClawHub publish: dispatched in parallel"

689840

if [[ "${PUBLISH_OPENCLAW_NPM}" == "true" ]]; then

690841

echo "- OpenClaw npm publish: starts after plugin npm succeeds"

@@ -698,8 +849,8 @@ jobs:

698849

fi

699850

} >> "$GITHUB_STEP_SUMMARY"

700851701-

npm_args=(-f publish_scope="${PLUGIN_PUBLISH_SCOPE}" -f ref="${TARGET_SHA}")

702-

clawhub_args=(-f publish_scope="${PLUGIN_PUBLISH_SCOPE}" -f ref="${TARGET_SHA}")

852+

npm_args=(-f publish_scope="${PLUGIN_PUBLISH_SCOPE}" -f ref="${TARGET_SHA}" -f release_publish_run_id="${GITHUB_RUN_ID}")

853+

clawhub_args=(-f publish_scope="${PLUGIN_PUBLISH_SCOPE}" -f ref="${TARGET_SHA}" -f release_publish_run_id="${GITHUB_RUN_ID}")

703854

if [[ -n "${PLUGINS}" ]]; then

704855

npm_args+=(-f plugins="${PLUGINS}")

705856

clawhub_args+=(-f plugins="${PLUGINS}")

@@ -725,6 +876,7 @@ jobs:

725876

-f preflight_only=false \

726877

-f preflight_run_id="${PREFLIGHT_RUN_ID}" \

727878

-f full_release_validation_run_id="${FULL_RELEASE_VALIDATION_RUN_ID}" \

879+

-f release_publish_run_id="${GITHUB_RUN_ID}" \

728880

-f npm_dist_tag="${RELEASE_NPM_DIST_TAG}")"

729881

echo "- OpenClaw npm run ID: \`${openclaw_npm_run_id}\`" >> "$GITHUB_STEP_SUMMARY"

730882

else

@@ -739,7 +891,9 @@ jobs:

739891

wait_for_run_background plugin-clawhub-release.yml "${plugin_clawhub_run_id}" "${clawhub_result}"

740892

clawhub_pid="${wait_run_pid}"

741893

else

742-

echo "- plugin-clawhub-release.yml: not awaited (${plugin_clawhub_run_id})" >> "$GITHUB_STEP_SUMMARY"

894+

wait_for_job_success plugin-clawhub-release.yml "${plugin_clawhub_run_id}" "Validate release publish approval"

895+

approve_child_publish_environment plugin-clawhub-release.yml "${plugin_clawhub_run_id}"

896+

echo "- plugin-clawhub-release.yml: publish not awaited (${plugin_clawhub_run_id})" >> "$GITHUB_STEP_SUMMARY"

743897

fi

744898745899

openclaw_result=""

@@ -776,6 +930,7 @@ jobs:

776930777931

if [[ "${failed}" == "0" && -n "${openclaw_npm_run_id}" ]]; then

778932

verify_published_release

933+

append_release_proof_to_github_release

779934

fi

780935

if [[ "${failed}" != "0" ]]; then

781936

exit 1