ci: disable automatic workflow triggers
This commit is contained in:
8
.github/workflows/mobile.yml
vendored
8
.github/workflows/mobile.yml
vendored
@@ -1,14 +1,8 @@
|
|||||||
name: Mobile Builds
|
name: Mobile Builds
|
||||||
|
|
||||||
|
# Auto-trigger disabled; workflow preserved for manual use via workflow_dispatch.
|
||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
paths:
|
|
||||||
- "packages/mobile/**"
|
|
||||||
- "packages/dashboard/**"
|
|
||||||
- ".github/workflows/mobile.yml"
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build-web:
|
build-web:
|
||||||
|
|||||||
5
.github/workflows/release.yml
vendored
5
.github/workflows/release.yml
vendored
@@ -10,10 +10,9 @@
|
|||||||
|
|
||||||
name: Binary Release
|
name: Binary Release
|
||||||
|
|
||||||
|
# Auto-trigger disabled; workflow preserved for manual use via workflow_dispatch.
|
||||||
on:
|
on:
|
||||||
push:
|
workflow_dispatch:
|
||||||
tags:
|
|
||||||
- "v*"
|
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
|
|||||||
5
.github/workflows/version.yml
vendored
5
.github/workflows/version.yml
vendored
@@ -5,10 +5,9 @@
|
|||||||
|
|
||||||
name: Version & Release
|
name: Version & Release
|
||||||
|
|
||||||
|
# Auto-trigger disabled; workflow preserved for manual use via workflow_dispatch.
|
||||||
on:
|
on:
|
||||||
push:
|
workflow_dispatch:
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
|
|||||||
@@ -83,8 +83,12 @@ describe("Version & Release workflow (.github/workflows/version.yml)", () => {
|
|||||||
expect(typeof workflow).toBe("object");
|
expect(typeof workflow).toBe("object");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("has push trigger on main", () => {
|
it("uses workflow_dispatch trigger (auto release disabled)", () => {
|
||||||
expect(workflow.on.push.branches).toContain("main");
|
expect(workflow.on).toHaveProperty("workflow_dispatch");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("does not auto-trigger on push", () => {
|
||||||
|
expect(workflow.on.push).toBeUndefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("includes pnpm install step", () => {
|
it("includes pnpm install step", () => {
|
||||||
@@ -143,9 +147,12 @@ describe("Binary release workflow (.github/workflows/release.yml)", () => {
|
|||||||
expect(typeof workflow).toBe("object");
|
expect(typeof workflow).toBe("object");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("triggers on version tags", () => {
|
it("uses workflow_dispatch trigger (auto binary release disabled)", () => {
|
||||||
expect(workflow.on.push.tags).toBeDefined();
|
expect(workflow.on).toHaveProperty("workflow_dispatch");
|
||||||
expect(workflow.on.push.tags.some((t: string) => t.includes("v"))).toBe(true);
|
});
|
||||||
|
|
||||||
|
it("does not auto-trigger on version tags", () => {
|
||||||
|
expect(workflow.on.push).toBeUndefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("has build-binaries job with 4-target matrix", () => {
|
it("has build-binaries job with 4-target matrix", () => {
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ describe("Changeset configuration", () => {
|
|||||||
|
|
||||||
const content = readFileSync(workflowPath, "utf-8");
|
const content = readFileSync(workflowPath, "utf-8");
|
||||||
expect(content).toContain("changesets/action");
|
expect(content).toContain("changesets/action");
|
||||||
expect(content).toContain("push");
|
expect(content).toContain("workflow_dispatch");
|
||||||
expect(content).toContain("main");
|
expect(content).toContain("Auto-trigger disabled");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { describe, it, expect, vi, beforeEach } from "vitest";
|
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
||||||
import { EventEmitter } from "node:events";
|
import { EventEmitter } from "node:events";
|
||||||
|
|
||||||
// ── Capture arguments ───────────────────────────────────────────────
|
// ── Capture arguments ───────────────────────────────────────────────
|
||||||
@@ -6,6 +6,10 @@ import { EventEmitter } from "node:events";
|
|||||||
// Minimal mock store backed by EventEmitter so `store.on` works
|
// Minimal mock store backed by EventEmitter so `store.on` works
|
||||||
function makeMockStore() {
|
function makeMockStore() {
|
||||||
const emitter = new EventEmitter();
|
const emitter = new EventEmitter();
|
||||||
|
// runDashboard registers several independent settings listeners by design;
|
||||||
|
// keep the test mock above Node's low default threshold while still checking
|
||||||
|
// startup wiring behavior.
|
||||||
|
emitter.setMaxListeners(20);
|
||||||
const mockMissionStore = {
|
const mockMissionStore = {
|
||||||
listMissions: vi.fn().mockReturnValue([]),
|
listMissions: vi.fn().mockReturnValue([]),
|
||||||
getMission: vi.fn(),
|
getMission: vi.fn(),
|
||||||
@@ -214,10 +218,28 @@ vi.mock("@mariozechner/pi-coding-agent", () => ({
|
|||||||
|
|
||||||
// ── Import module under test (after mocks) ──────────────────────────
|
// ── Import module under test (after mocks) ──────────────────────────
|
||||||
|
|
||||||
const { runDashboard } = await import("../dashboard.js");
|
const { runDashboard: runDashboardImpl } = await import("../dashboard.js");
|
||||||
|
const dashboardDisposables: Array<() => void> = [];
|
||||||
|
|
||||||
|
function disposeTrackedDashboards(): void {
|
||||||
|
for (const dispose of dashboardDisposables.splice(0)) {
|
||||||
|
dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function runDashboard(...args: Parameters<typeof runDashboardImpl>): ReturnType<typeof runDashboardImpl> {
|
||||||
|
disposeTrackedDashboards();
|
||||||
|
const result = await runDashboardImpl(...args);
|
||||||
|
dashboardDisposables.push(result.dispose);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
// ── Tests ───────────────────────────────────────────────────────────
|
// ── Tests ───────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
disposeTrackedDashboards();
|
||||||
|
});
|
||||||
|
|
||||||
describe("runDashboard — AuthStorage & ModelRegistry wiring", () => {
|
describe("runDashboard — AuthStorage & ModelRegistry wiring", () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
vi.clearAllMocks();
|
vi.clearAllMocks();
|
||||||
|
|||||||
@@ -35,6 +35,10 @@ const {
|
|||||||
// Minimal mock store backed by EventEmitter so `store.on` works
|
// Minimal mock store backed by EventEmitter so `store.on` works
|
||||||
function makeMockStore() {
|
function makeMockStore() {
|
||||||
const emitter = new EventEmitter();
|
const emitter = new EventEmitter();
|
||||||
|
// runDashboard registers several independent settings listeners by design;
|
||||||
|
// keep the test mock above Node's low default threshold while still asserting
|
||||||
|
// disposal behavior in the lifecycle cleanup tests below.
|
||||||
|
emitter.setMaxListeners(20);
|
||||||
const mockMissionStore = {
|
const mockMissionStore = {
|
||||||
listMissions: vi.fn().mockReturnValue([]),
|
listMissions: vi.fn().mockReturnValue([]),
|
||||||
getMission: vi.fn(),
|
getMission: vi.fn(),
|
||||||
@@ -164,12 +168,19 @@ const {
|
|||||||
mockMergePr,
|
mockMergePr,
|
||||||
} = vi.hoisted(() => ({
|
} = vi.hoisted(() => ({
|
||||||
mockExec: vi.fn((_command: string, _options?: any, callback?: (err: null, stdout: string, stderr: string) => void) => {
|
mockExec: vi.fn((_command: string, _options?: any, callback?: (err: null, stdout: string, stderr: string) => void) => {
|
||||||
// Handle both callback-style (original exec) and promise-style (promisified execAsync)
|
|
||||||
if (typeof callback === "function") {
|
if (typeof callback === "function") {
|
||||||
callback(null, "", "");
|
callback(null, "", "");
|
||||||
}
|
}
|
||||||
// Return resolved promise for promisified usage
|
// Match child_process.exec's callback-style contract. Returning a Promise
|
||||||
return Promise.resolve({ stdout: "", stderr: "" });
|
// makes util.promisify(exec) emit DEP0174 in tests.
|
||||||
|
return {
|
||||||
|
pid: 12345,
|
||||||
|
stdout: null,
|
||||||
|
stderr: null,
|
||||||
|
on: vi.fn(),
|
||||||
|
once: vi.fn(),
|
||||||
|
kill: vi.fn(),
|
||||||
|
};
|
||||||
}),
|
}),
|
||||||
mockExecSync: vi.fn(() => ""),
|
mockExecSync: vi.fn(() => ""),
|
||||||
mockFindPrForBranch: vi.fn(),
|
mockFindPrForBranch: vi.fn(),
|
||||||
@@ -329,8 +340,22 @@ vi.mock("@mariozechner/pi-coding-agent", () => ({
|
|||||||
|
|
||||||
// ── Import module under test (after mocks) ──────────────────────────
|
// ── Import module under test (after mocks) ──────────────────────────
|
||||||
|
|
||||||
const { runDashboard } = await import("./dashboard.js");
|
const { runDashboard: runDashboardImpl } = await import("./dashboard.js");
|
||||||
const { processPullRequestMergeTask, getMergeStrategy, getTaskBranchName } = await import("./task-lifecycle.js");
|
const { processPullRequestMergeTask, getMergeStrategy, getTaskBranchName } = await import("./task-lifecycle.js");
|
||||||
|
const dashboardDisposables: Array<() => void> = [];
|
||||||
|
|
||||||
|
function disposeTrackedDashboards(): void {
|
||||||
|
for (const dispose of dashboardDisposables.splice(0)) {
|
||||||
|
dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function runDashboard(...args: Parameters<typeof runDashboardImpl>): ReturnType<typeof runDashboardImpl> {
|
||||||
|
disposeTrackedDashboards();
|
||||||
|
const result = await runDashboardImpl(...args);
|
||||||
|
dashboardDisposables.push(result.dispose);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
// ── Tests ───────────────────────────────────────────────────────────
|
// ── Tests ───────────────────────────────────────────────────────────
|
||||||
|
|
||||||
@@ -385,6 +410,10 @@ beforeEach(() => {
|
|||||||
mockStuckCheckNow.mockResolvedValue(undefined);
|
mockStuckCheckNow.mockResolvedValue(undefined);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
disposeTrackedDashboards();
|
||||||
|
});
|
||||||
|
|
||||||
describe("PR merge helpers", () => {
|
describe("PR merge helpers", () => {
|
||||||
it("defaults mergeStrategy to direct when unset", () => {
|
it("defaults mergeStrategy to direct when unset", () => {
|
||||||
expect(getMergeStrategy({ mergeStrategy: undefined })).toBe("direct");
|
expect(getMergeStrategy({ mergeStrategy: undefined })).toBe("direct");
|
||||||
|
|||||||
@@ -147,11 +147,7 @@ function cleanupExpiredRateLimits(): void {
|
|||||||
|
|
||||||
// Start cleanup interval
|
// Start cleanup interval
|
||||||
const cleanupInterval = setInterval(cleanupExpiredRateLimits, CLEANUP_INTERVAL_MS);
|
const cleanupInterval = setInterval(cleanupExpiredRateLimits, CLEANUP_INTERVAL_MS);
|
||||||
|
cleanupInterval.unref?.();
|
||||||
// Handle graceful shutdown
|
|
||||||
process.on("beforeExit", () => {
|
|
||||||
clearInterval(cleanupInterval);
|
|
||||||
});
|
|
||||||
|
|
||||||
// ── Custom Errors ───────────────────────────────────────────────────────────
|
// ── Custom Errors ───────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user