Publish curated projectbrain source from 0244fbf232898e6dc076ff2159d96a6da55ab5b5
This commit is contained in:
1 parent
eca2891b07
commit
d5c9615684
10 files changed
+170
-31
No files matched your search
@@ -301,7 +301,7 @@ databaseDescribe("autonomy database write isolation", () => {
|
||||
vi.spyOn(GiteaClient.prototype, "getBranch").mockResolvedValue({ name: "chatgpt/existing", commit: { id: head, message: "Repair" }, protected: false });
|
||||
vi.spyOn(GiteaClient.prototype, "getContents").mockResolvedValue({ type: "file", path: "src/feature.ts", name: "feature.ts", sha: "file-sha", size: 4, encoding: "base64", content: "dGVzdA==" });
|
||||
const write = vi.spyOn(GiteaClient.prototype, "updateFile").mockResolvedValue({});
|
||||
vi.spyOn(GiteaClient.prototype, "listActionRuns").mockResolvedValue({ total_count: 2, workflow_runs: [
|
||||
const actionRuns = vi.spyOn(GiteaClient.prototype, "listActionRuns").mockResolvedValue({ total_count: 2, workflow_runs: [
|
||||
{ id: 2, run_number: 2, display_title: "Managed validation / full", path: ".gitea/workflows/managed-validation.yml", event: "pull_request", head_sha: head, head_branch: "chatgpt/existing", status: "completed", conclusion: "success", html_url: "https://gitea.example.com/runs/2" },
|
||||
{ id: 3, run_number: 3, display_title: "CI", path: ".gitea/workflows/ci.yml", event: "pull_request", head_sha: head, head_branch: "chatgpt/existing", status: "completed", conclusion: "success", html_url: "https://gitea.example.com/runs/3" },
|
||||
] });
|
||||
@@ -323,6 +323,32 @@ databaseDescribe("autonomy database write isolation", () => {
|
||||
expect(repaired.spec.validationResults).toEqual([]);
|
||||
const synced = await client.callTool({ name: "sync_feature_validation", arguments: { project_id: slug, delivery_id: delivery.id } });
|
||||
expect(synced.isError, JSON.stringify(synced.content)).not.toBe(true);
|
||||
|
||||
actionRuns.mockResolvedValue({ total_count: 1, workflow_runs: [
|
||||
{ id: 4, run_number: 4, display_title: "Managed validation / full", path: ".gitea/workflows/managed-validation.yml", event: "pull_request", head_sha: "c".repeat(40), head_branch: "chatgpt/existing", status: "completed", conclusion: "success", html_url: "https://gitea.example.com/runs/4" },
|
||||
] });
|
||||
const stalePrRun = await client.callTool({ name: "merge_feature_delivery", arguments: { project_id: slug, delivery_id: delivery.id, expected_head_sha: head, delete_branch: false } });
|
||||
expect(stalePrRun.isError, JSON.stringify(stalePrRun.content)).toBe(true);
|
||||
expect(merge).not.toHaveBeenCalled();
|
||||
|
||||
actionRuns.mockResolvedValue({ total_count: 1, workflow_runs: [
|
||||
{ id: 5, run_number: 5, display_title: "Managed validation / full", path: ".gitea/workflows/managed-validation.yml", event: "workflow_dispatch", head_sha: head, head_branch: "chatgpt/existing", status: "completed", conclusion: "success", html_url: "https://gitea.example.com/runs/5" },
|
||||
] });
|
||||
const dispatchOnly = await client.callTool({ name: "merge_feature_delivery", arguments: { project_id: slug, delivery_id: delivery.id, expected_head_sha: head, delete_branch: false } });
|
||||
expect(dispatchOnly.isError, JSON.stringify(dispatchOnly.content)).toBe(true);
|
||||
expect(merge).not.toHaveBeenCalled();
|
||||
|
||||
actionRuns.mockResolvedValue({ total_count: 1, workflow_runs: [
|
||||
{ id: 6, run_number: 6, display_title: "Managed validation / full", path: ".gitea/workflows/managed-validation.yml", event: "pull_request", head_sha: head, head_branch: "chatgpt/existing", status: "completed", conclusion: "failure", html_url: "https://gitea.example.com/runs/6" },
|
||||
] });
|
||||
const failedPrFull = await client.callTool({ name: "merge_feature_delivery", arguments: { project_id: slug, delivery_id: delivery.id, expected_head_sha: head, delete_branch: false } });
|
||||
expect(failedPrFull.isError, JSON.stringify(failedPrFull.content)).toBe(true);
|
||||
expect(merge).not.toHaveBeenCalled();
|
||||
|
||||
actionRuns.mockResolvedValue({ total_count: 2, workflow_runs: [
|
||||
{ id: 2, run_number: 2, display_title: "Managed validation / full", path: ".gitea/workflows/managed-validation.yml", event: "pull_request", head_sha: head, head_branch: "chatgpt/existing", status: "completed", conclusion: "success", html_url: "https://gitea.example.com/runs/2" },
|
||||
{ id: 3, run_number: 3, display_title: "CI", path: ".gitea/workflows/ci.yml", event: "pull_request", head_sha: head, head_branch: "chatgpt/existing", status: "completed", conclusion: "success", html_url: "https://gitea.example.com/runs/3" },
|
||||
] });
|
||||
const merged = await client.callTool({ name: "merge_feature_delivery", arguments: { project_id: slug, delivery_id: delivery.id, expected_head_sha: head, delete_branch: false } });
|
||||
expect(merged.isError, JSON.stringify(merged.content)).not.toBe(true);
|
||||
expect(merge).toHaveBeenCalledTimes(1);
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import { giteaMergeCompatibility } from "../src/integrations/gitea/compatibility.js";
|
||||
import { GiteaClient } from "../src/integrations/gitea/client.js";
|
||||
|
||||
describe("upstream Gitea merge negotiation", () => {
|
||||
it.each(["28.0.0", "v28.0.0", "28.0.0+gitea.build-123", " v1.27.3+build.42 ", "1.25.0"])("accepts attested stable version %s", (value) => {
|
||||
expect(giteaMergeCompatibility(value)).toMatchObject({ supported: true });
|
||||
});
|
||||
it.each([undefined, null, {}, 28, "", "1.24.9", "29.0.0", "2.0.0", "28.0", "028.0.0", "28.0.0+", "28.0.0+bad/metadata", "28.0.0-rc.1", "28.0.0-garbage suffix", "28.0.0+" + "a".repeat(128)])("fails closed for %s", (value) => {
|
||||
expect(giteaMergeCompatibility(value).supported).toBe(false);
|
||||
});
|
||||
it("does not accept a connector version in place of the upstream version", async () => {
|
||||
const fetcher = vi.fn(async () => new Response(JSON.stringify({ connectorVersion: "28.0.0", version: "1.24.9" })));
|
||||
const client = new GiteaClient("https://gitea.example.com", "test-token", fetcher as typeof fetch);
|
||||
expect(await client.getUpstreamCompatibility()).toMatchObject({ supported: false, source: "upstream:/api/v1/version", normalizedVersion: "1.24.9" });
|
||||
});
|
||||
it("uses current upstream 28 when connector build is 1.14", async () => {
|
||||
const fetcher = vi.fn(async () => new Response(JSON.stringify({ connectorVersion: "1.14.0", version: "28.0.0" })));
|
||||
const client = new GiteaClient("https://gitea.example.com", "test-token", fetcher as typeof fetch);
|
||||
expect(await client.getUpstreamCompatibility()).toMatchObject({ supported: true, normalizedVersion: "28.0.0", strategyKey: "do" });
|
||||
});
|
||||
it("re-negotiates before each merge and blocks an unsupported server upgrade", async () => {
|
||||
let version = "28.0.0";
|
||||
let writes = 0;
|
||||
const fetcher = vi.fn(async (input: string | URL | Request) => {
|
||||
if (String(input).endsWith("/version")) return new Response(JSON.stringify({ version }));
|
||||
writes += 1;
|
||||
return new Response(null, { status: 204 });
|
||||
});
|
||||
const client = new GiteaClient("https://gitea.example.com", "test-token", fetcher as typeof fetch);
|
||||
await client.mergePullRequest("Jens", "canary", 1, { method: "squash", headCommitId: "a".repeat(40) });
|
||||
version = "29.0.0";
|
||||
await expect(client.mergePullRequest("Jens", "canary", 1, { method: "squash", headCommitId: "a".repeat(40) })).rejects.toMatchObject({ code: "GITEA_VERSION_UNSUPPORTED" });
|
||||
expect(writes).toBe(1);
|
||||
});
|
||||
});
|
||||
@@ -1,7 +1,7 @@
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import { loadEnv } from "../src/config/env.js";
|
||||
import { GiteaClient, GiteaApiError } from "../src/integrations/gitea/client.js";
|
||||
import { assertChatGptBranch, assertExpectedFileSha, assertFileSize, assertProjectBrainBranch, assertReadablePath, assertSuccessfulActionRuns, normalizeRepositoryPath } from "../src/integrations/gitea/policy.js";
|
||||
import { assertChatGptBranch, assertExpectedFileSha, assertFileSize, assertProjectBrainBranch, assertReadablePath, assertSuccessfulActionRuns, assertSuccessfulPullRequestFullActionRun, normalizeRepositoryPath } from "../src/integrations/gitea/policy.js";
|
||||
import type { GiteaActionRun } from "../src/integrations/gitea/types.js";
|
||||
import { exchangeAuthorizationCode, exchangeRefreshToken, issueAuthorizationCode, registerOAuthClient, verifyMcpAccessToken } from "../src/security/mcpOAuth.js";
|
||||
import { createHash, createHmac } from "node:crypto";
|
||||
@@ -295,7 +295,7 @@ describe("Gitea API client", () => {
|
||||
await client.mergePullRequest("Acme", "Repo", 17, { method: "merge", headCommitId: "b".repeat(40) });
|
||||
await client.mergePullRequest("Acme", "Repo", 18, { method: "squash", headCommitId: "c".repeat(40) });
|
||||
|
||||
expect(fetcher.mock.calls.filter(([input]) => String(input).endsWith("/version"))).toHaveLength(1);
|
||||
expect(fetcher.mock.calls.filter(([input]) => String(input).endsWith("/version"))).toHaveLength(2);
|
||||
const firstBody = JSON.parse(String(fetcher.mock.calls[1][1]?.body)) as Record<string, unknown>;
|
||||
expect(firstBody[strategyKey]).toBe("merge");
|
||||
expect(firstBody[strategyKey === "Do" ? "do" : "Do"]).toBeUndefined();
|
||||
@@ -539,4 +539,27 @@ describe("ChatGPT feature delivery approval", () => {
|
||||
expect(() => assertSuccessfulActionRuns([run(1, "success"), run(2, "failure")], "chatgpt/feature", "current-sha")).toThrow("FEATURE_DELIVERY_FULL_VALIDATION_REQUIRED");
|
||||
expect(() => assertSuccessfulActionRuns([run(1, "success", "stale-sha")], "chatgpt/feature", "current-sha")).toThrow("FEATURE_DELIVERY_CI_NOT_SUCCESSFUL");
|
||||
});
|
||||
|
||||
it("requires a successful canonical pull-request full run on the exact head before merge", () => {
|
||||
const headSha = "a".repeat(40);
|
||||
const branch = "chatgpt/feature";
|
||||
const run = (overrides: Partial<GiteaActionRun> = {}): GiteaActionRun => ({
|
||||
id: 10,
|
||||
run_number: 10,
|
||||
display_title: "Managed validation / full",
|
||||
path: ".gitea/workflows/managed-validation.yml",
|
||||
event: "pull_request",
|
||||
head_sha: headSha,
|
||||
head_branch: branch,
|
||||
status: "completed",
|
||||
conclusion: "success",
|
||||
html_url: "https://gitea.example.com/runs/10",
|
||||
...overrides,
|
||||
});
|
||||
|
||||
expect(assertSuccessfulPullRequestFullActionRun([run()], branch, headSha)).toMatchObject({ event: "pull_request", head_sha: headSha, conclusion: "success" });
|
||||
expect(() => assertSuccessfulPullRequestFullActionRun([run({ head_sha: "b".repeat(40) })], branch, headSha)).toThrow("FEATURE_DELIVERY_PULL_REQUEST_FULL_VALIDATION_REQUIRED");
|
||||
expect(() => assertSuccessfulPullRequestFullActionRun([run({ event: "workflow_dispatch" })], branch, headSha)).toThrow("FEATURE_DELIVERY_PULL_REQUEST_FULL_VALIDATION_REQUIRED");
|
||||
expect(() => assertSuccessfulPullRequestFullActionRun([run({ conclusion: "failure" })], branch, headSha)).toThrow("FEATURE_DELIVERY_PULL_REQUEST_FULL_VALIDATION_REQUIRED");
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user