mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-28 05:16:23 -06:00
fix(release): unblock beta validation workflows (#116708)
* fix(release): repair beta validation workflow state * fix(qa): dispatch yielded fanout runs without task tracking * fix(test): honor GPT-Live shard opt-in
This commit is contained in:
@@ -352,7 +352,7 @@ jobs:
|
||||
}
|
||||
attempt_started_at="$(jq -er '.run_started_at | fromdateiso8601' <<< "$attempt_json")"
|
||||
if [[ "$ARTIFACT_RUN_ID" == "$GITHUB_RUN_ID" ]]; then
|
||||
jq -e '(.status == "queued" or .status == "in_progress") and .conclusion == null' \
|
||||
jq -e '(.status == "pending" or .status == "queued" or .status == "in_progress") and .conclusion == null' \
|
||||
<<< "$attempt_json" >/dev/null || {
|
||||
echo "Current-run Package Telegram artifact is not from the active workflow attempt." >&2
|
||||
exit 1
|
||||
|
||||
@@ -1665,6 +1665,10 @@ jobs:
|
||||
expected_sha: ${{ needs.resolve_target.outputs.revision }}
|
||||
run_matrix: true
|
||||
fail_fast: ${{ fromJSON(needs.resolve_target.outputs.fail_fast) }}
|
||||
secrets:
|
||||
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
||||
OPENCLAW_QA_CONVEX_SITE_URL: ${{ secrets.OPENCLAW_QA_CONVEX_SITE_URL }}
|
||||
OPENCLAW_QA_CONVEX_SECRET_CI: ${{ secrets.OPENCLAW_QA_CONVEX_SECRET_CI }}
|
||||
|
||||
qa_live_buzz_release_checks:
|
||||
name: Run QA Lab live Buzz lane
|
||||
@@ -1679,6 +1683,10 @@ jobs:
|
||||
expected_sha: ${{ needs.resolve_target.outputs.revision }}
|
||||
run_buzz: true
|
||||
buzz_scenario: channel-canary,channel-mention-gating
|
||||
secrets:
|
||||
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
||||
OPENCLAW_QA_CONVEX_SITE_URL: ${{ secrets.OPENCLAW_QA_CONVEX_SITE_URL }}
|
||||
OPENCLAW_QA_CONVEX_SECRET_CI: ${{ secrets.OPENCLAW_QA_CONVEX_SECRET_CI }}
|
||||
|
||||
# The dispatched child owns Telegram evidence/status artifacts; this blocking job
|
||||
# carries its exact conclusion into the parent summary without copying secrets or artifacts.
|
||||
|
||||
@@ -58,6 +58,16 @@ on:
|
||||
required: false
|
||||
default: false
|
||||
type: boolean
|
||||
secrets:
|
||||
OPENAI_API_KEY:
|
||||
description: OpenAI API key used by live QA scenarios
|
||||
required: false
|
||||
OPENCLAW_QA_CONVEX_SITE_URL:
|
||||
description: Convex credential broker URL
|
||||
required: false
|
||||
OPENCLAW_QA_CONVEX_SECRET_CI:
|
||||
description: Convex CI credential
|
||||
required: false
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
ref:
|
||||
|
||||
@@ -79,6 +79,7 @@ describe("qa scenario catalog channel contracts", () => {
|
||||
|
||||
expect(flow).toContain('"call":"startAgentRun"');
|
||||
expect(flow).not.toContain('"call":"runAgentPrompt"');
|
||||
expect(flow).toContain('"taskTracking":false');
|
||||
expect(flow).toContain('"saveAs":"parentOutbound"');
|
||||
expect(flow).toContain("messages.slice(parentOutboundStartIndex)");
|
||||
expect(flow).not.toContain("waitForAgentHistoryReply");
|
||||
|
||||
@@ -105,6 +105,7 @@ flow:
|
||||
ref: sessionKey
|
||||
message:
|
||||
ref: prompt
|
||||
taskTracking: false
|
||||
timeoutMs:
|
||||
expr: liveTurnTimeoutMs(env, 30000)
|
||||
- call: waitForCondition
|
||||
|
||||
@@ -29,6 +29,11 @@ const OPTIONAL_LIVE_SHARD_FILE_ENVS = new Map([
|
||||
["src/agents/subagent-announce.live.test.ts", ["OPENCLAW_LIVE_SUBAGENT_E2E"]],
|
||||
["src/agents/tools/image-tool.ollama.live.test.ts", ["OPENCLAW_LIVE_OLLAMA_IMAGE"]],
|
||||
["src/agents/tools/image-tool.providers.live.test.ts", ["OPENCLAW_LIVE_IMAGE_TOOL_TEST"]],
|
||||
[
|
||||
"extensions/openai/realtime-quicksilver-gateway-bridge.live.test.ts",
|
||||
["OPENCLAW_LIVE_GPT_LIVE"],
|
||||
],
|
||||
["extensions/openai/realtime-quicksilver.live.test.ts", ["OPENCLAW_LIVE_GPT_LIVE"]],
|
||||
["src/skills/workshop/experience-review.live.test.ts", ["OPENCLAW_LIVE_SKILL_EXPERIENCE_REVIEW"]],
|
||||
["src/system-agent/rescue-channel.live.test.ts", ["OPENCLAW_LIVE_SYSTEM_AGENT_RESCUE_CHANNEL"]],
|
||||
["src/gateway/android-node.capabilities.live.test.ts", ["OPENCLAW_LIVE_ANDROID_NODE"]],
|
||||
|
||||
@@ -245,7 +245,7 @@ function runNpmTelegramInputValidation(overrides: Record<string, string>) {
|
||||
function runNpmTelegramArtifactValidation(params: {
|
||||
currentRunId: string;
|
||||
producerRunId: string;
|
||||
producerStatus: "completed" | "in_progress" | "queued";
|
||||
producerStatus: "completed" | "in_progress" | "pending" | "queued";
|
||||
producerConclusion: "success" | null;
|
||||
}) {
|
||||
const job = workflowJob(NPM_TELEGRAM_WORKFLOW, "run_package_telegram_e2e");
|
||||
@@ -2583,7 +2583,11 @@ describe("package artifact reuse", () => {
|
||||
const releaseJob = workflowJob(RELEASE_CHECKS_WORKFLOW, "qa_live_release_checks");
|
||||
|
||||
expect(releaseJob.uses).toBe("./.github/workflows/qa-live-transports-convex.yml");
|
||||
expect(releaseJob.secrets).toBeUndefined();
|
||||
expect(releaseJob.secrets).toEqual({
|
||||
OPENAI_API_KEY: "${{ secrets.OPENAI_API_KEY }}",
|
||||
OPENCLAW_QA_CONVEX_SECRET_CI: "${{ secrets.OPENCLAW_QA_CONVEX_SECRET_CI }}",
|
||||
OPENCLAW_QA_CONVEX_SITE_URL: "${{ secrets.OPENCLAW_QA_CONVEX_SITE_URL }}",
|
||||
});
|
||||
expect(releaseJob.permissions).toEqual({ contents: "read", "pull-requests": "read" });
|
||||
expect(releaseJob.if).toContain('contains(fromJSON(\'["all","qa","qa-live"]\')');
|
||||
expect(releaseJob.with).toMatchObject({
|
||||
@@ -2650,7 +2654,11 @@ describe("package artifact reuse", () => {
|
||||
const releaseJob = workflowJob(RELEASE_CHECKS_WORKFLOW, "qa_live_buzz_release_checks");
|
||||
|
||||
expect(releaseJob.uses).toBe("./.github/workflows/qa-live-transports-convex.yml");
|
||||
expect(releaseJob.secrets).toBeUndefined();
|
||||
expect(releaseJob.secrets).toEqual({
|
||||
OPENAI_API_KEY: "${{ secrets.OPENAI_API_KEY }}",
|
||||
OPENCLAW_QA_CONVEX_SECRET_CI: "${{ secrets.OPENCLAW_QA_CONVEX_SECRET_CI }}",
|
||||
OPENCLAW_QA_CONVEX_SITE_URL: "${{ secrets.OPENCLAW_QA_CONVEX_SITE_URL }}",
|
||||
});
|
||||
expect(releaseJob.permissions).toEqual({ contents: "read", "pull-requests": "read" });
|
||||
expect(releaseJob.if).toContain('contains(fromJSON(\'["all","qa","qa-live"]\')');
|
||||
expect(releaseJob.if).toContain("needs.resolve_target.outputs.qa_live_buzz_enabled == 'true'");
|
||||
@@ -3212,6 +3220,7 @@ describe("package artifact reuse", () => {
|
||||
'--arg digest "sha256:${ARTIFACT_DIGEST}"',
|
||||
"actions/runs/${ARTIFACT_RUN_ID}/attempts/${ARTIFACT_RUN_ATTEMPT}",
|
||||
'if [[ "$ARTIFACT_RUN_ID" == "$GITHUB_RUN_ID" ]]',
|
||||
'.status == "pending"',
|
||||
'.status == "queued" or .status == "in_progress"',
|
||||
".conclusion == null",
|
||||
"Package Telegram artifact predates the active producer run attempt.",
|
||||
@@ -3269,6 +3278,17 @@ describe("package artifact reuse", () => {
|
||||
expect(result.status, result.stderr).toBe(0);
|
||||
});
|
||||
|
||||
it("accepts active artifacts while GitHub reports the workflow as pending", () => {
|
||||
const result = runNpmTelegramArtifactValidation({
|
||||
currentRunId: "123",
|
||||
producerConclusion: null,
|
||||
producerRunId: "123",
|
||||
producerStatus: "pending",
|
||||
});
|
||||
|
||||
expect(result.status, result.stderr).toBe(0);
|
||||
});
|
||||
|
||||
it("rejects queued artifacts after GitHub assigns a conclusion", () => {
|
||||
const result = runNpmTelegramArtifactValidation({
|
||||
currentRunId: "123",
|
||||
|
||||
@@ -420,6 +420,40 @@ describe("scripts/test-live-shard", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("allows GPT-Live files to be skipped until their shared opt-in is enabled", () => {
|
||||
const quicksilverFiles = [
|
||||
"extensions/openai/realtime-quicksilver-gateway-bridge.live.test.ts",
|
||||
"extensions/openai/realtime-quicksilver.live.test.ts",
|
||||
];
|
||||
const payload = {
|
||||
numPassedTests: 1,
|
||||
numTotalTests: 3,
|
||||
testResults: [
|
||||
{
|
||||
name: path.join(process.cwd(), "extensions/openai/openai.live.test.ts"),
|
||||
assertionResults: [{ status: "passed" }],
|
||||
},
|
||||
...quicksilverFiles.map((file) => ({
|
||||
name: path.join(process.cwd(), file),
|
||||
assertionResults: [{ status: "skipped" }],
|
||||
})),
|
||||
],
|
||||
};
|
||||
const expectedFiles = ["extensions/openai/openai.live.test.ts", ...quicksilverFiles];
|
||||
|
||||
expect(validateLiveShardReportPayload(payload, expectedFiles, process.cwd(), {})).toEqual({
|
||||
ok: true,
|
||||
});
|
||||
expect(
|
||||
validateLiveShardReportPayload(payload, expectedFiles, process.cwd(), {
|
||||
OPENCLAW_LIVE_GPT_LIVE: "1",
|
||||
}),
|
||||
).toEqual({
|
||||
ok: false,
|
||||
reason: `Vitest report selected live test files had no passing assertions: ${quicksilverFiles.join(", ")}`,
|
||||
});
|
||||
});
|
||||
|
||||
it("does not count disabled opt-in sentinel assertions as live shard proof", () => {
|
||||
const payload = {
|
||||
numPassedTests: 1,
|
||||
|
||||
Reference in New Issue
Block a user