Skip to content

Commit acb74a1

Browse files
committed
chore: repo-wide refactoring, reducing racing conditions and code smell.
- enforce TTL on in-memory hash fallbacks and improve hash handling - Added a test to ensure TTL is enforced on in-memory hash fallbacks when the runtime lacks hash support. - Updated RedisClient to manage hash fallback keys and ensure proper expiration handling. - Enhanced RedisEventsService to handle dead-lettering of malformed claimed payloads and maintain valid entries. - Introduced checkpointing for claimed entries in RedisEventsService to track successful claims. - Added utility functions to normalize Windows-style paths for group IDs in utils. - Implemented migration of temporary-root session state into canonical parent sessions in SessionManager.
1 parent e04a61f commit acb74a1

45 files changed

Lines changed: 6366 additions & 494 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/scripts/version.test.ts

Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,52 @@ import {
1313
findReleaseAs,
1414
hasBreakingChangeBody,
1515
hasNonTestChanges,
16+
parseChangedFiles,
1617
parseSemver,
18+
run,
1719
} from "./version.ts";
1820

21+
const makeCliDeps = (options: {
22+
env?: Record<string, string | undefined>;
23+
files?: Record<string, string>;
24+
commands?: Record<string, string | Error>;
25+
now?: Date;
26+
}) => {
27+
const outputs: string[] = [];
28+
const logs: string[] = [];
29+
const calls: string[] = [];
30+
31+
return {
32+
deps: {
33+
cmd: (...command: string[]) => {
34+
const key = command.join(" ");
35+
calls.push(key);
36+
const result = options.commands?.[key];
37+
if (result instanceof Error) return Promise.reject(result);
38+
return Promise.resolve(result ?? "");
39+
},
40+
readTextFile: (filePath: string) => {
41+
const result = options.files?.[filePath];
42+
if (result === undefined) {
43+
return Promise.reject(new Error(`ENOENT: ${filePath}`));
44+
}
45+
return Promise.resolve(result);
46+
},
47+
envGet: (name: string) => options.env?.[name],
48+
appendFile: (_filePath: string, text: string) => {
49+
outputs.push(text);
50+
},
51+
log: (message: string) => {
52+
logs.push(message);
53+
},
54+
now: () => options.now ?? new Date("2026-02-12T09:14:29Z"),
55+
},
56+
outputs,
57+
logs,
58+
calls,
59+
};
60+
};
61+
1962
describe("analyzeCommits", () => {
2063
it("returns 'none' for empty array", () => {
2164
assertEquals(analyzeCommits([]), "none");
@@ -339,6 +382,15 @@ describe("hasNonTestChanges", () => {
339382
});
340383
});
341384

385+
describe("parseChangedFiles", () => {
386+
it("returns unique trimmed changed paths", () => {
387+
assertEquals(
388+
parseChangedFiles("src/mod.ts\n\nsrc/mod.ts\n src/util.ts \n"),
389+
["src/mod.ts", "src/util.ts"],
390+
);
391+
});
392+
});
393+
342394
describe("calculateVersion", () => {
343395
const baseOpts = {
344396
currentVersion: "1.0.0",
@@ -582,6 +634,30 @@ describe("calculateVersion", () => {
582634
tag: "canary",
583635
});
584636
});
637+
638+
it("skips push release when no git tags and only test files changed", () => {
639+
const result = calculateVersion({
640+
...baseOpts,
641+
currentVersion: "0.0.0",
642+
subjects: ["chore: initial"],
643+
changedFiles: ["src/foo.test.ts", ".github/scripts/version.test.ts"],
644+
noGitTags: true,
645+
eventName: "push",
646+
});
647+
assertEquals(result, { skip: true });
648+
});
649+
650+
it("skips canary publish when no git tags and only test files changed", () => {
651+
const result = calculateVersion({
652+
...baseOpts,
653+
currentVersion: "0.0.0",
654+
subjects: ["docs: update"],
655+
changedFiles: ["src/foo.test.ts"],
656+
noGitTags: true,
657+
eventName: "pull_request",
658+
});
659+
assertEquals(result, { skip: true });
660+
});
585661
});
586662

587663
describe("edge cases", () => {
@@ -688,3 +764,131 @@ describe("calculateVersion", () => {
688764
});
689765
});
690766
});
767+
768+
describe("run", () => {
769+
it("writes release outputs for the git-tag CLI path used by GitHub Actions", async () => {
770+
const cli = makeCliDeps({
771+
env: {
772+
GITHUB_EVENT_NAME: "push",
773+
GITHUB_OUTPUT: "/tmp/github-output",
774+
COMMIT_SHA: "override-sha-1234567",
775+
},
776+
files: {
777+
"deno.json": JSON.stringify({ name: "opencode-graphiti" }),
778+
},
779+
commands: {
780+
"git describe --tags --abbrev=0 --match v*": "v1.2.3",
781+
"git log v1.2.3..HEAD --format=%s": "feat: ship cli coverage",
782+
"git log v1.2.3..HEAD --format=%b": "",
783+
"git diff --name-only v1.2.3..HEAD": ".github/scripts/version.ts\n",
784+
},
785+
});
786+
787+
await run([], cli.deps);
788+
789+
assertEquals(cli.outputs, ["version=1.3.0\n", "tag=latest\n"]);
790+
assertEquals(cli.logs, [
791+
"version=1.3.0",
792+
"tag=latest",
793+
"Release version: 1.3.0",
794+
]);
795+
assertEquals(
796+
cli.calls.includes("git describe --tags --abbrev=0 --match v*"),
797+
true,
798+
);
799+
});
800+
801+
it("covers the no-tag fallback path, package discovery, args fallback, and canary output", async () => {
802+
const cli = makeCliDeps({
803+
env: {
804+
GITHUB_OUTPUT: "/tmp/github-output",
805+
},
806+
files: {
807+
"package.json": JSON.stringify({ name: "fallback-package" }),
808+
},
809+
commands: {
810+
"git describe --tags --abbrev=0 --match v*": new Error("no tags"),
811+
"npm view fallback-package version": "0.1.0",
812+
"git log --format=%s": "docs: note fallback behavior",
813+
"git log --format=%b": "",
814+
"git log --format= --name-only": "src/mod.ts\n",
815+
},
816+
now: new Date("2026-02-12T09:14:29Z"),
817+
});
818+
819+
await run(["pull_request", "abcdef1234567890"], cli.deps);
820+
821+
assertEquals(cli.outputs, [
822+
"version=0.1.1-canary.abcdef1.20260212091429\n",
823+
"tag=canary\n",
824+
]);
825+
assertEquals(
826+
cli.logs.at(-1),
827+
"Canary version: 0.1.1-canary.abcdef1.20260212091429",
828+
);
829+
assertEquals(cli.calls.includes("npm view fallback-package version"), true);
830+
});
831+
832+
it("reads the package name from commented deno.jsonc content", async () => {
833+
const cli = makeCliDeps({
834+
env: {
835+
GITHUB_OUTPUT: "/tmp/github-output",
836+
},
837+
files: {
838+
"deno.jsonc": `{
839+
// Package metadata for release automation.
840+
"name": "commented-package",
841+
/* Keep the rest of the manifest commented-friendly. */
842+
"version": "0.0.0-development"
843+
}`,
844+
},
845+
commands: {
846+
"git describe --tags --abbrev=0 --match v*": new Error("no tags"),
847+
"npm view commented-package version": "0.2.0",
848+
"git log --format=%s": "docs: note jsonc support",
849+
"git log --format=%b": "",
850+
"git log --format= --name-only": ".github/scripts/version.ts\n",
851+
},
852+
now: new Date("2026-02-12T09:14:29Z"),
853+
});
854+
855+
await run(["pull_request", "abcdef1234567890"], cli.deps);
856+
857+
assertEquals(cli.outputs, [
858+
"version=0.2.1-canary.abcdef1.20260212091429\n",
859+
"tag=canary\n",
860+
]);
861+
assertEquals(
862+
cli.calls.includes("npm view commented-package version"),
863+
true,
864+
);
865+
});
866+
867+
it("emits skip=true when only test files changed", async () => {
868+
const cli = makeCliDeps({
869+
env: {
870+
GITHUB_EVENT_NAME: "push",
871+
GITHUB_OUTPUT: "/tmp/github-output",
872+
},
873+
files: {
874+
"deno.json": JSON.stringify({ name: "opencode-graphiti" }),
875+
},
876+
commands: {
877+
"git rev-parse HEAD": "abc123def4567890",
878+
"git describe --tags --abbrev=0 --match v*": "v1.2.3",
879+
"git log v1.2.3..HEAD --format=%s": "test: add cli coverage",
880+
"git log v1.2.3..HEAD --format=%b": "",
881+
"git diff --name-only v1.2.3..HEAD":
882+
".github/scripts/version.test.ts\n",
883+
},
884+
});
885+
886+
await run([], cli.deps);
887+
888+
assertEquals(cli.outputs, ["skip=true\n"]);
889+
assertEquals(cli.logs, [
890+
"skip=true",
891+
"No release-triggering commits since v1.2.3, skipping",
892+
]);
893+
});
894+
});

0 commit comments

Comments
 (0)