@decohere/ci-tools 0.0.1-dev.39 → 0.0.1-dev.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@decohere/ci-tools",
3
- "version": "0.0.1-dev.39",
3
+ "version": "0.0.1-dev.4",
4
4
  "description": "CI utility scripts for badge generation, coverage reporting, pages artifact assembly, and GitHub API tooling",
5
5
  "keywords": [
6
6
  "typescript",
@@ -21,7 +21,7 @@ try {
21
21
  "- npm audit output could not be parsed.",
22
22
  `- See uploaded \`${auditFilePath}\` artifact for raw output.`,
23
23
  ]);
24
- process.exit(1);
24
+ process.exit(0);
25
25
  }
26
26
 
27
27
  const vulnerabilities = data.metadata?.vulnerabilities ?? {};
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  /**
4
- * bench.mjs — run the forge benchmark and compare against the last saved baseline.
4
+ * bench.mjs — run the forgev2 benchmark and compare against the last saved baseline.
5
5
  *
6
6
  * Usage:
7
7
  * node bench.mjs — run and compare, do not save
@@ -34,7 +34,7 @@ const HISTORY_FILE = join(
34
34
  "projects/ci-tools/dist/ci/bench/bench-history.json",
35
35
  );
36
36
  const VITEST_BIN = join(WORKSPACE_ROOT, "node_modules/.bin/vitest");
37
- const BENCH_FILE = "projects/terminal/e2e/build.benchmark.bench.ts";
37
+ const BENCH_FILE = "projects/foundry/e2e/build.benchmark.bench.ts";
38
38
  const CONFIG = join(WORKSPACE_ROOT, "vitest.e2e.config.ts");
39
39
  const TRACE_LOG_DIR = join(WORKSPACE_ROOT, ".decohere", "logs");
40
40
  const MAX_RUNS = 10;
@@ -7,7 +7,7 @@ import { join } from "node:path";
7
7
  const WORKSPACE_ROOT = process.cwd();
8
8
  const VITEST_BIN = join(WORKSPACE_ROOT, "node_modules/.bin/vitest");
9
9
  const CONFIG = join(WORKSPACE_ROOT, "vitest.e2e.config.ts");
10
- const TRACE_SPEC = "projects/terminal/e2e/build.trace.e2e.spec.ts";
10
+ const TRACE_SPEC = "projects/foundry/e2e/build.trace.e2e.spec.ts";
11
11
  const TRACE_LOG_DIR = join(WORKSPACE_ROOT, ".decohere", "logs");
12
12
 
13
13
  function truthy(value, defaultValue = false) {
@@ -10,8 +10,8 @@ import path from "node:path";
10
10
  import { parseLcovByProject } from "../lib/lcov.mjs";
11
11
  import { createBadgeSvg, getColor } from "../lib/svg.mjs";
12
12
 
13
- const summaryPath = path.resolve("dist/coverage/coverage-summary.json");
14
- const lcovPath = path.resolve("dist/coverage/lcov.info");
13
+ const summaryPath = path.resolve(".forge/coverage/coverage-summary.json");
14
+ const lcovPath = path.resolve(".forge/coverage/lcov.info");
15
15
  const badgesDirectory = path.resolve("projects/ci-tools/dist/ci/badges");
16
16
  const globalBadgePath = path.join(badgesDirectory, "coverage.svg");
17
17
  const projectBadgesDirectory = path.join(badgesDirectory, "projects");
@@ -3,8 +3,9 @@
3
3
  // Restore benchmark history from Pages, or initialize empty if not found
4
4
 
5
5
  import { execSync } from "node:child_process";
6
- import { writeFileSync } from "node:fs";
6
+ import { existsSync, writeFileSync } from "node:fs";
7
7
  import { mkdir } from "node:fs/promises";
8
+ import { dirname } from "node:path";
8
9
 
9
10
  const HISTORY_DIR = "projects/ci-tools/dist/ci/bench";
10
11
  const HISTORY_FILE = `${HISTORY_DIR}/bench-history.json`;
@@ -1,23 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * Publish prerelease version commit via PR
4
- * Validates working tree, pushes prerelease commit to a release branch,
5
- * and creates/updates a PR targeting the protected base branch.
3
+ * Push prerelease version commit before publish
4
+ * Validates working tree and pushes new prerelease commit to remote
6
5
  */
