mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 08:40:44 +00:00
ci: split plugin prerelease validation
This commit is contained in:
274
.github/workflows/ci.yml
vendored
274
.github/workflows/ci.yml
vendored
@@ -8,11 +8,6 @@ on:
|
||||
required: false
|
||||
default: ""
|
||||
type: string
|
||||
full_release_validation:
|
||||
description: Run release-only CI lanes. Reserved for Full Release Validation.
|
||||
required: false
|
||||
default: false
|
||||
type: boolean
|
||||
include_android:
|
||||
description: Run Android lanes for this manual CI dispatch.
|
||||
required: false
|
||||
@@ -60,8 +55,6 @@ jobs:
|
||||
run_checks_fast: ${{ steps.manifest.outputs.run_checks_fast }}
|
||||
checks_fast_core_matrix: ${{ steps.manifest.outputs.checks_fast_core_matrix }}
|
||||
channel_contracts_matrix: ${{ steps.manifest.outputs.channel_contracts_matrix }}
|
||||
run_checks_node_extensions: ${{ steps.manifest.outputs.run_checks_node_extensions }}
|
||||
checks_node_extensions_matrix: ${{ steps.manifest.outputs.checks_node_extensions_matrix }}
|
||||
run_checks: ${{ steps.manifest.outputs.run_checks }}
|
||||
checks_matrix: ${{ steps.manifest.outputs.checks_matrix }}
|
||||
run_checks_node_core_nondist: ${{ steps.manifest.outputs.run_checks_node_core_nondist }}
|
||||
@@ -70,10 +63,6 @@ jobs:
|
||||
checks_node_core_dist_matrix: ${{ steps.manifest.outputs.checks_node_core_dist_matrix }}
|
||||
run_check: ${{ steps.manifest.outputs.run_check }}
|
||||
run_check_additional: ${{ steps.manifest.outputs.run_check_additional }}
|
||||
run_plugin_prerelease_suite: ${{ steps.manifest.outputs.run_plugin_prerelease_suite }}
|
||||
plugin_prerelease_ref: ${{ steps.manifest.outputs.plugin_prerelease_ref }}
|
||||
plugin_prerelease_static_matrix: ${{ steps.manifest.outputs.plugin_prerelease_static_matrix }}
|
||||
plugin_prerelease_docker_lanes: ${{ steps.manifest.outputs.plugin_prerelease_docker_lanes }}
|
||||
run_build_smoke: ${{ steps.manifest.outputs.run_build_smoke }}
|
||||
run_check_docs: ${{ steps.manifest.outputs.run_check_docs }}
|
||||
run_control_ui_i18n: ${{ steps.manifest.outputs.run_control_ui_i18n }}
|
||||
@@ -132,7 +121,7 @@ jobs:
|
||||
OPENCLAW_CI_DOCS_CHANGED: ${{ github.event_name == 'workflow_dispatch' && 'true' || steps.docs_scope.outputs.docs_changed }}
|
||||
OPENCLAW_CI_RUN_NODE: ${{ github.event_name == 'workflow_dispatch' && 'true' || steps.changed_scope.outputs.run_node || 'false' }}
|
||||
OPENCLAW_CI_RUN_MACOS: ${{ github.event_name == 'workflow_dispatch' && 'true' || steps.changed_scope.outputs.run_macos || 'false' }}
|
||||
OPENCLAW_CI_RUN_ANDROID: ${{ github.event_name == 'workflow_dispatch' && (inputs.full_release_validation || inputs.include_android) && 'true' || steps.changed_scope.outputs.run_android || 'false' }}
|
||||
OPENCLAW_CI_RUN_ANDROID: ${{ github.event_name == 'workflow_dispatch' && inputs.include_android && 'true' || steps.changed_scope.outputs.run_android || 'false' }}
|
||||
OPENCLAW_CI_RUN_WINDOWS: ${{ github.event_name == 'workflow_dispatch' && 'true' || steps.changed_scope.outputs.run_windows || 'false' }}
|
||||
OPENCLAW_CI_RUN_NODE_FAST_ONLY: ${{ github.event_name == 'workflow_dispatch' && 'false' || steps.changed_scope.outputs.run_node_fast_only || 'false' }}
|
||||
OPENCLAW_CI_RUN_NODE_FAST_PLUGIN_CONTRACTS: ${{ github.event_name == 'workflow_dispatch' && 'false' || steps.changed_scope.outputs.run_node_fast_plugin_contracts || 'false' }}
|
||||
@@ -140,10 +129,6 @@ jobs:
|
||||
OPENCLAW_CI_RUN_SKILLS_PYTHON: ${{ github.event_name == 'workflow_dispatch' && 'true' || steps.changed_scope.outputs.run_skills_python || 'false' }}
|
||||
OPENCLAW_CI_RUN_CONTROL_UI_I18N: ${{ github.event_name == 'workflow_dispatch' && 'true' || steps.changed_scope.outputs.run_control_ui_i18n || 'false' }}
|
||||
OPENCLAW_CI_CHECKOUT_REVISION: ${{ steps.checkout_ref.outputs.sha }}
|
||||
OPENCLAW_CI_EVENT_NAME: ${{ github.event_name }}
|
||||
OPENCLAW_CI_FULL_RELEASE_VALIDATION: ${{ github.event_name == 'workflow_dispatch' && inputs.full_release_validation && 'true' || 'false' }}
|
||||
OPENCLAW_CI_PR_HEAD_REPOSITORY: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name || github.repository }}
|
||||
OPENCLAW_CI_PR_HEAD_SHA: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || '' }}
|
||||
OPENCLAW_CI_REPOSITORY: ${{ github.repository }}
|
||||
run: |
|
||||
node --input-type=module <<'EOF'
|
||||
@@ -154,10 +139,6 @@ jobs:
|
||||
import {
|
||||
createChannelContractTestShards,
|
||||
} from "./scripts/lib/channel-contract-test-plan.mjs";
|
||||
import {
|
||||
createExtensionTestShards,
|
||||
DEFAULT_EXTENSION_TEST_SHARD_COUNT,
|
||||
} from "./scripts/lib/extension-test-plan.mjs";
|
||||
|
||||
const parseBoolean = (value, fallback = false) => {
|
||||
if (value === undefined) return fallback;
|
||||
@@ -193,65 +174,6 @@ jobs:
|
||||
const runSkillsPython = parseBoolean(process.env.OPENCLAW_CI_RUN_SKILLS_PYTHON) && !docsOnly;
|
||||
const runControlUiI18n =
|
||||
parseBoolean(process.env.OPENCLAW_CI_RUN_CONTROL_UI_I18N) && !docsOnly;
|
||||
const isFullReleaseValidationCiRun =
|
||||
process.env.OPENCLAW_CI_EVENT_NAME === "workflow_dispatch" &&
|
||||
parseBoolean(process.env.OPENCLAW_CI_FULL_RELEASE_VALIDATION);
|
||||
const trustedPluginPrereleaseRef =
|
||||
process.env.OPENCLAW_CI_EVENT_NAME !== "pull_request" ||
|
||||
process.env.OPENCLAW_CI_PR_HEAD_REPOSITORY === process.env.OPENCLAW_CI_REPOSITORY;
|
||||
const pluginPrereleaseRef =
|
||||
process.env.OPENCLAW_CI_EVENT_NAME === "pull_request" && trustedPluginPrereleaseRef
|
||||
? process.env.OPENCLAW_CI_PR_HEAD_SHA
|
||||
: process.env.OPENCLAW_CI_CHECKOUT_REVISION;
|
||||
let runPluginPrereleaseSuite =
|
||||
isFullReleaseValidationCiRun && runNodeFull && isCanonicalRepository;
|
||||
const runReleaseOnlyPluginSuites =
|
||||
isFullReleaseValidationCiRun && runNodeFull && isCanonicalRepository;
|
||||
let pluginPrereleasePlan = { staticChecks: [], dockerLanes: [] };
|
||||
if (runPluginPrereleaseSuite) {
|
||||
try {
|
||||
const { assertPluginPrereleaseTestPlanComplete } = await import(
|
||||
"./scripts/lib/plugin-prerelease-test-plan.mjs"
|
||||
);
|
||||
pluginPrereleasePlan = assertPluginPrereleaseTestPlanComplete();
|
||||
} catch (error) {
|
||||
const errorCode =
|
||||
error && typeof error === "object" && "code" in error ? error.code : "";
|
||||
const moduleUrl =
|
||||
error && typeof error === "object" && "url" in error ? String(error.url) : "";
|
||||
if (
|
||||
errorCode === "ERR_MODULE_NOT_FOUND" &&
|
||||
moduleUrl.endsWith("/scripts/lib/plugin-prerelease-test-plan.mjs")
|
||||
) {
|
||||
console.warn(
|
||||
"Plugin prerelease plan unavailable in target ref; skipping plugin prerelease suite.",
|
||||
);
|
||||
runPluginPrereleaseSuite = false;
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
const extensionTestShardCount = isCanonicalRepository
|
||||
? DEFAULT_EXTENSION_TEST_SHARD_COUNT
|
||||
: Math.max(DEFAULT_EXTENSION_TEST_SHARD_COUNT, 36);
|
||||
const extensionShardMatrix = createMatrix(
|
||||
runReleaseOnlyPluginSuites
|
||||
? createExtensionTestShards({
|
||||
shardCount: extensionTestShardCount,
|
||||
}).map((shard) => ({
|
||||
check_name: shard.checkName,
|
||||
extensions_csv: shard.extensionIds.join(","),
|
||||
runner: isCanonicalRepository && [0, 1, 2, 3].includes(shard.index)
|
||||
? "blacksmith-8vcpu-ubuntu-2404"
|
||||
: isCanonicalRepository
|
||||
? "blacksmith-4vcpu-ubuntu-2404"
|
||||
: "ubuntu-24.04",
|
||||
shard_index: shard.index + 1,
|
||||
task: "extensions-batch",
|
||||
}))
|
||||
: [],
|
||||
);
|
||||
const checksFastCoreTasks = [];
|
||||
if (runNodeFull) {
|
||||
checksFastCoreTasks.push(
|
||||
@@ -280,7 +202,7 @@ jobs:
|
||||
|
||||
const nodeTestShards = runNodeFull
|
||||
? createNodeTestShards({
|
||||
includeReleaseOnlyPluginShards: runReleaseOnlyPluginSuites,
|
||||
includeReleaseOnlyPluginShards: false,
|
||||
}).map((shard) => ({
|
||||
check_name: shard.checkName,
|
||||
runtime: "node",
|
||||
@@ -310,8 +232,6 @@ jobs:
|
||||
channel_contracts_matrix: createMatrix(
|
||||
runNodeFull ? createChannelContractTestShards() : [],
|
||||
),
|
||||
run_checks_node_extensions: runReleaseOnlyPluginSuites,
|
||||
checks_node_extensions_matrix: extensionShardMatrix,
|
||||
run_checks: runNodeFull,
|
||||
checks_matrix: createMatrix(
|
||||
runNodeFull
|
||||
@@ -326,20 +246,6 @@ jobs:
|
||||
checks_node_core_dist_matrix: createMatrix(nodeTestDistShards),
|
||||
run_check: runNodeFull,
|
||||
run_check_additional: runNodeFull,
|
||||
run_plugin_prerelease_suite: runPluginPrereleaseSuite,
|
||||
plugin_prerelease_ref: runPluginPrereleaseSuite ? pluginPrereleaseRef : "",
|
||||
plugin_prerelease_static_matrix: createMatrix(
|
||||
runPluginPrereleaseSuite
|
||||
? pluginPrereleasePlan.staticChecks.map((check) => ({
|
||||
check_name: check.checkName,
|
||||
command: check.command,
|
||||
task: check.check,
|
||||
}))
|
||||
: [],
|
||||
),
|
||||
plugin_prerelease_docker_lanes: runPluginPrereleaseSuite
|
||||
? pluginPrereleasePlan.dockerLanes.join(" ")
|
||||
: "",
|
||||
run_build_smoke: runNodeFull,
|
||||
run_check_docs: docsChanged,
|
||||
run_control_ui_i18n: runControlUiI18n,
|
||||
@@ -995,97 +901,6 @@ jobs:
|
||||
- name: Run protocol check
|
||||
run: pnpm protocol:check
|
||||
|
||||
checks-node-extensions-shard:
|
||||
permissions:
|
||||
contents: read
|
||||
name: ${{ matrix.check_name }}
|
||||
needs: [preflight]
|
||||
if: needs.preflight.outputs.run_checks_node_extensions == 'true'
|
||||
runs-on: ${{ matrix.runner }}
|
||||
timeout-minutes: 60
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix: ${{ fromJson(needs.preflight.outputs.checks_node_extensions_matrix) }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
shell: bash
|
||||
env:
|
||||
CHECKOUT_REPO: ${{ github.repository }}
|
||||
CHECKOUT_SHA: ${{ needs.preflight.outputs.checkout_revision }}
|
||||
CHECKOUT_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
workdir="$GITHUB_WORKSPACE"
|
||||
auth_header="$(printf 'x-access-token:%s' "$CHECKOUT_TOKEN" | base64 | tr -d '\n')"
|
||||
|
||||
reset_checkout_dir() {
|
||||
mkdir -p "$workdir"
|
||||
find "$workdir" -mindepth 1 -maxdepth 1 -exec rm -rf {} +
|
||||
}
|
||||
|
||||
checkout_attempt() {
|
||||
local attempt="$1"
|
||||
|
||||
reset_checkout_dir
|
||||
git init "$workdir" >/dev/null
|
||||
git config --global --add safe.directory "$workdir"
|
||||
git -C "$workdir" remote add origin "https://github.com/${CHECKOUT_REPO}"
|
||||
git -C "$workdir" config gc.auto 0
|
||||
|
||||
timeout --signal=TERM 30s git -C "$workdir" \
|
||||
-c protocol.version=2 \
|
||||
-c "http.https://github.com/.extraheader=AUTHORIZATION: basic ${auth_header}" \
|
||||
fetch --no-tags --prune --no-recurse-submodules --depth=1 origin \
|
||||
"+${CHECKOUT_SHA}:refs/remotes/origin/ci-target" || return 1
|
||||
|
||||
git -C "$workdir" checkout --force --detach "$CHECKOUT_SHA" || return 1
|
||||
test -f "$workdir/.github/actions/setup-node-env/action.yml" || return 1
|
||||
echo "checkout attempt ${attempt}/5 succeeded"
|
||||
}
|
||||
|
||||
for attempt in 1 2 3 4 5; do
|
||||
if checkout_attempt "$attempt"; then
|
||||
exit 0
|
||||
fi
|
||||
echo "checkout attempt ${attempt}/5 failed"
|
||||
sleep $((attempt * 5))
|
||||
done
|
||||
|
||||
echo "checkout failed after 5 attempts" >&2
|
||||
exit 1
|
||||
|
||||
- name: Setup Node environment
|
||||
uses: ./.github/actions/setup-node-env
|
||||
with:
|
||||
install-bun: "false"
|
||||
|
||||
- name: Run extension shard
|
||||
env:
|
||||
NODE_OPTIONS: --max-old-space-size=6144
|
||||
OPENCLAW_EXTENSION_BATCH_PARALLEL: 2
|
||||
OPENCLAW_VITEST_MAX_WORKERS: 1
|
||||
OPENCLAW_EXTENSION_BATCH: ${{ matrix.extensions_csv }}
|
||||
run: pnpm test:extensions:batch -- "$OPENCLAW_EXTENSION_BATCH"
|
||||
|
||||
checks-node-extensions:
|
||||
permissions:
|
||||
contents: read
|
||||
name: checks-node-extensions
|
||||
needs: [preflight, checks-node-extensions-shard]
|
||||
if: ${{ !cancelled() && always() && needs.preflight.outputs.run_checks_node_extensions == 'true' }}
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- name: Verify extension shards
|
||||
env:
|
||||
SHARD_RESULT: ${{ needs.checks-node-extensions-shard.result }}
|
||||
run: |
|
||||
if [ "$SHARD_RESULT" != "success" ]; then
|
||||
echo "Extension shard checks failed: $SHARD_RESULT" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
checks:
|
||||
permissions:
|
||||
contents: read
|
||||
@@ -1697,91 +1512,6 @@ jobs:
|
||||
exit 1
|
||||
fi
|
||||
|
||||
plugin-prerelease-static-shard:
|
||||
permissions:
|
||||
contents: read
|
||||
name: ${{ matrix.check_name }}
|
||||
needs: [preflight]
|
||||
if: needs.preflight.outputs.run_plugin_prerelease_suite == 'true'
|
||||
runs-on: blacksmith-8vcpu-ubuntu-2404
|
||||
timeout-minutes: 45
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix: ${{ fromJson(needs.preflight.outputs.plugin_prerelease_static_matrix) }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
ref: ${{ needs.preflight.outputs.checkout_revision }}
|
||||
fetch-depth: 1
|
||||
fetch-tags: false
|
||||
persist-credentials: false
|
||||
submodules: false
|
||||
|
||||
- name: Setup Node environment
|
||||
uses: ./.github/actions/setup-node-env
|
||||
with:
|
||||
install-bun: "false"
|
||||
|
||||
- name: Run plugin prerelease static shard
|
||||
env:
|
||||
PLUGIN_PRERELEASE_COMMAND: ${{ matrix.command }}
|
||||
PLUGIN_PRERELEASE_TASK: ${{ matrix.task }}
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
echo "Running ${PLUGIN_PRERELEASE_TASK}: ${PLUGIN_PRERELEASE_COMMAND}"
|
||||
bash -c "$PLUGIN_PRERELEASE_COMMAND"
|
||||
|
||||
plugin-prerelease-docker-suite:
|
||||
name: plugin-prerelease-docker-suite
|
||||
needs: [preflight]
|
||||
if: needs.preflight.outputs.run_plugin_prerelease_suite == 'true'
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
packages: write
|
||||
pull-requests: read
|
||||
uses: ./.github/workflows/openclaw-live-and-e2e-checks-reusable.yml
|
||||
with:
|
||||
ref: ${{ needs.preflight.outputs.plugin_prerelease_ref }}
|
||||
include_repo_e2e: false
|
||||
include_release_path_suites: false
|
||||
include_openwebui: false
|
||||
docker_lanes: ${{ needs.preflight.outputs.plugin_prerelease_docker_lanes }}
|
||||
include_live_suites: false
|
||||
live_models_only: false
|
||||
|
||||
plugin-prerelease-suite:
|
||||
permissions:
|
||||
contents: read
|
||||
name: plugin-prerelease-suite
|
||||
needs: [preflight, plugin-prerelease-static-shard, plugin-prerelease-docker-suite]
|
||||
if: ${{ !cancelled() && always() && needs.preflight.outputs.run_plugin_prerelease_suite == 'true' }}
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- name: Verify plugin prerelease suite
|
||||
env:
|
||||
DOCKER_RESULT: ${{ needs.plugin-prerelease-docker-suite.result }}
|
||||
STATIC_RESULT: ${{ needs.plugin-prerelease-static-shard.result }}
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
failed=0
|
||||
for result in \
|
||||
"plugin-prerelease-static=${STATIC_RESULT}" \
|
||||
"plugin-prerelease-docker=${DOCKER_RESULT}"
|
||||
do
|
||||
name="${result%%=*}"
|
||||
status="${result#*=}"
|
||||
if [ "$status" != "success" ]; then
|
||||
echo "::error::${name} ended with ${status}"
|
||||
failed=1
|
||||
fi
|
||||
done
|
||||
exit "$failed"
|
||||
|
||||
build-smoke:
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
121
.github/workflows/full-release-validation.yml
vendored
121
.github/workflows/full-release-validation.yml
vendored
@@ -43,6 +43,7 @@ on:
|
||||
options:
|
||||
- all
|
||||
- ci
|
||||
- plugin-prerelease
|
||||
- release-checks
|
||||
- install-smoke
|
||||
- cross-os
|
||||
@@ -131,11 +132,16 @@ jobs:
|
||||
echo "- Child workflow ref: \`${CHILD_WORKFLOW_REF}\`"
|
||||
echo "- Rerun group: \`${RERUN_GROUP}\`"
|
||||
if [[ "$RERUN_GROUP" == "all" || "$RERUN_GROUP" == "ci" ]]; then
|
||||
echo "- Normal CI: \`CI\` with \`target_ref=${TARGET_SHA}\` and release-only lanes enabled"
|
||||
echo "- Normal CI: \`CI\` with \`target_ref=${TARGET_SHA}\`"
|
||||
else
|
||||
echo "- Normal CI: skipped by rerun group"
|
||||
fi
|
||||
if [[ "$RERUN_GROUP" != "ci" && "$RERUN_GROUP" != "npm-telegram" ]]; then
|
||||
if [[ "$RERUN_GROUP" == "all" || "$RERUN_GROUP" == "plugin-prerelease" ]]; then
|
||||
echo "- Plugin prerelease: \`Plugin Prerelease\` with \`target_ref=${TARGET_SHA}\`"
|
||||
else
|
||||
echo "- Plugin prerelease: skipped by rerun group"
|
||||
fi
|
||||
if [[ "$RERUN_GROUP" == "all" || "$RERUN_GROUP" == "release-checks" || "$RERUN_GROUP" == "install-smoke" || "$RERUN_GROUP" == "cross-os" || "$RERUN_GROUP" == "live-e2e" || "$RERUN_GROUP" == "package" || "$RERUN_GROUP" == "qa" || "$RERUN_GROUP" == "qa-parity" || "$RERUN_GROUP" == "qa-live" ]]; then
|
||||
echo "- Release/live/Docker/package/QA: \`OpenClaw Release Checks\`"
|
||||
else
|
||||
echo "- Release/live/Docker/package/QA: skipped by rerun group"
|
||||
@@ -263,7 +269,105 @@ jobs:
|
||||
}
|
||||
|
||||
cancel_same_sha_push_ci
|
||||
dispatch_and_wait ci.yml -f target_ref="$TARGET_SHA" -f full_release_validation=true
|
||||
dispatch_and_wait ci.yml -f target_ref="$TARGET_SHA" -f include_android=true
|
||||
|
||||
plugin_prerelease:
|
||||
name: Run plugin prerelease validation
|
||||
needs: [resolve_target]
|
||||
if: contains(fromJSON('["all","plugin-prerelease"]'), inputs.rerun_group)
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 300
|
||||
outputs:
|
||||
run_id: ${{ steps.dispatch.outputs.run_id }}
|
||||
url: ${{ steps.dispatch.outputs.url }}
|
||||
conclusion: ${{ steps.dispatch.outputs.conclusion }}
|
||||
steps:
|
||||
- name: Dispatch and monitor plugin prerelease
|
||||
id: dispatch
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
TARGET_REF: ${{ inputs.ref }}
|
||||
TARGET_SHA: ${{ needs.resolve_target.outputs.sha }}
|
||||
CHILD_WORKFLOW_REF: ${{ github.ref_name }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
dispatch_and_wait() {
|
||||
local workflow="$1"
|
||||
shift
|
||||
|
||||
local before_json dispatch_output run_id status conclusion url
|
||||
before_json="$(gh run list --workflow "$workflow" --event workflow_dispatch --limit 100 --json databaseId --jq '[.[].databaseId]')"
|
||||
|
||||
dispatch_output="$(gh workflow run "$workflow" --ref "$CHILD_WORKFLOW_REF" "$@" 2>&1)"
|
||||
printf '%s\n' "$dispatch_output"
|
||||
run_id="$(
|
||||
printf '%s\n' "$dispatch_output" |
|
||||
sed -nE 's#.*actions/runs/([0-9]+).*#\1#p' |
|
||||
tail -n 1
|
||||
)"
|
||||
|
||||
if [[ -z "$run_id" ]]; then
|
||||
for _ in $(seq 1 60); do
|
||||
run_id="$(
|
||||
BEFORE_IDS="$before_json" gh run list --workflow "$workflow" --event workflow_dispatch --limit 50 --json databaseId,createdAt \
|
||||
--jq 'map(select(.databaseId as $id | (env.BEFORE_IDS | fromjson | index($id) | not))) | sort_by(.createdAt) | reverse | .[0].databaseId // empty'
|
||||
)"
|
||||
if [[ -n "$run_id" ]]; then
|
||||
break
|
||||
fi
|
||||
sleep 5
|
||||
done
|
||||
fi
|
||||
|
||||
if [[ -z "${run_id:-}" ]]; then
|
||||
echo "Could not find dispatched run for ${workflow}." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Dispatched ${workflow}: https://github.com/${GITHUB_REPOSITORY}/actions/runs/${run_id}"
|
||||
echo "run_id=${run_id}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
cleanup_child_run() {
|
||||
local exit_code=$?
|
||||
trap - EXIT INT TERM
|
||||
local child_status
|
||||
child_status="$(gh run view "$run_id" --json status --jq '.status' 2>/dev/null || true)"
|
||||
if [[ "$child_status" != "completed" ]]; then
|
||||
echo "Cancelling child ${workflow} run ${run_id} after parent exit (${exit_code})."
|
||||
gh run cancel "$run_id" || gh api -X POST "repos/${GITHUB_REPOSITORY}/actions/runs/${run_id}/force-cancel" || true
|
||||
fi
|
||||
return "$exit_code"
|
||||
}
|
||||
trap cleanup_child_run EXIT INT TERM
|
||||
|
||||
while true; do
|
||||
status="$(gh run view "$run_id" --json status --jq '.status')"
|
||||
if [[ "$status" == "completed" ]]; then
|
||||
break
|
||||
fi
|
||||
sleep 30
|
||||
done
|
||||
trap - EXIT INT TERM
|
||||
|
||||
conclusion="$(gh run view "$run_id" --json conclusion --jq '.conclusion')"
|
||||
url="$(gh run view "$run_id" --json url --jq '.url')"
|
||||
echo "${workflow} finished with ${conclusion}: ${url}"
|
||||
echo "url=${url}" >> "$GITHUB_OUTPUT"
|
||||
echo "conclusion=${conclusion}" >> "$GITHUB_OUTPUT"
|
||||
if [[ "$conclusion" != "success" ]]; then
|
||||
gh run view "$run_id" --json jobs --jq '.jobs[] | select(.conclusion != "success" and .conclusion != "skipped") | {name, conclusion, url}' || true
|
||||
fi
|
||||
}
|
||||
|
||||
{
|
||||
echo "### Plugin prerelease"
|
||||
echo
|
||||
echo "- Target ref: \`${TARGET_REF}\`"
|
||||
echo "- Target SHA: \`${TARGET_SHA}\`"
|
||||
} >> "$GITHUB_STEP_SUMMARY"
|
||||
|
||||
dispatch_and_wait plugin-prerelease.yml -f target_ref="$TARGET_SHA" -f expected_sha="$TARGET_SHA"
|
||||
|
||||
release_checks:
|
||||
name: Run release/live/Docker/QA validation
|
||||
@@ -467,7 +571,7 @@ jobs:
|
||||
|
||||
summary:
|
||||
name: Verify full validation
|
||||
needs: [normal_ci, release_checks, npm_telegram]
|
||||
needs: [normal_ci, plugin_prerelease, release_checks, npm_telegram]
|
||||
if: always()
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 5
|
||||
@@ -532,9 +636,11 @@ jobs:
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
NORMAL_CI_RUN_ID: ${{ needs.normal_ci.outputs.run_id }}
|
||||
PLUGIN_PRERELEASE_RUN_ID: ${{ needs.plugin_prerelease.outputs.run_id }}
|
||||
RELEASE_CHECKS_RUN_ID: ${{ needs.release_checks.outputs.run_id }}
|
||||
NPM_TELEGRAM_RUN_ID: ${{ needs.npm_telegram.outputs.run_id }}
|
||||
NORMAL_CI_RESULT: ${{ needs.normal_ci.result }}
|
||||
PLUGIN_PRERELEASE_RESULT: ${{ needs.plugin_prerelease.result }}
|
||||
RELEASE_CHECKS_RESULT: ${{ needs.release_checks.result }}
|
||||
NPM_TELEGRAM_RESULT: ${{ needs.npm_telegram.result }}
|
||||
run: |
|
||||
@@ -604,6 +710,12 @@ jobs:
|
||||
check_child "normal_ci" "$NORMAL_CI_RUN_ID" 1 || failed=1
|
||||
fi
|
||||
|
||||
if [[ "$PLUGIN_PRERELEASE_RESULT" == "skipped" && -z "${PLUGIN_PRERELEASE_RUN_ID// }" ]]; then
|
||||
check_child "plugin_prerelease" "" 0 || failed=1
|
||||
else
|
||||
check_child "plugin_prerelease" "$PLUGIN_PRERELEASE_RUN_ID" 1 || failed=1
|
||||
fi
|
||||
|
||||
if [[ "$RELEASE_CHECKS_RESULT" == "skipped" && -z "${RELEASE_CHECKS_RUN_ID// }" ]]; then
|
||||
check_child "release_checks" "" 0 || failed=1
|
||||
else
|
||||
@@ -617,6 +729,7 @@ jobs:
|
||||
fi
|
||||
|
||||
summarize_child_timing "normal_ci" "$NORMAL_CI_RUN_ID"
|
||||
summarize_child_timing "plugin_prerelease" "$PLUGIN_PRERELEASE_RUN_ID"
|
||||
summarize_child_timing "release_checks" "$RELEASE_CHECKS_RUN_ID"
|
||||
summarize_child_timing "npm_telegram" "$NPM_TELEGRAM_RUN_ID"
|
||||
|
||||
|
||||
406
.github/workflows/plugin-prerelease.yml
vendored
Normal file
406
.github/workflows/plugin-prerelease.yml
vendored
Normal file
@@ -0,0 +1,406 @@
|
||||
name: Plugin Prerelease
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
target_ref:
|
||||
description: Branch, tag, or full commit SHA to validate
|
||||
required: false
|
||||
default: main
|
||||
type: string
|
||||
expected_sha:
|
||||
description: Optional full commit SHA that target_ref must resolve to
|
||||
required: false
|
||||
default: ""
|
||||
type: string
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: plugin-prerelease-${{ inputs.target_ref }}
|
||||
cancel-in-progress: ${{ inputs.target_ref == 'main' }}
|
||||
|
||||
env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
|
||||
|
||||
jobs:
|
||||
preflight:
|
||||
name: Build plugin prerelease plan
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 15
|
||||
outputs:
|
||||
checkout_revision: ${{ steps.manifest.outputs.checkout_revision }}
|
||||
run_plugin_prerelease_suite: ${{ steps.manifest.outputs.run_plugin_prerelease_suite }}
|
||||
run_plugin_prerelease_static: ${{ steps.manifest.outputs.run_plugin_prerelease_static }}
|
||||
plugin_prerelease_static_matrix: ${{ steps.manifest.outputs.plugin_prerelease_static_matrix }}
|
||||
run_plugin_prerelease_node: ${{ steps.manifest.outputs.run_plugin_prerelease_node }}
|
||||
plugin_prerelease_node_matrix: ${{ steps.manifest.outputs.plugin_prerelease_node_matrix }}
|
||||
run_plugin_prerelease_extensions: ${{ steps.manifest.outputs.run_plugin_prerelease_extensions }}
|
||||
plugin_prerelease_extension_matrix: ${{ steps.manifest.outputs.plugin_prerelease_extension_matrix }}
|
||||
run_plugin_prerelease_docker: ${{ steps.manifest.outputs.run_plugin_prerelease_docker }}
|
||||
plugin_prerelease_docker_lanes: ${{ steps.manifest.outputs.plugin_prerelease_docker_lanes }}
|
||||
steps:
|
||||
- name: Checkout target
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
ref: ${{ inputs.target_ref }}
|
||||
fetch-depth: 1
|
||||
fetch-tags: false
|
||||
persist-credentials: false
|
||||
submodules: false
|
||||
|
||||
- name: Build plugin prerelease manifest
|
||||
id: manifest
|
||||
env:
|
||||
EXPECTED_SHA: ${{ inputs.expected_sha }}
|
||||
run: |
|
||||
node --input-type=module <<'EOF'
|
||||
import { appendFileSync } from "node:fs";
|
||||
import { execFileSync } from "node:child_process";
|
||||
|
||||
const createMatrix = (include) => ({ include });
|
||||
const outputPath = process.env.GITHUB_OUTPUT;
|
||||
const checkoutRevision = execFileSync("git", ["rev-parse", "HEAD"], {
|
||||
encoding: "utf8",
|
||||
}).trim();
|
||||
const expectedSha = (process.env.EXPECTED_SHA ?? "").trim();
|
||||
if (expectedSha && expectedSha !== checkoutRevision) {
|
||||
console.error(
|
||||
`target_ref resolved to ${checkoutRevision}, expected ${expectedSha}`,
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
let pluginPrereleasePlan = { staticChecks: [], dockerLanes: [] };
|
||||
let extensionShards = [];
|
||||
let nodeShards = [];
|
||||
|
||||
try {
|
||||
const { assertPluginPrereleaseTestPlanComplete } = await import(
|
||||
"./scripts/lib/plugin-prerelease-test-plan.mjs"
|
||||
);
|
||||
pluginPrereleasePlan = assertPluginPrereleaseTestPlanComplete();
|
||||
} catch (error) {
|
||||
const errorCode =
|
||||
error && typeof error === "object" && "code" in error ? error.code : "";
|
||||
const moduleUrl =
|
||||
error && typeof error === "object" && "url" in error ? String(error.url) : "";
|
||||
if (
|
||||
errorCode === "ERR_MODULE_NOT_FOUND" &&
|
||||
moduleUrl.endsWith("/scripts/lib/plugin-prerelease-test-plan.mjs")
|
||||
) {
|
||||
console.warn(
|
||||
"Plugin prerelease plan unavailable in target ref; skipping static and Docker plugin prerelease lanes.",
|
||||
);
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
const { createExtensionTestShards, DEFAULT_EXTENSION_TEST_SHARD_COUNT } = await import(
|
||||
"./scripts/lib/extension-test-plan.mjs"
|
||||
);
|
||||
extensionShards = createExtensionTestShards({
|
||||
shardCount: DEFAULT_EXTENSION_TEST_SHARD_COUNT,
|
||||
}).map((shard) => ({
|
||||
check_name: shard.checkName,
|
||||
extensions_csv: shard.extensionIds.join(","),
|
||||
runner: [0, 1, 2, 3].includes(shard.index)
|
||||
? "blacksmith-8vcpu-ubuntu-2404"
|
||||
: "blacksmith-4vcpu-ubuntu-2404",
|
||||
shard_index: shard.index + 1,
|
||||
task: "extensions-batch",
|
||||
}));
|
||||
} catch (error) {
|
||||
const errorCode =
|
||||
error && typeof error === "object" && "code" in error ? error.code : "";
|
||||
const moduleUrl =
|
||||
error && typeof error === "object" && "url" in error ? String(error.url) : "";
|
||||
if (
|
||||
errorCode === "ERR_MODULE_NOT_FOUND" &&
|
||||
moduleUrl.endsWith("/scripts/lib/extension-test-plan.mjs")
|
||||
) {
|
||||
console.warn(
|
||||
"Extension test plan unavailable in target ref; skipping extension prerelease shards.",
|
||||
);
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
const { createNodeTestShards } = await import("./scripts/lib/ci-node-test-plan.mjs");
|
||||
nodeShards = createNodeTestShards({
|
||||
includeReleaseOnlyPluginShards: true,
|
||||
})
|
||||
.filter((shard) => shard.shardName === "agentic-plugins")
|
||||
.map((shard) => ({
|
||||
check_name: shard.checkName,
|
||||
runtime: "node",
|
||||
task: "test-shard",
|
||||
shard_name: shard.shardName,
|
||||
configs: shard.configs,
|
||||
includePatterns: shard.includePatterns,
|
||||
runner: shard.runner,
|
||||
}));
|
||||
} catch (error) {
|
||||
const errorCode =
|
||||
error && typeof error === "object" && "code" in error ? error.code : "";
|
||||
const moduleUrl =
|
||||
error && typeof error === "object" && "url" in error ? String(error.url) : "";
|
||||
if (
|
||||
errorCode === "ERR_MODULE_NOT_FOUND" &&
|
||||
moduleUrl.endsWith("/scripts/lib/ci-node-test-plan.mjs")
|
||||
) {
|
||||
console.warn(
|
||||
"Node test plan unavailable in target ref; skipping release-only plugin Node shard.",
|
||||
);
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
const staticChecks = pluginPrereleasePlan.staticChecks.map((check) => ({
|
||||
check_name: check.checkName,
|
||||
command: check.command,
|
||||
task: check.check,
|
||||
}));
|
||||
const dockerLanes = pluginPrereleasePlan.dockerLanes;
|
||||
const runStatic = staticChecks.length > 0;
|
||||
const runNode = nodeShards.length > 0;
|
||||
const runExtensions = extensionShards.length > 0;
|
||||
const runDocker = dockerLanes.length > 0;
|
||||
const runSuite = runStatic || runNode || runExtensions || runDocker;
|
||||
|
||||
const manifest = {
|
||||
checkout_revision: checkoutRevision,
|
||||
run_plugin_prerelease_suite: runSuite,
|
||||
run_plugin_prerelease_static: runStatic,
|
||||
plugin_prerelease_static_matrix: createMatrix(staticChecks),
|
||||
run_plugin_prerelease_node: runNode,
|
||||
plugin_prerelease_node_matrix: createMatrix(nodeShards),
|
||||
run_plugin_prerelease_extensions: runExtensions,
|
||||
plugin_prerelease_extension_matrix: createMatrix(extensionShards),
|
||||
run_plugin_prerelease_docker: runDocker,
|
||||
plugin_prerelease_docker_lanes: dockerLanes.join(" "),
|
||||
};
|
||||
|
||||
for (const [key, value] of Object.entries(manifest)) {
|
||||
appendFileSync(
|
||||
outputPath,
|
||||
`${key}=${typeof value === "string" ? value : JSON.stringify(value)}\n`,
|
||||
"utf8",
|
||||
);
|
||||
}
|
||||
EOF
|
||||
|
||||
plugin-prerelease-static-shard:
|
||||
permissions:
|
||||
contents: read
|
||||
name: ${{ matrix.check_name }}
|
||||
needs: [preflight]
|
||||
if: needs.preflight.outputs.run_plugin_prerelease_static == 'true'
|
||||
runs-on: blacksmith-8vcpu-ubuntu-2404
|
||||
timeout-minutes: 45
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix: ${{ fromJson(needs.preflight.outputs.plugin_prerelease_static_matrix) }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
ref: ${{ needs.preflight.outputs.checkout_revision }}
|
||||
fetch-depth: 1
|
||||
fetch-tags: false
|
||||
persist-credentials: false
|
||||
submodules: false
|
||||
|
||||
- name: Setup Node environment
|
||||
uses: ./.github/actions/setup-node-env
|
||||
with:
|
||||
install-bun: "false"
|
||||
|
||||
- name: Run plugin prerelease static shard
|
||||
env:
|
||||
PLUGIN_PRERELEASE_COMMAND: ${{ matrix.command }}
|
||||
PLUGIN_PRERELEASE_TASK: ${{ matrix.task }}
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
echo "Running ${PLUGIN_PRERELEASE_TASK}: ${PLUGIN_PRERELEASE_COMMAND}"
|
||||
bash -c "$PLUGIN_PRERELEASE_COMMAND"
|
||||
|
||||
plugin-prerelease-node-shard:
|
||||
permissions:
|
||||
contents: read
|
||||
name: ${{ matrix.check_name }}
|
||||
needs: [preflight]
|
||||
if: needs.preflight.outputs.run_plugin_prerelease_node == 'true'
|
||||
runs-on: ${{ matrix.runner || 'ubuntu-24.04' }}
|
||||
timeout-minutes: 60
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix: ${{ fromJson(needs.preflight.outputs.plugin_prerelease_node_matrix) }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
ref: ${{ needs.preflight.outputs.checkout_revision }}
|
||||
fetch-depth: 1
|
||||
fetch-tags: false
|
||||
persist-credentials: false
|
||||
submodules: false
|
||||
|
||||
- name: Setup Node environment
|
||||
uses: ./.github/actions/setup-node-env
|
||||
with:
|
||||
install-bun: "false"
|
||||
|
||||
- name: Configure Node test resources
|
||||
run: echo "OPENCLAW_VITEST_MAX_WORKERS=2" >> "$GITHUB_ENV"
|
||||
|
||||
- name: Run release-only plugin Node shard
|
||||
env:
|
||||
NODE_OPTIONS: --max-old-space-size=6144
|
||||
OPENCLAW_NODE_TEST_CONFIGS_JSON: ${{ toJson(matrix.configs) }}
|
||||
OPENCLAW_NODE_TEST_INCLUDE_PATTERNS_JSON: ${{ toJson(matrix.includePatterns) }}
|
||||
OPENCLAW_VITEST_SHARD_NAME: ${{ matrix.shard_name }}
|
||||
OPENCLAW_TEST_PROJECTS_PARALLEL: "2"
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
node --input-type=module <<'EOF'
|
||||
import { spawnSync } from "node:child_process";
|
||||
import { writeFileSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
|
||||
const configs = JSON.parse(process.env.OPENCLAW_NODE_TEST_CONFIGS_JSON ?? "[]");
|
||||
if (!Array.isArray(configs) || configs.length === 0) {
|
||||
console.error("Missing node test shard configs");
|
||||
process.exit(1);
|
||||
}
|
||||
const includePatterns = JSON.parse(
|
||||
process.env.OPENCLAW_NODE_TEST_INCLUDE_PATTERNS_JSON ?? "null",
|
||||
);
|
||||
const childEnv = { ...process.env };
|
||||
if (Array.isArray(includePatterns) && includePatterns.length > 0) {
|
||||
const includeFile = join(
|
||||
process.env.RUNNER_TEMP ?? ".",
|
||||
`node-test-include-${process.env.GITHUB_JOB ?? "local"}-${Date.now()}.json`,
|
||||
);
|
||||
writeFileSync(includeFile, JSON.stringify(includePatterns), "utf8");
|
||||
childEnv.OPENCLAW_VITEST_INCLUDE_FILE = includeFile;
|
||||
}
|
||||
|
||||
const result = spawnSync(
|
||||
"pnpm",
|
||||
["exec", "node", "scripts/test-projects.mjs", ...configs],
|
||||
{
|
||||
env: childEnv,
|
||||
stdio: "inherit",
|
||||
},
|
||||
);
|
||||
process.exit(result.status ?? 1);
|
||||
EOF
|
||||
|
||||
plugin-prerelease-extension-shard:
|
||||
permissions:
|
||||
contents: read
|
||||
name: ${{ matrix.check_name }}
|
||||
needs: [preflight]
|
||||
if: needs.preflight.outputs.run_plugin_prerelease_extensions == 'true'
|
||||
runs-on: ${{ matrix.runner }}
|
||||
timeout-minutes: 60
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix: ${{ fromJson(needs.preflight.outputs.plugin_prerelease_extension_matrix) }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
ref: ${{ needs.preflight.outputs.checkout_revision }}
|
||||
fetch-depth: 1
|
||||
fetch-tags: false
|
||||
persist-credentials: false
|
||||
submodules: false
|
||||
|
||||
- name: Setup Node environment
|
||||
uses: ./.github/actions/setup-node-env
|
||||
with:
|
||||
install-bun: "false"
|
||||
|
||||
- name: Run extension shard
|
||||
env:
|
||||
NODE_OPTIONS: --max-old-space-size=6144
|
||||
OPENCLAW_EXTENSION_BATCH_PARALLEL: 2
|
||||
OPENCLAW_VITEST_MAX_WORKERS: 1
|
||||
OPENCLAW_EXTENSION_BATCH: ${{ matrix.extensions_csv }}
|
||||
run: pnpm test:extensions:batch -- "$OPENCLAW_EXTENSION_BATCH"
|
||||
|
||||
plugin-prerelease-docker-suite:
|
||||
name: plugin-prerelease-docker-suite
|
||||
needs: [preflight]
|
||||
if: needs.preflight.outputs.run_plugin_prerelease_docker == 'true'
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
packages: write
|
||||
pull-requests: read
|
||||
uses: ./.github/workflows/openclaw-live-and-e2e-checks-reusable.yml
|
||||
with:
|
||||
ref: ${{ needs.preflight.outputs.checkout_revision }}
|
||||
include_repo_e2e: false
|
||||
include_release_path_suites: false
|
||||
include_openwebui: false
|
||||
docker_lanes: ${{ needs.preflight.outputs.plugin_prerelease_docker_lanes }}
|
||||
include_live_suites: false
|
||||
live_models_only: false
|
||||
|
||||
plugin-prerelease-suite:
|
||||
permissions:
|
||||
contents: read
|
||||
name: plugin-prerelease-suite
|
||||
needs:
|
||||
- preflight
|
||||
- plugin-prerelease-static-shard
|
||||
- plugin-prerelease-node-shard
|
||||
- plugin-prerelease-extension-shard
|
||||
- plugin-prerelease-docker-suite
|
||||
if: ${{ !cancelled() && always() && needs.preflight.outputs.run_plugin_prerelease_suite == 'true' }}
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- name: Verify plugin prerelease suite
|
||||
env:
|
||||
RUN_STATIC: ${{ needs.preflight.outputs.run_plugin_prerelease_static }}
|
||||
RUN_NODE: ${{ needs.preflight.outputs.run_plugin_prerelease_node }}
|
||||
RUN_EXTENSIONS: ${{ needs.preflight.outputs.run_plugin_prerelease_extensions }}
|
||||
RUN_DOCKER: ${{ needs.preflight.outputs.run_plugin_prerelease_docker }}
|
||||
STATIC_RESULT: ${{ needs.plugin-prerelease-static-shard.result }}
|
||||
NODE_RESULT: ${{ needs.plugin-prerelease-node-shard.result }}
|
||||
EXTENSIONS_RESULT: ${{ needs.plugin-prerelease-extension-shard.result }}
|
||||
DOCKER_RESULT: ${{ needs.plugin-prerelease-docker-suite.result }}
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
failed=0
|
||||
check_required() {
|
||||
local name="$1"
|
||||
local required="$2"
|
||||
local status="$3"
|
||||
if [ "$required" != "true" ]; then
|
||||
return 0
|
||||
fi
|
||||
if [ "$status" != "success" ]; then
|
||||
echo "::error::${name} ended with ${status}"
|
||||
failed=1
|
||||
fi
|
||||
}
|
||||
|
||||
check_required "plugin-prerelease-static" "$RUN_STATIC" "$STATIC_RESULT"
|
||||
check_required "plugin-prerelease-node" "$RUN_NODE" "$NODE_RESULT"
|
||||
check_required "plugin-prerelease-extensions" "$RUN_EXTENSIONS" "$EXTENSIONS_RESULT"
|
||||
check_required "plugin-prerelease-docker" "$RUN_DOCKER" "$DOCKER_RESULT"
|
||||
exit "$failed"
|
||||
Reference in New Issue
Block a user