fix: 支持部署态CaseRun authority

This commit is contained in:
root
2026-07-26 09:14:04 +02:00
parent dbee5efe0a
commit a6a31f84fa
3 changed files with 29 additions and 6 deletions
+22
View File
@@ -55,6 +55,28 @@ test("Git case authority uses committed checkout HEAD and keeps configured drift
}]);
});
test("Git case authority accepts an immutable detached checkout with declared ref", async () => {
const fixture = await gitCaseFixture();
await git(fixture.root, ["checkout", "--detach", fixture.commit]);
const resolver = createGitCaseAuthorityResolver({
caseRepo: fixture.root,
expectedRepository: fixture.repository,
expectedRef: "main",
expectedCommit: fixture.commit
});
const resolved = await resolver.resolve(fixture.caseId);
assert.equal(resolved.authority.ref, "main");
assert.equal(resolved.authority.commit, fixture.commit);
assert.equal(resolved.authority.warnings, undefined);
});
test("Git case authority derives a stable ref for an undeclared detached checkout", async () => {
const fixture = await gitCaseFixture();
await git(fixture.root, ["checkout", "--detach", fixture.commit]);
const resolved = await createGitCaseAuthorityResolver({ caseRepo: fixture.root }).resolve(fixture.caseId);
assert.equal(resolved.authority.ref, `detached@${fixture.commit.slice(0, 12)}`);
});
test("Git case authority rejects a configured commit that is not readable", async () => {
const fixture = await gitCaseFixture();
const resolver = createGitCaseAuthorityResolver({ caseRepo: fixture.root, expectedCommit: "f".repeat(40) });
+4 -3
View File
@@ -34,7 +34,7 @@ export function createGitCaseAuthorityResolver(options: {
const [checkoutRepository, checkoutRef, checkoutCommit, dirty] = await Promise.all([
git(caseRepo, ["remote", "get-url", "origin"], "case_authority_repository_required"),
git(caseRepo, ["symbolic-ref", "--short", "HEAD"], "case_authority_ref_required"),
git(caseRepo, ["rev-parse", "--abbrev-ref", "HEAD"], "case_authority_ref_required"),
git(caseRepo, ["rev-parse", "HEAD"], "case_authority_commit_required"),
git(caseRepo, ["status", "--porcelain", "--", `cases/${caseId}`], "case_authority_status_failed", true)
]);
@@ -47,10 +47,11 @@ export function createGitCaseAuthorityResolver(options: {
}
const normalizedCommit = normalizedCheckoutCommit;
const repository = options.expectedRepository?.trim() || checkoutRepository;
const ref = options.expectedRef?.trim() || checkoutRef;
const detached = checkoutRef === "HEAD";
const ref = options.expectedRef?.trim() || (detached ? `detached@${normalizedCommit.slice(0, 12)}` : checkoutRef);
const warnings = [
authorityDriftWarning("repository", repository, checkoutRepository),
authorityDriftWarning("ref", ref, checkoutRef),
authorityDriftWarning("ref", ref, detached ? ref : checkoutRef),
authorityDriftWarning("commit", normalizedExpectedCommit, normalizedCheckoutCommit),
dirty && normalizedExpectedCommit ? {
code: "case_authority_checkout_dirty",
+3 -3
View File
@@ -26,9 +26,9 @@ export function harnessRLRuntime(env: Record<string, string | undefined> = proce
const temporal = createHarnessRLTemporalGateway({ address: temporalAddress, namespace: temporalNamespace, taskQueue, activity });
const caseAuthority = createGitCaseAuthorityResolver({
caseRepo,
expectedRepository: env.HARNESSRL_CASE_REPOSITORY,
expectedRef: env.HARNESSRL_CASE_REF,
expectedCommit: env.HARNESSRL_CASE_COMMIT
expectedRepository: env.HARNESSRL_CASE_REPOSITORY ?? env.HWLAB_BOOT_REPO,
expectedRef: env.HARNESSRL_CASE_REF ?? env.HWLAB_BOOT_REF,
expectedCommit: env.HARNESSRL_CASE_COMMIT ?? env.HWLAB_BOOT_COMMIT
});
return {
cwd, caseRepo, stateRoot, registry, temporalAddress, temporalNamespace, taskQueue, activity, caseAuthority,