mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-12 21:53:00 -06:00
fix(release): unblock deferred Telegram beta validation (#120630)
* fix(release): allow deferring package Telegram validation * fix(qa): mount taxonomy in package Telegram harness * fix(release): restrict Telegram deferral to beta
This commit is contained in:
@@ -18,6 +18,11 @@ on:
|
||||
required: false
|
||||
default: false
|
||||
type: boolean
|
||||
skip_package_telegram_e2e:
|
||||
description: Defer beta Package Acceptance Telegram E2E while preserving focused npm Telegram validation
|
||||
required: false
|
||||
default: false
|
||||
type: boolean
|
||||
provider:
|
||||
description: Provider lane for cross-OS onboarding and the end-to-end agent turn
|
||||
required: false
|
||||
@@ -175,6 +180,17 @@ jobs:
|
||||
--ref "$TARGET_REF" \
|
||||
--github-output "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Validate release inputs
|
||||
env:
|
||||
RELEASE_PROFILE: ${{ inputs.release_profile }}
|
||||
SKIP_PACKAGE_TELEGRAM_E2E: ${{ inputs.skip_package_telegram_e2e }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
if [[ "$SKIP_PACKAGE_TELEGRAM_E2E" == "true" && "$RELEASE_PROFILE" != "beta" ]]; then
|
||||
echo "skip_package_telegram_e2e is allowed only for release_profile=beta." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Summarize target
|
||||
env:
|
||||
TARGET_REF: ${{ inputs.ref }}
|
||||
@@ -188,6 +204,7 @@ jobs:
|
||||
RELEASE_PROFILE: ${{ inputs.release_profile }}
|
||||
RUN_RELEASE_SOAK: ${{ inputs.run_release_soak || inputs.release_profile == 'stable' || inputs.release_profile == 'full' }}
|
||||
FAIL_FAST: ${{ inputs.fail_fast }}
|
||||
SKIP_PACKAGE_TELEGRAM_E2E: ${{ inputs.skip_package_telegram_e2e }}
|
||||
ALLOW_UNRELEASED_CHANGELOG: ${{ inputs.allow_unreleased_changelog || (inputs.target_context_ref == '' && (inputs.ref == 'main' || inputs.ref == 'refs/heads/main')) }}
|
||||
RERUN_GROUP: ${{ inputs.rerun_group }}
|
||||
LIVE_SUITE_FILTER: ${{ inputs.live_suite_filter }}
|
||||
@@ -201,6 +218,7 @@ jobs:
|
||||
echo "- Child workflow ref: \`${CHILD_WORKFLOW_REF}\`"
|
||||
echo "- Release soak lanes: \`${RUN_RELEASE_SOAK}\`"
|
||||
echo "- Fail fast: \`${FAIL_FAST}\`"
|
||||
echo "- Package Acceptance Telegram E2E deferred: \`${SKIP_PACKAGE_TELEGRAM_E2E}\`"
|
||||
echo "- Allow Unreleased changelog packaging: \`${ALLOW_UNRELEASED_CHANGELOG}\`"
|
||||
echo "- Rerun group: \`${RERUN_GROUP}\`"
|
||||
if [[ -n "${LIVE_SUITE_FILTER// }" ]]; then
|
||||
@@ -239,7 +257,11 @@ jobs:
|
||||
elif [[ "$RERUN_GROUP" == "npm-telegram" ]]; then
|
||||
echo "- Package Telegram E2E: focused rerun requires \`release_package_spec\` or \`npm_telegram_package_spec\`"
|
||||
elif [[ "$RERUN_GROUP" == "all" || "$RERUN_GROUP" == "release-checks" || "$RERUN_GROUP" == "package" ]]; then
|
||||
echo "- Package Telegram E2E: OpenClaw Release Checks Package Acceptance"
|
||||
if [[ "$SKIP_PACKAGE_TELEGRAM_E2E" == "true" ]]; then
|
||||
echo "- Package Telegram E2E: deferred by \`skip_package_telegram_e2e\`"
|
||||
else
|
||||
echo "- Package Telegram E2E: OpenClaw Release Checks Package Acceptance"
|
||||
fi
|
||||
else
|
||||
echo "- Package Telegram E2E: skipped by rerun group"
|
||||
fi
|
||||
@@ -311,6 +333,7 @@ jobs:
|
||||
NPM_TELEGRAM_PACKAGE_SPEC: ${{ inputs.npm_telegram_package_spec }}
|
||||
NPM_TELEGRAM_PROVIDER_MODE: ${{ inputs.npm_telegram_provider_mode }}
|
||||
NPM_TELEGRAM_SCENARIO: ${{ inputs.npm_telegram_scenario }}
|
||||
SKIP_PACKAGE_TELEGRAM_E2E: ${{ inputs.skip_package_telegram_e2e }}
|
||||
ALLOW_UNRELEASED_CHANGELOG: ${{ inputs.allow_unreleased_changelog || (inputs.target_context_ref == '' && (inputs.ref == 'main' || inputs.ref == 'refs/heads/main')) }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
@@ -328,6 +351,7 @@ jobs:
|
||||
--arg npmTelegramPackageSpec "$NPM_TELEGRAM_PACKAGE_SPEC" \
|
||||
--arg npmTelegramProviderMode "$NPM_TELEGRAM_PROVIDER_MODE" \
|
||||
--arg npmTelegramScenario "$NPM_TELEGRAM_SCENARIO" \
|
||||
--arg skipPackageTelegramE2e "$SKIP_PACKAGE_TELEGRAM_E2E" \
|
||||
--arg allowUnreleasedChangelog "$ALLOW_UNRELEASED_CHANGELOG" \
|
||||
'{
|
||||
provider: $provider,
|
||||
@@ -341,6 +365,7 @@ jobs:
|
||||
npmTelegramPackageSpec: $npmTelegramPackageSpec,
|
||||
npmTelegramProviderMode: $npmTelegramProviderMode,
|
||||
npmTelegramScenario: $npmTelegramScenario,
|
||||
skipPackageTelegramE2e: $skipPackageTelegramE2e,
|
||||
allowUnreleasedChangelog: $allowUnreleasedChangelog
|
||||
}')"
|
||||
bash workflow/scripts/github/find-reusable-release-validation.sh \
|
||||
@@ -857,6 +882,7 @@ jobs:
|
||||
if [[ -n "${CODEX_PLUGIN_SPEC// }" ]]; then
|
||||
echo "- Codex plugin spec: \`${CODEX_PLUGIN_SPEC}\`"
|
||||
fi
|
||||
echo "- Package Telegram E2E deferred: \`${SKIP_PACKAGE_TELEGRAM_E2E}\`"
|
||||
} >> "$GITHUB_STEP_SUMMARY"
|
||||
child_rerun_group="$RERUN_GROUP"
|
||||
if [[ "$child_rerun_group" == "release-checks" ]]; then
|
||||
@@ -872,6 +898,7 @@ jobs:
|
||||
-f run_release_soak="$RUN_RELEASE_SOAK"
|
||||
-f fail_fast="$FAIL_FAST"
|
||||
-f allow_unreleased_changelog="$ALLOW_UNRELEASED_CHANGELOG"
|
||||
-f skip_package_telegram_e2e="$SKIP_PACKAGE_TELEGRAM_E2E"
|
||||
-f rerun_group="$child_rerun_group"
|
||||
)
|
||||
if [[ -n "${TARGET_CONTEXT_REF// }" ]]; then
|
||||
@@ -1011,6 +1038,7 @@ jobs:
|
||||
PACKAGE_ACCEPTANCE_PACKAGE_SPEC: ${{ inputs.package_acceptance_package_spec }}
|
||||
CODEX_PLUGIN_SPEC: ${{ inputs.codex_plugin_spec }}
|
||||
CANDIDATE_ARTIFACT_JSON: ${{ needs.prepare_release_candidate.outputs.candidate_artifact_json }}
|
||||
SKIP_PACKAGE_TELEGRAM_E2E: ${{ inputs.skip_package_telegram_e2e }}
|
||||
run: *full_release_child_dispatch
|
||||
|
||||
npm_telegram:
|
||||
@@ -1099,6 +1127,7 @@ jobs:
|
||||
RELEASE_PACKAGE_SPEC: ${{ inputs.release_package_spec }}
|
||||
NPM_TELEGRAM_PACKAGE_SPEC: ${{ inputs.npm_telegram_package_spec }}
|
||||
PACKAGE_ACCEPTANCE_PACKAGE_SPEC: ${{ inputs.package_acceptance_package_spec }}
|
||||
SKIP_PACKAGE_TELEGRAM_E2E: ${{ inputs.skip_package_telegram_e2e }}
|
||||
EVIDENCE_REUSE: ${{ needs.evidence_reuse.outputs.reuse }}
|
||||
EVIDENCE_ROOT_RUN_ID: ${{ needs.evidence_reuse.outputs.evidence_root_run_id }}
|
||||
EVIDENCE_RUN_URL: ${{ needs.evidence_reuse.outputs.evidence_run_url }}
|
||||
@@ -1374,6 +1403,7 @@ jobs:
|
||||
if [[ "$RERUN_GROUP" == "npm-telegram" || ( "$RERUN_GROUP" == "all" && ( -n "${NPM_TELEGRAM_PACKAGE_SPEC// }" || -n "${RELEASE_PACKAGE_SPEC// }" ) ) ]]; then
|
||||
npm_telegram_required=1
|
||||
fi
|
||||
echo "- Package Telegram E2E deferred: \`${SKIP_PACKAGE_TELEGRAM_E2E}\`" >> "$GITHUB_STEP_SUMMARY"
|
||||
if [[ -z "${RELEASE_PACKAGE_SPEC// }" && -z "${PACKAGE_ACCEPTANCE_PACKAGE_SPEC// }" ]]; then
|
||||
case "$RERUN_GROUP" in
|
||||
all|plugin-prerelease|release-checks|cross-os|live-e2e|package)
|
||||
@@ -1625,6 +1655,7 @@ jobs:
|
||||
NPM_TELEGRAM_PACKAGE_SPEC: ${{ inputs.npm_telegram_package_spec }}
|
||||
NPM_TELEGRAM_PROVIDER_MODE: ${{ inputs.npm_telegram_provider_mode }}
|
||||
NPM_TELEGRAM_SCENARIO: ${{ inputs.npm_telegram_scenario }}
|
||||
SKIP_PACKAGE_TELEGRAM_E2E: ${{ inputs.skip_package_telegram_e2e }}
|
||||
ALLOW_UNRELEASED_CHANGELOG: ${{ inputs.allow_unreleased_changelog || (inputs.target_context_ref == '' && (inputs.ref == 'main' || inputs.ref == 'refs/heads/main')) }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
@@ -1700,6 +1731,7 @@ jobs:
|
||||
--arg npmTelegramPackageSpec "$NPM_TELEGRAM_PACKAGE_SPEC" \
|
||||
--arg npmTelegramProviderMode "$NPM_TELEGRAM_PROVIDER_MODE" \
|
||||
--arg npmTelegramScenario "$NPM_TELEGRAM_SCENARIO" \
|
||||
--arg skipPackageTelegramE2e "$SKIP_PACKAGE_TELEGRAM_E2E" \
|
||||
--arg allowUnreleasedChangelog "$ALLOW_UNRELEASED_CHANGELOG" \
|
||||
'{
|
||||
version: 3,
|
||||
@@ -1727,6 +1759,7 @@ jobs:
|
||||
npmTelegramPackageSpec: $npmTelegramPackageSpec,
|
||||
npmTelegramProviderMode: $npmTelegramProviderMode,
|
||||
npmTelegramScenario: $npmTelegramScenario,
|
||||
skipPackageTelegramE2e: $skipPackageTelegramE2e,
|
||||
allowUnreleasedChangelog: $allowUnreleasedChangelog
|
||||
},
|
||||
controls: {
|
||||
|
||||
@@ -61,6 +61,11 @@ on:
|
||||
required: false
|
||||
default: false
|
||||
type: boolean
|
||||
skip_package_telegram_e2e:
|
||||
description: Defer beta Package Acceptance Telegram E2E
|
||||
required: false
|
||||
default: false
|
||||
type: boolean
|
||||
allow_frozen_target_scenario_omissions:
|
||||
description: Allow trusted compatibility filtering for a canonical frozen release target
|
||||
required: false
|
||||
@@ -141,6 +146,7 @@ jobs:
|
||||
fail_fast: ${{ steps.inputs.outputs.fail_fast }}
|
||||
run_maturity_scorecard: ${{ steps.inputs.outputs.run_maturity_scorecard }}
|
||||
allow_unreleased_changelog: ${{ steps.inputs.outputs.allow_unreleased_changelog }}
|
||||
skip_package_telegram_e2e: ${{ steps.inputs.outputs.skip_package_telegram_e2e }}
|
||||
rerun_group: ${{ steps.inputs.outputs.rerun_group }}
|
||||
live_suite_filter: ${{ steps.inputs.outputs.live_suite_filter }}
|
||||
repo_live_suite_filter: ${{ steps.inputs.outputs.repo_live_suite_filter }}
|
||||
@@ -324,6 +330,7 @@ jobs:
|
||||
RELEASE_FAIL_FAST_INPUT: ${{ inputs.fail_fast }}
|
||||
RELEASE_RUN_MATURITY_SCORECARD_INPUT: ${{ inputs.run_maturity_scorecard }}
|
||||
RELEASE_ALLOW_UNRELEASED_CHANGELOG_INPUT: ${{ inputs.allow_unreleased_changelog }}
|
||||
RELEASE_SKIP_PACKAGE_TELEGRAM_E2E_INPUT: ${{ inputs.skip_package_telegram_e2e }}
|
||||
RELEASE_RERUN_GROUP_INPUT: ${{ inputs.rerun_group }}
|
||||
RELEASE_LIVE_SUITE_FILTER_INPUT: ${{ inputs.live_suite_filter }}
|
||||
RELEASE_CROSS_OS_SUITE_FILTER_INPUT: ${{ inputs.cross_os_suite_filter }}
|
||||
@@ -408,6 +415,16 @@ jobs:
|
||||
else
|
||||
allow_unreleased_changelog=false
|
||||
fi
|
||||
skip_package_telegram_e2e="$(printf '%s' "$RELEASE_SKIP_PACKAGE_TELEGRAM_E2E_INPUT" | tr '[:upper:]' '[:lower:]')"
|
||||
if [[ "$skip_package_telegram_e2e" != "true" && "$skip_package_telegram_e2e" != "1" && "$skip_package_telegram_e2e" != "yes" ]]; then
|
||||
skip_package_telegram_e2e=false
|
||||
else
|
||||
skip_package_telegram_e2e=true
|
||||
fi
|
||||
if [[ "$skip_package_telegram_e2e" == "true" && "$release_profile" != "beta" ]]; then
|
||||
echo "skip_package_telegram_e2e is allowed only for release_profile=beta." >&2
|
||||
exit 1
|
||||
fi
|
||||
codex_plugin_spec="$RELEASE_CODEX_PLUGIN_SPEC_INPUT"
|
||||
if [[ -z "${codex_plugin_spec// }" && "$RELEASE_PACKAGE_SPEC_INPUT" =~ ^openclaw@(.+)$ ]]; then
|
||||
codex_plugin_spec="npm:@openclaw/codex@${BASH_REMATCH[1]}"
|
||||
@@ -528,6 +545,7 @@ jobs:
|
||||
printf 'fail_fast=%s\n' "$fail_fast"
|
||||
printf 'run_maturity_scorecard=%s\n' "$run_maturity_scorecard"
|
||||
printf 'allow_unreleased_changelog=%s\n' "$allow_unreleased_changelog"
|
||||
printf 'skip_package_telegram_e2e=%s\n' "$skip_package_telegram_e2e"
|
||||
printf 'rerun_group=%s\n' "$RELEASE_RERUN_GROUP_INPUT"
|
||||
printf 'live_suite_filter=%s\n' "$RELEASE_LIVE_SUITE_FILTER_INPUT"
|
||||
printf 'repo_live_suite_filter=%s\n' "$repo_live_suite_filter"
|
||||
@@ -556,6 +574,7 @@ jobs:
|
||||
RUN_RELEASE_SOAK: ${{ steps.inputs.outputs.run_release_soak }}
|
||||
FAIL_FAST: ${{ steps.inputs.outputs.fail_fast }}
|
||||
RUN_MATURITY_SCORECARD: ${{ steps.inputs.outputs.run_maturity_scorecard }}
|
||||
SKIP_PACKAGE_TELEGRAM_E2E: ${{ steps.inputs.outputs.skip_package_telegram_e2e }}
|
||||
ALLOW_UNRELEASED_CHANGELOG: ${{ steps.inputs.outputs.allow_unreleased_changelog }}
|
||||
RELEASE_RERUN_GROUP: ${{ inputs.rerun_group }}
|
||||
RELEASE_LIVE_SUITE_FILTER: ${{ inputs.live_suite_filter }}
|
||||
@@ -576,6 +595,7 @@ jobs:
|
||||
echo "- Release soak lanes: \`${RUN_RELEASE_SOAK}\`"
|
||||
echo "- Matrix QA fail fast: \`${FAIL_FAST}\`"
|
||||
echo "- Maturity scorecard docs: \`${RUN_MATURITY_SCORECARD}\`"
|
||||
echo "- Package Acceptance Telegram E2E deferred: \`${SKIP_PACKAGE_TELEGRAM_E2E}\`"
|
||||
echo "- Allow Unreleased changelog packaging: \`${ALLOW_UNRELEASED_CHANGELOG}\`"
|
||||
echo "- Rerun group: \`${RELEASE_RERUN_GROUP}\`"
|
||||
if [[ -n "${RELEASE_LIVE_SUITE_FILTER// }" ]]; then
|
||||
@@ -1117,7 +1137,7 @@ jobs:
|
||||
docker_lanes: release-typed-onboarding doctor-switch update-channel-switch skill-install update-corrupt-plugin upgrade-survivor published-upgrade-survivor root-managed-vps-upgrade update-restart-auth plugins-offline plugin-update plugin-binding-command-escape
|
||||
published_upgrade_survivor_baselines: ${{ needs.resolve_target.outputs.run_release_soak == 'true' && 'last-stable-4 2026.4.23 2026.5.2 2026.4.15' || '' }}
|
||||
published_upgrade_survivor_scenarios: ${{ needs.resolve_target.outputs.run_release_soak == 'true' && 'reported-issues' || '' }}
|
||||
telegram_mode: mock-openai
|
||||
telegram_mode: ${{ needs.resolve_target.outputs.skip_package_telegram_e2e == 'true' && 'none' || 'mock-openai' }}
|
||||
telegram_advisory: ${{ needs.resolve_target.outputs.release_profile == 'beta' }}
|
||||
shared_image_artifact_namespace: release-package
|
||||
candidate_artifact_json: ${{ inputs.candidate_artifact_json }}
|
||||
|
||||
@@ -89,6 +89,11 @@ Codex `final`, reads randomized workspace inputs, writes their exact artifact,
|
||||
and sends explicit completion. This catches the v2026.7.1 regression where an
|
||||
ordinary progress send terminated the turn.
|
||||
|
||||
Use `-f skip_package_telegram_e2e=true` only when the release owner explicitly
|
||||
defers the Package Acceptance Telegram E2E to a follow-up beta. The input is
|
||||
rejected for `stable` and `full`, recorded in validation evidence, and does not disable the focused
|
||||
`rerun_group=npm-telegram` workflow.
|
||||
|
||||
## Top-level stages
|
||||
|
||||
For `rerun_group=all`, a `Check for reusable validation evidence` job runs
|
||||
|
||||
@@ -417,6 +417,7 @@ run_logged_print_heartbeat "npm-telegram-live-suite" 60 docker_e2e_run_with_harn
|
||||
-v "$ROOT_DIR/dist:/app/.openclaw-qa-harness-dist:ro" \
|
||||
-v "$ROOT_DIR/extensions/qa-lab:/app/extensions/qa-lab:ro" \
|
||||
-v "$ROOT_DIR/qa/scenarios:/app/qa/scenarios:ro" \
|
||||
-v "$ROOT_DIR/taxonomy.yaml:/app/taxonomy.yaml:ro" \
|
||||
-v "$npm_prefix_host:/npm-global" \
|
||||
-i "$IMAGE_NAME" bash -s <<'EOF'
|
||||
set -euo pipefail
|
||||
|
||||
@@ -29,6 +29,7 @@ const DEFAULT_INPUTS = {
|
||||
npmTelegramPackageSpec: "",
|
||||
npmTelegramProviderMode: "mock-openai",
|
||||
npmTelegramScenario: "",
|
||||
skipPackageTelegramE2e: "false",
|
||||
allowUnreleasedChangelog: "false",
|
||||
};
|
||||
|
||||
@@ -906,6 +907,14 @@ describe("scripts/github/find-reusable-release-validation.sh", () => {
|
||||
},
|
||||
resolverOptions: {},
|
||||
},
|
||||
{
|
||||
expected: "validation inputs differ",
|
||||
label: "different package Telegram deferral",
|
||||
recordOptions: {
|
||||
validationInputs: { ...DEFAULT_INPUTS, skipPackageTelegramE2e: "true" },
|
||||
},
|
||||
resolverOptions: {},
|
||||
},
|
||||
{
|
||||
expected: "validation inputs differ",
|
||||
label: "different unreleased changelog policy",
|
||||
|
||||
@@ -228,6 +228,13 @@ describe("package Telegram live Docker E2E", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("mounts the QA taxonomy without exposing the repository root", () => {
|
||||
const script = readFileSync(DOCKER_SCRIPT_PATH, "utf8");
|
||||
|
||||
expect(script).toContain('-v "$ROOT_DIR/taxonomy.yaml:/app/taxonomy.yaml:ro"');
|
||||
expect(script).not.toContain('-v "$ROOT_DIR:/app');
|
||||
});
|
||||
|
||||
it("mounts configured output paths before entering the container", () => {
|
||||
const script = readFileSync(DOCKER_SCRIPT_PATH, "utf8");
|
||||
const dockerEnvStart = script.indexOf("docker_env=(");
|
||||
|
||||
@@ -165,6 +165,9 @@ type Workflow = {
|
||||
workflow_call?: {
|
||||
inputs?: Record<string, unknown>;
|
||||
};
|
||||
workflow_dispatch?: {
|
||||
inputs?: Record<string, unknown>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -194,6 +197,78 @@ function workflowStep(job: WorkflowJob, stepName: string): WorkflowStep {
|
||||
return step;
|
||||
}
|
||||
|
||||
function runFullReleaseInputValidation(releaseProfile: string, skipTelegram: string) {
|
||||
const step = workflowStep(
|
||||
workflowJob(FULL_RELEASE_VALIDATION_WORKFLOW, "resolve_target"),
|
||||
"Validate release inputs",
|
||||
);
|
||||
return spawnSync("bash", ["-c", step.run ?? ""], {
|
||||
encoding: "utf8",
|
||||
env: {
|
||||
PATH: process.env.PATH,
|
||||
RELEASE_PROFILE: releaseProfile,
|
||||
SKIP_PACKAGE_TELEGRAM_E2E: skipTelegram,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function runReleaseChecksInputValidation(releaseProfile: string, skipTelegram: string) {
|
||||
const step = workflowStep(
|
||||
workflowJob(RELEASE_CHECKS_WORKFLOW, "resolve_target"),
|
||||
"Capture selected inputs",
|
||||
);
|
||||
const workdir = tempDirs.make("release-checks-input-validation-");
|
||||
const outputPath = resolve(workdir, "github-output");
|
||||
const stepEnv = Object.fromEntries(Object.keys(step.env ?? {}).map((name) => [name, ""]));
|
||||
const result = spawnSync("bash", ["-c", step.run ?? ""], {
|
||||
encoding: "utf8",
|
||||
env: {
|
||||
...stepEnv,
|
||||
CANDIDATE_ARTIFACT_JSON_INPUT: "",
|
||||
GITHUB_OUTPUT: outputPath,
|
||||
PATH: process.env.PATH,
|
||||
RELEASE_FAIL_FAST_INPUT: "false",
|
||||
RELEASE_MODE_INPUT: "both",
|
||||
RELEASE_PROFILE_INPUT: releaseProfile,
|
||||
RELEASE_PROVIDER_INPUT: "openai",
|
||||
RELEASE_QA_DISCORD_LIVE_CI_ENABLED: "false",
|
||||
RELEASE_QA_SLACK_LIVE_CI_ENABLED: "false",
|
||||
RELEASE_QA_WHATSAPP_LIVE_CI_ENABLED: "false",
|
||||
RELEASE_REF_INPUT: "main",
|
||||
RELEASE_RERUN_GROUP_INPUT: "all",
|
||||
RELEASE_RUN_MATURITY_SCORECARD_INPUT: "false",
|
||||
RELEASE_RUN_RELEASE_SOAK_INPUT: "false",
|
||||
RELEASE_SKIP_PACKAGE_TELEGRAM_E2E_INPUT: skipTelegram,
|
||||
},
|
||||
});
|
||||
return { outputPath, result };
|
||||
}
|
||||
|
||||
function runFullReleaseTargetSummary(rerunGroup: string, skipTelegram: string) {
|
||||
const step = workflowStep(
|
||||
workflowJob(FULL_RELEASE_VALIDATION_WORKFLOW, "resolve_target"),
|
||||
"Summarize target",
|
||||
);
|
||||
const workdir = tempDirs.make("full-release-target-summary-");
|
||||
const summaryPath = resolve(workdir, "github-summary");
|
||||
const stepEnv = Object.fromEntries(Object.keys(step.env ?? {}).map((name) => [name, ""]));
|
||||
const result = spawnSync("bash", ["-c", step.run ?? ""], {
|
||||
encoding: "utf8",
|
||||
env: {
|
||||
...stepEnv,
|
||||
GITHUB_STEP_SUMMARY: summaryPath,
|
||||
PATH: process.env.PATH,
|
||||
RELEASE_PROFILE: "beta",
|
||||
RERUN_GROUP: rerunGroup,
|
||||
SKIP_PACKAGE_TELEGRAM_E2E: skipTelegram,
|
||||
TARGET_REF: "main",
|
||||
TARGET_SHA: "a".repeat(40),
|
||||
},
|
||||
});
|
||||
const summary = result.status === 0 ? readFileSync(summaryPath, "utf8") : "";
|
||||
return { result, summary };
|
||||
}
|
||||
|
||||
function shellFunctionSource(source: string, functionName: string): string {
|
||||
const startMarker = `${functionName}() {`;
|
||||
const endMarker = "\n}\n";
|
||||
@@ -368,6 +443,7 @@ if (args[0] === "workflow" && args[1] === "run") {
|
||||
RERUN_GROUP: "all",
|
||||
RUN_RELEASE_SOAK: "false",
|
||||
SCENARIO: "",
|
||||
SKIP_PACKAGE_TELEGRAM_E2E: "false",
|
||||
TARGET_CONTEXT_REF: "",
|
||||
TARGET_REF: "main",
|
||||
TARGET_SHA: "b".repeat(40),
|
||||
@@ -3292,6 +3368,66 @@ describe("package artifact reuse", () => {
|
||||
expect(workflow).toContain("run_package_telegram_e2e:");
|
||||
});
|
||||
|
||||
it.each(["stable", "full"])(
|
||||
"rejects Package Acceptance Telegram deferral for direct %s release checks",
|
||||
(releaseProfile) => {
|
||||
const { result } = runReleaseChecksInputValidation(releaseProfile, "true");
|
||||
|
||||
expect(result.status).toBe(1);
|
||||
expect(result.stderr).toContain(
|
||||
"skip_package_telegram_e2e is allowed only for release_profile=beta.",
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
it.each(["stable", "full"])(
|
||||
"rejects Package Acceptance Telegram deferral for umbrella %s validation",
|
||||
(releaseProfile) => {
|
||||
const result = runFullReleaseInputValidation(releaseProfile, "true");
|
||||
|
||||
expect(result.status).toBe(1);
|
||||
expect(result.stderr).toContain(
|
||||
"skip_package_telegram_e2e is allowed only for release_profile=beta.",
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
it("allows Package Acceptance Telegram deferral only for beta validation", () => {
|
||||
const direct = runReleaseChecksInputValidation("beta", "true");
|
||||
const umbrella = runFullReleaseInputValidation("beta", "true");
|
||||
|
||||
expect(direct.result.status, direct.result.stderr).toBe(0);
|
||||
expect(readFileSync(direct.outputPath, "utf8")).toContain("skip_package_telegram_e2e=true");
|
||||
expect(umbrella.status, umbrella.stderr).toBe(0);
|
||||
});
|
||||
|
||||
it.each(["stable", "full"])(
|
||||
"preserves normal %s validation when Telegram deferral is false",
|
||||
(releaseProfile) => {
|
||||
const direct = runReleaseChecksInputValidation(releaseProfile, "false");
|
||||
const umbrella = runFullReleaseInputValidation(releaseProfile, "false");
|
||||
|
||||
expect(direct.result.status, direct.result.stderr).toBe(0);
|
||||
expect(readFileSync(direct.outputPath, "utf8")).toContain("skip_package_telegram_e2e=false");
|
||||
expect(umbrella.status, umbrella.stderr).toBe(0);
|
||||
},
|
||||
);
|
||||
|
||||
it("summarizes Telegram deferral only when Package Acceptance is scheduled", () => {
|
||||
const scheduled = runFullReleaseTargetSummary("release-checks", "true");
|
||||
const unrelated = runFullReleaseTargetSummary("ci", "true");
|
||||
|
||||
expect(scheduled.result.status, scheduled.result.stderr).toBe(0);
|
||||
expect(scheduled.summary).toContain(
|
||||
"Package Telegram E2E: deferred by `skip_package_telegram_e2e`",
|
||||
);
|
||||
expect(unrelated.result.status, unrelated.result.stderr).toBe(0);
|
||||
expect(unrelated.summary).toContain("Package Telegram E2E: skipped by rerun group");
|
||||
expect(unrelated.summary).not.toContain(
|
||||
"Package Telegram E2E: deferred by `skip_package_telegram_e2e`",
|
||||
);
|
||||
});
|
||||
|
||||
it("includes package acceptance in release checks", () => {
|
||||
const workflow = readFileSync(RELEASE_CHECKS_WORKFLOW, "utf8");
|
||||
const packageAcceptanceWorkflow = parse(readFileSync(PACKAGE_ACCEPTANCE_WORKFLOW, "utf8")) as {
|
||||
@@ -3303,6 +3439,10 @@ describe("package artifact reuse", () => {
|
||||
RELEASE_CHECKS_WORKFLOW,
|
||||
"package_acceptance_release_checks",
|
||||
);
|
||||
const releaseChecksTargetSummary = workflowStep(
|
||||
workflowJob(RELEASE_CHECKS_WORKFLOW, "resolve_target"),
|
||||
"Summarize validated ref",
|
||||
);
|
||||
const dockerAcceptanceJob = workflowJob(PACKAGE_ACCEPTANCE_WORKFLOW, "docker_acceptance");
|
||||
|
||||
expect(workflow).toContain("package_acceptance_release_checks:");
|
||||
@@ -3324,6 +3464,10 @@ describe("package artifact reuse", () => {
|
||||
package_version: "${{ needs.prepare_release_package.outputs.package_version }}",
|
||||
suite_profile: "custom",
|
||||
});
|
||||
expect(releaseChecksTargetSummary.env).toMatchObject({
|
||||
SKIP_PACKAGE_TELEGRAM_E2E: "${{ steps.inputs.outputs.skip_package_telegram_e2e }}",
|
||||
});
|
||||
expect(releaseChecksTargetSummary.run).toContain("Package Acceptance Telegram E2E deferred:");
|
||||
expect(dockerAcceptanceJob.with).toMatchObject({
|
||||
allow_frozen_target_scenario_omissions:
|
||||
"${{ inputs.allow_frozen_target_scenario_omissions || false }}",
|
||||
@@ -3381,7 +3525,16 @@ describe("package artifact reuse", () => {
|
||||
expect(workflow).toContain(
|
||||
"published_upgrade_survivor_scenarios: ${{ needs.resolve_target.outputs.run_release_soak == 'true' && 'reported-issues' || '' }}",
|
||||
);
|
||||
expect(workflow).toContain("telegram_mode: mock-openai");
|
||||
expect(readWorkflow(RELEASE_CHECKS_WORKFLOW).on?.workflow_dispatch?.inputs).toMatchObject({
|
||||
skip_package_telegram_e2e: {
|
||||
default: false,
|
||||
type: "boolean",
|
||||
},
|
||||
});
|
||||
expect(packageAcceptanceJob.with).toMatchObject({
|
||||
telegram_mode:
|
||||
"${{ needs.resolve_target.outputs.skip_package_telegram_e2e == 'true' && 'none' || 'mock-openai' }}",
|
||||
});
|
||||
expect(packageAcceptanceJob.with).toMatchObject({
|
||||
telegram_advisory: "${{ needs.resolve_target.outputs.release_profile == 'beta' }}",
|
||||
});
|
||||
@@ -4007,14 +4160,30 @@ describe("package artifact reuse", () => {
|
||||
|
||||
it("runs full release children from the trusted workflow ref", () => {
|
||||
const workflow = readFileSync(FULL_RELEASE_VALIDATION_WORKFLOW, "utf8");
|
||||
const workflowInputs = readWorkflow(FULL_RELEASE_VALIDATION_WORKFLOW).on?.workflow_dispatch
|
||||
?.inputs;
|
||||
const resolveTargetJob = workflowJob(FULL_RELEASE_VALIDATION_WORKFLOW, "resolve_target");
|
||||
const evidenceReuseJob = workflowJob(FULL_RELEASE_VALIDATION_WORKFLOW, "evidence_reuse");
|
||||
const releaseChecksJob = workflowJob(FULL_RELEASE_VALIDATION_WORKFLOW, "release_checks");
|
||||
const npmTelegramJob = workflowJob(FULL_RELEASE_VALIDATION_WORKFLOW, "npm_telegram");
|
||||
const performanceJob = workflowJob(FULL_RELEASE_VALIDATION_WORKFLOW, "performance");
|
||||
const summaryJob = workflowJob(FULL_RELEASE_VALIDATION_WORKFLOW, "summary");
|
||||
const targetSummaryStep = workflowStep(resolveTargetJob, "Summarize target");
|
||||
const evidenceReuseStep = workflowStep(evidenceReuseJob, "Find reusable validation evidence");
|
||||
const releaseChecksDispatchStep = workflowStep(
|
||||
releaseChecksJob,
|
||||
"Dispatch and monitor release checks",
|
||||
);
|
||||
const dispatchStep = workflowStep(npmTelegramJob, "Dispatch and monitor npm Telegram E2E");
|
||||
const verificationStep = workflowStep(summaryJob, "Verify child workflow results");
|
||||
const manifestStep = workflowStep(summaryJob, "Write release validation manifest");
|
||||
|
||||
expect(workflowInputs).toMatchObject({
|
||||
skip_package_telegram_e2e: {
|
||||
default: false,
|
||||
type: "boolean",
|
||||
},
|
||||
});
|
||||
expect(workflow).toContain("CHILD_WORKFLOW_REF: ${{ github.ref_name }}");
|
||||
expect(workflow).toContain('gh workflow run "$workflow" --ref "$CHILD_WORKFLOW_REF" "$@" 2>&1');
|
||||
expect(npmTelegramJob.name).toBe("Run package Telegram E2E");
|
||||
@@ -4035,13 +4204,28 @@ describe("package artifact reuse", () => {
|
||||
NPM_TELEGRAM_PACKAGE_SPEC: "${{ inputs.npm_telegram_package_spec }}",
|
||||
NPM_TELEGRAM_PROVIDER_MODE: "${{ inputs.npm_telegram_provider_mode }}",
|
||||
NPM_TELEGRAM_SCENARIO: "${{ inputs.npm_telegram_scenario }}",
|
||||
SKIP_PACKAGE_TELEGRAM_E2E: "${{ inputs.skip_package_telegram_e2e }}",
|
||||
});
|
||||
expectTextToIncludeAll(evidenceReuseStep.run, [
|
||||
"npmTelegramPackageSpec: $npmTelegramPackageSpec",
|
||||
"npmTelegramProviderMode: $npmTelegramProviderMode",
|
||||
"npmTelegramScenario: $npmTelegramScenario",
|
||||
"skipPackageTelegramE2e: $skipPackageTelegramE2e",
|
||||
"allowUnreleasedChangelog: $allowUnreleasedChangelog",
|
||||
]);
|
||||
expect(targetSummaryStep.env).toMatchObject({
|
||||
SKIP_PACKAGE_TELEGRAM_E2E: "${{ inputs.skip_package_telegram_e2e }}",
|
||||
});
|
||||
expectTextToIncludeAll(targetSummaryStep.run, [
|
||||
"Package Acceptance Telegram E2E deferred:",
|
||||
"Package Telegram E2E: deferred by \\`skip_package_telegram_e2e\\`",
|
||||
]);
|
||||
expect(releaseChecksDispatchStep.env).toMatchObject({
|
||||
SKIP_PACKAGE_TELEGRAM_E2E: "${{ inputs.skip_package_telegram_e2e }}",
|
||||
});
|
||||
expect(releaseChecksDispatchStep.run).toContain(
|
||||
'-f skip_package_telegram_e2e="$SKIP_PACKAGE_TELEGRAM_E2E"',
|
||||
);
|
||||
expect(dispatchStep.env).toEqual({
|
||||
CHILD_WORKFLOW_KIND: "npm-telegram",
|
||||
CHILD_WORKFLOW_REF: "${{ github.ref_name }}",
|
||||
@@ -4059,13 +4243,19 @@ describe("package artifact reuse", () => {
|
||||
NPM_TELEGRAM_PACKAGE_SPEC: "${{ inputs.npm_telegram_package_spec }}",
|
||||
NPM_TELEGRAM_PROVIDER_MODE: "${{ inputs.npm_telegram_provider_mode }}",
|
||||
NPM_TELEGRAM_SCENARIO: "${{ inputs.npm_telegram_scenario }}",
|
||||
SKIP_PACKAGE_TELEGRAM_E2E: "${{ inputs.skip_package_telegram_e2e }}",
|
||||
});
|
||||
expectTextToIncludeAll(manifestStep.run, [
|
||||
"npmTelegramPackageSpec: $npmTelegramPackageSpec",
|
||||
"npmTelegramProviderMode: $npmTelegramProviderMode",
|
||||
"npmTelegramScenario: $npmTelegramScenario",
|
||||
"skipPackageTelegramE2e: $skipPackageTelegramE2e",
|
||||
"allowUnreleasedChangelog: $allowUnreleasedChangelog",
|
||||
]);
|
||||
expect(verificationStep.env).toMatchObject({
|
||||
SKIP_PACKAGE_TELEGRAM_E2E: "${{ inputs.skip_package_telegram_e2e }}",
|
||||
});
|
||||
expect(verificationStep.run).toContain("Package Telegram E2E deferred:");
|
||||
expectTextToIncludeAll(dispatchStep.run, [
|
||||
'dispatch_id="full-release-validation-${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}-npm-telegram"',
|
||||
'dispatch_output="$(gh workflow run "$workflow" --ref "$CHILD_WORKFLOW_REF" "$@" 2>&1)"',
|
||||
@@ -4118,6 +4308,7 @@ describe("package artifact reuse", () => {
|
||||
|
||||
expectTextToIncludeAll(workflow, [
|
||||
"Published-package Telegram E2E:",
|
||||
"Package Telegram E2E: deferred by \\`skip_package_telegram_e2e\\`",
|
||||
"Package Telegram E2E: OpenClaw Release Checks Package Acceptance",
|
||||
"Package Telegram E2E: focused rerun requires \\`release_package_spec\\` or \\`npm_telegram_package_spec\\`",
|
||||
]);
|
||||
|
||||
@@ -247,6 +247,7 @@ function rawManifest({
|
||||
packageAcceptancePackageSpec: "",
|
||||
provider: "openai",
|
||||
releasePackageSpec: "",
|
||||
skipPackageTelegramE2e: "false",
|
||||
targetContextRef: "",
|
||||
},
|
||||
version,
|
||||
@@ -1316,6 +1317,7 @@ describe("release CI summary child correlation", () => {
|
||||
const raw = rawManifest({});
|
||||
raw.childRuns.npmTelegram = "505";
|
||||
raw.validationInputs.npmTelegramPackageSpec = "openclaw@beta";
|
||||
raw.validationInputs.skipPackageTelegramE2e = "true";
|
||||
const manifest = validateParentManifest(raw, {
|
||||
runAttempt: 2,
|
||||
runId: "29090000000",
|
||||
|
||||
Reference in New Issue
Block a user