7
6
 
8
7
  import { execSync } from "node:child_process";
9
8
 
10
- function run(command) {
11
- return execSync(command, { encoding: "utf8" }).trim();
12
- }
13
-
14
- function runInherit(command, env) {
15
- execSync(command, { stdio: "inherit", env });
16
- }
17
-
18
9
  try {
19
10
  // Check if working tree is dirty
20
- const status = run("git status --porcelain");
11
+ const status = execSync("git status --porcelain", { encoding: "utf8" });
21
12
  if (status.trim().length > 0) {
22
13
  console.error(
23
14
  "::error::Working tree is dirty after version/dependency sync; refusing to publish with uncommitted changes.",
@@ -26,58 +17,25 @@ try {
26
17
  process.exit(1);
27
18
  }
28
19
 
29
- // Compare HEAD with origin and create a PR branch targeting an explicit base branch.
30
- const head = run("git rev-parse HEAD");
31
- const sourceBranch = process.env.GITHUB_REF_NAME || run("git rev-parse --abbrev-ref HEAD");
32
- const channel = process.env.RELEASE_CHANNEL ?? "beta";
33
- const baseBranch = process.env.RELEASE_BASE_BRANCH || sourceBranch;
34
- const releasePrBranch = `release/${channel}-${sourceBranch}-to-${baseBranch}`;
35
- const token = process.env.GITHUB_TOKEN ?? process.env.GH_TOKEN;
20
+ // Compare HEAD with origin
21
+ const head = execSync("git rev-parse HEAD", { encoding: "utf8" }).trim();
22
+ const branch =
23
+ process.env.GITHUB_REF_NAME ||
24
+ execSync("git rev-parse --abbrev-ref HEAD", {
25
+ encoding: "utf8",
26
+ }).trim();
36
27
 
37
28
  try {
38
- const origin = run(`git rev-parse origin/${sourceBranch}`);
29
+ const origin = execSync(`git rev-parse origin/${branch}`, { encoding: "utf8" }).trim();
39
30
 
40
31
  if (head !== origin) {
41
- console.log(
42
- `Publishing release commit via PR branch origin/${releasePrBranch} (base: origin/${baseBranch})`,
43
- );
44
- runInherit(`git push origin HEAD:${releasePrBranch} --force`, process.env);
45
-
46
- if (token == null || token.length === 0) {
47
- throw new Error("Missing GITHUB_TOKEN/GH_TOKEN for PR upsert");
48
- }
49
-
50
- const version = process.env.RELEASE_VERSION ?? "(unknown)";
51
- const ownerRepo = run("git config --get remote.origin.url")
52
- .replace(/^.*github\.com[:/]/, "")
53
- .replace(/\.git$/, "");
54
-
55
- runInherit(
56
- [
57
- "node projects/ci-tools/src/github/create-or-update-pr.mjs",
58
- `--title "chore(release): ${channel} ${version}"`,
59
- `--base "${baseBranch}"`,
60
- `--head "${releasePrBranch}"`,
61
- `--body "Automated ${channel} version bump and dependency sync.\\n\\n- Channel: ${channel}\\n- Version: ${version}\\n- Source branch: ${sourceBranch}\\n- Base branch: ${baseBranch}\\n- Source commit: ${head}\\n\\nGenerated by pull-request workflow."`,
62
- `--owner "${ownerRepo.split("/")[0]}"`,
63
- `--repo "${ownerRepo.split("/")[1]}"`,
64
- ].join(" "),
65
- { ...process.env, GITHUB_TOKEN: token },
66
- );
32
+ console.log(`Pushing prerelease version commit to origin/${branch}`);
33
+ execSync(`git push origin HEAD:${branch}`, { stdio: "inherit" });
67
34
  } else {
68
35
  console.log("No prerelease version commit to push.");
69
36
  }
70
- } catch (err) {
71
- const message = err?.message ?? "";
72
- if (
73
- message.includes(`origin/${sourceBranch}`) &&
74
- message.includes("Needed a single revision")
75
- ) {
76
- console.log(`Remote branch origin/${sourceBranch} not found, skipping push.`);
77
- } else {
78
- console.error("::error::Failed to publish release commit via PR branch.");
79
- throw err;
80
- }
37
+ } catch {
38
+ console.log(`Remote branch origin/${branch} not found, skipping push.`);
81
39
  }
82
40
  } catch (e) {
83
41
  console.error(`Push failed: ${e.message}`);
@@ -10,7 +10,7 @@ const DRY_RUN = process.env.DRY_RUN === "true";
10
10
  const TERMINAL_CLI = process.env.TERMINAL_CLI || "dist/debug/projects/terminal/src/cli.js";
11
11
  const DECOHERE_CONFIG = process.env.DECOHERE_CONFIG || ".decohere.js";
12
12
 
13
- const baseCmd = `node "${TERMINAL_CLI}" --log-level info --config-file "${DECOHERE_CONFIG}" forge dependencies --configuration release sync`;
13
+ const baseCmd = `node "${TERMINAL_CLI}" --log-level trace --config-file "${DECOHERE_CONFIG}" foundry dependencies --configuration release sync`;
14
14
 
15
15
  try {
16
16
  if (DRY_RUN) {
@@ -5,11 +5,11 @@ import {
5
5
  parseLcovFiles,
6
6
  } from "../../src/lib/lcov.mjs";
7
7
 
8
- const sampleLcov = `SF:projects/forge/src/index.ts
8
+ const sampleLcov = `SF:projects/foundry/src/index.ts
9
9
  LF:10
10
10
  LH:9
11
11
  end_of_record
12
- SF:projects/forge/src/build/index.ts
12
+ SF:projects/foundry/src/build/index.ts
13
13
  LF:20
14
14
  LH:15
15
15
  end_of_record
@@ -32,7 +32,7 @@ end_of_record
32
32
 
33
33
  describe("getProjectFromPath", () => {
34
34
  it("extracts project name from projects/ path", () => {
35
- expect(getProjectFromPath("projects/forge/src/index.ts")).toBe("forge");
35
+ expect(getProjectFromPath("projects/foundry/src/index.ts")).toBe("foundry");
36
36
  });
37
37
 
38
38
  it("returns undefined for unrecognized paths", () => {
@@ -43,16 +43,16 @@ describe("getProjectFromPath", () => {
43
43
  describe("parseLcovByProject", () => {
44
44
  it("groups files by project and sums coverage", () => {
45
45
  const result = parseLcovByProject(sampleLcov);
46
- expect(result.get("forge")).toBeDefined();
47
- expect(result.get("forge").totalLines).toBe(30);
48
- expect(result.get("forge").coveredLines).toBe(24);
46
+ expect(result.get("foundry")).toBeDefined();
47
+ expect(result.get("foundry").totalLines).toBe(30);
48
+ expect(result.get("foundry").coveredLines).toBe(24);
49
49
  expect(result.get("nexus")).toBeDefined();
50
50
  expect(result.get("nexus").totalLines).toBe(5);
51
51
  expect(result.get("nexus").coveredLines).toBe(5);
52
52
  });
53
53
 
54
54
  it("ignores records with LF:0", () => {
55
- const lcov = `SF:projects/forge/src/empty.ts\nLF:0\nLH:0\nend_of_record\n`;
55
+ const lcov = `SF:projects/foundry/src/empty.ts\nLF:0\nLH:0\nend_of_record\n`;
56
56
  const result = parseLcovByProject(lcov);
57
57
  expect(result.size).toBe(0);
58
58
  });