Compare commits
No commits in common. "main" and "runtime-0a5062166444" have entirely different histories.
main
...
runtime-0a
44
.github/workflows/validate-release-pr.yml
vendored
44
.github/workflows/validate-release-pr.yml
vendored
@ -1,44 +0,0 @@
|
||||
name: Validate Release PR
|
||||
|
||||
# release/* 分支的发布策略门禁:仅接受 hotfix/* 或带 cherry-pick/backport 标签的 PR。
|
||||
# 详见 iac_modules/docs/tldr-github-branch-model.md
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [opened, synchronize, reopened, labeled, unlabeled]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: read
|
||||
|
||||
jobs:
|
||||
validate-release-source:
|
||||
runs-on: ubuntu-latest
|
||||
if: startsWith(github.base_ref, 'release/')
|
||||
steps:
|
||||
- name: Check PR source branch
|
||||
run: |
|
||||
SRC="${{ github.head_ref }}"
|
||||
TGT="${{ github.base_ref }}"
|
||||
LABELS="${{ join(github.event.pull_request.labels.*.name, ',') }}"
|
||||
|
||||
echo "🔍 Validating PR into release branch"
|
||||
echo " source: $SRC"
|
||||
echo " target: $TGT"
|
||||
echo " labels: $LABELS"
|
||||
|
||||
if [[ "$SRC" =~ ^hotfix/ ]]; then
|
||||
echo "✅ Allowed: hotfix/* branch"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "$LABELS" =~ (^|,)(cherry-pick|backport)(,|$) ]]; then
|
||||
echo "✅ Allowed: cherry-pick/backport labeled PR"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "❌ Rejected."
|
||||
echo "release/* 仅接受:"
|
||||
echo " - 来自 hotfix/* 的 PR"
|
||||
echo " - 带 cherry-pick 或 backport 标签的 PR(已验证 feature 的 backport/cherry-pick)"
|
||||
echo "禁止从 main / develop / feature/* 直接合并到 release/*。"
|
||||
exit 1
|
||||
@ -132,49 +132,6 @@ func TestNormalizeOpenClawTaskGetUnknownArtifactEvidenceKeepsActiveRecordRunning
|
||||
}
|
||||
}
|
||||
|
||||
func TestExpectedArtifactDirectoriesDoNotBlockTerminalTaskState(t *testing.T) {
|
||||
params := map[string]any{"expectedArtifactDirs": []any{"reports/", "artifacts/"}}
|
||||
payload := map[string]any{
|
||||
"success": true,
|
||||
"status": string(TaskStateCompleted),
|
||||
"artifactScope": "tasks/session/run",
|
||||
"artifactDirectory": "/remote/openclaw/workspace/tasks/session/run",
|
||||
"expectedArtifactDirs": []any{
|
||||
"reports/",
|
||||
"artifacts/",
|
||||
},
|
||||
}
|
||||
|
||||
if openClawTaskGetRequiresArtifactExport(params, payload) {
|
||||
t.Fatal("expectedArtifactDirs must remain non-blocking scan hints")
|
||||
}
|
||||
got := normalizeOpenClawTaskGetResult(params, payload, "openclaw", nil)
|
||||
if status := shared.StringArg(got, "status", ""); status != string(TaskStateCompleted) {
|
||||
t.Fatalf("expected terminal status to remain completed, got %#v", got)
|
||||
}
|
||||
if parseBool(got["pending"]) {
|
||||
t.Fatalf("expected terminal payload not to become pending, got %#v", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRequiredArtifactExtensionsStillBlockUntilVerified(t *testing.T) {
|
||||
params := map[string]any{"requiredArtifactExtensions": []any{"md"}}
|
||||
payload := map[string]any{
|
||||
"success": true,
|
||||
"status": string(TaskStateCompleted),
|
||||
"artifactScope": "tasks/session/run",
|
||||
"artifactDirectory": "/remote/openclaw/workspace/tasks/session/run",
|
||||
}
|
||||
|
||||
if !openClawTaskGetRequiresArtifactExport(params, payload) {
|
||||
t.Fatal("requiredArtifactExtensions must remain a blocking delivery contract")
|
||||
}
|
||||
got := normalizeOpenClawTaskGetResult(params, payload, "openclaw", nil)
|
||||
if status := shared.StringArg(got, "status", ""); status != string(TaskStateRunning) {
|
||||
t.Fatalf("expected missing required artifact to remain syncing, got %#v", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNormalizeOpenClawTaskGetUnknownArtifactEvidenceFailsAfterDeadlineWithoutRequiredArtifacts(t *testing.T) {
|
||||
payload := map[string]any{
|
||||
"success": false,
|
||||
|
||||
@ -471,11 +471,9 @@ func openClawTaskGetRequiresArtifactExport(params map[string]any, payload map[st
|
||||
if parseBool(params["requiresExportBeforeFinalResponse"]) || parseBool(payload["requiresExportBeforeFinalResponse"]) {
|
||||
return true
|
||||
}
|
||||
// expectedArtifactDirs are discovery hints for the plugin's workspace-root
|
||||
// scan. They do not prove that the caller requires a file before the run can
|
||||
// reach a terminal state. Treating them as a blocking contract turns a
|
||||
// failed/no-output agent run into an endless "syncing-artifacts" loop.
|
||||
return len(shared.ListArg(params, "requiredArtifactExtensions")) > 0 ||
|
||||
return len(shared.ListArg(params, "expectedArtifactDirs")) > 0 ||
|
||||
len(shared.ListArg(payload, "expectedArtifactDirs")) > 0 ||
|
||||
len(shared.ListArg(params, "requiredArtifactExtensions")) > 0 ||
|
||||
len(shared.ListArg(payload, "requiredArtifactExtensions")) > 0
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user