mirror of
https://github.com/aljazceru/claude-code-viewer.git
synced 2025-12-24 08:44:21 +01:00
chore: fix a bit
This commit is contained in:
13
.github/workflows/ci.yml
vendored
13
.github/workflows/ci.yml
vendored
@@ -41,9 +41,6 @@ jobs:
|
||||
- name: Run type checking
|
||||
run: pnpm typecheck
|
||||
|
||||
- name: Run tests
|
||||
run: pnpm test
|
||||
|
||||
e2e:
|
||||
name: E2E Visual Regression Tests
|
||||
runs-on: ubuntu-latest
|
||||
@@ -67,8 +64,8 @@ jobs:
|
||||
- name: Setup Git user
|
||||
shell: bash
|
||||
run: |
|
||||
git config --global user.email "xxx@example.com"
|
||||
git config --global user.name "user"
|
||||
git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
||||
git config --global user.name "github-actions[bot]"
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
@@ -81,12 +78,6 @@ jobs:
|
||||
env:
|
||||
MAX_CONCURRENCY: 5
|
||||
|
||||
- name: Setup Git user
|
||||
shell: bash
|
||||
run: |
|
||||
git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
||||
git config --global user.name "github-actions[bot]"
|
||||
|
||||
- name: Commit screenshots
|
||||
run: |
|
||||
git add e2e/snapshots
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
import { homeCapture } from "./home";
|
||||
import { errorPagesCapture } from "./error-pages";
|
||||
import { projectsCapture } from "./projects";
|
||||
import { projectDetailCapture } from "./project-detail";
|
||||
import { sessionDetailCapture } from "./session-detail";
|
||||
import { TaskExecutor } from "../utils/TaskExecutor";
|
||||
import { errorPagesCapture } from "./error-pages";
|
||||
import { homeCapture } from "./home";
|
||||
import { projectDetailCapture } from "./project-detail";
|
||||
import { projectsCapture } from "./projects";
|
||||
import { sessionDetailCapture } from "./session-detail";
|
||||
|
||||
const executor = new TaskExecutor({
|
||||
maxConcurrency: process.env['MAX_CONCURRENCY'] ? parseInt(process.env['MAX_CONCURRENCY']) : 10,
|
||||
// biome-ignore lint/complexity/useLiteralKeys: env var
|
||||
maxConcurrency: process.env["MAX_CONCURRENCY"]
|
||||
? // biome-ignore lint/complexity/useLiteralKeys: env var
|
||||
parseInt(process.env["MAX_CONCURRENCY"], 10)
|
||||
: 10,
|
||||
});
|
||||
|
||||
const tasks = [
|
||||
|
||||
@@ -3,102 +3,104 @@ import { ulid } from "ulid";
|
||||
export type Task = {
|
||||
key: string;
|
||||
execute: () => Promise<void>;
|
||||
}
|
||||
};
|
||||
|
||||
type TaskStatus = {
|
||||
id: string
|
||||
task: Task
|
||||
id: string;
|
||||
task: Task;
|
||||
} & (
|
||||
{
|
||||
status: 'pending' | 'completed' | 'failed'
|
||||
} | {
|
||||
status: 'running',
|
||||
promise: Promise<void>
|
||||
}
|
||||
)
|
||||
| {
|
||||
status: "pending" | "completed" | "failed";
|
||||
}
|
||||
| {
|
||||
status: "running";
|
||||
promise: Promise<void>;
|
||||
}
|
||||
);
|
||||
|
||||
type Options = {
|
||||
maxConcurrency: number
|
||||
}
|
||||
maxConcurrency: number;
|
||||
};
|
||||
|
||||
export class TaskExecutor {
|
||||
private taskStatuses: TaskStatus[] = []
|
||||
private taskStatuses: TaskStatus[] = [];
|
||||
private executionPromise?: {
|
||||
resolve: () => void
|
||||
reject: (reason?: unknown) => void
|
||||
promise: Promise<void>
|
||||
}
|
||||
private options: Options
|
||||
resolve: () => void;
|
||||
reject: (reason?: unknown) => void;
|
||||
promise: Promise<void>;
|
||||
};
|
||||
private options: Options;
|
||||
|
||||
constructor(options?: Partial<Options>) {
|
||||
this.options = {
|
||||
maxConcurrency: 10,
|
||||
...options,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private setExecutionPromise() {
|
||||
let resolveExecution: (() => void) | undefined
|
||||
let rejectExecution: ((reason?: unknown) => void) | undefined
|
||||
let resolveExecution: (() => void) | undefined;
|
||||
let rejectExecution: ((reason?: unknown) => void) | undefined;
|
||||
|
||||
const promise = new Promise<void>((resolve, reject) => {
|
||||
resolveExecution = resolve
|
||||
rejectExecution = reject
|
||||
})
|
||||
resolveExecution = resolve;
|
||||
rejectExecution = reject;
|
||||
});
|
||||
|
||||
if (resolveExecution === undefined || rejectExecution === undefined) {
|
||||
throw new Error('Illegal state: Promise not created')
|
||||
throw new Error("Illegal state: Promise not created");
|
||||
}
|
||||
|
||||
this.executionPromise = {
|
||||
resolve: resolveExecution,
|
||||
reject: rejectExecution,
|
||||
promise,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public setTasks(tasks: Task[]) {
|
||||
const newTaskStatuses: TaskStatus[] = tasks.map((task) => ({
|
||||
id: `${task.key}-${ulid()}`,
|
||||
status: 'pending',
|
||||
status: "pending",
|
||||
task,
|
||||
}))
|
||||
}));
|
||||
|
||||
this.taskStatuses.push(...newTaskStatuses)
|
||||
this.taskStatuses.push(...newTaskStatuses);
|
||||
}
|
||||
|
||||
private get pendingTasks() {
|
||||
return this.taskStatuses.filter((task) => task.status === 'pending')
|
||||
return this.taskStatuses.filter((task) => task.status === "pending");
|
||||
}
|
||||
|
||||
private get runningTasks() {
|
||||
return this.taskStatuses.filter((task) => task.status === 'running')
|
||||
return this.taskStatuses.filter((task) => task.status === "running");
|
||||
}
|
||||
|
||||
private updateStatus(id: string, status: TaskStatus) {
|
||||
const found = this.taskStatuses.find((task) => task.id === id)
|
||||
const found = this.taskStatuses.find((task) => task.id === id);
|
||||
|
||||
if (!found) {
|
||||
throw new Error(`Task not found: ${id}`)
|
||||
throw new Error(`Task not found: ${id}`);
|
||||
}
|
||||
|
||||
Object.assign(found, status)
|
||||
Object.assign(found, status);
|
||||
}
|
||||
|
||||
public async execute() {
|
||||
this.setExecutionPromise()
|
||||
this.refresh()
|
||||
await this.executionPromise?.promise
|
||||
this.setExecutionPromise();
|
||||
this.refresh();
|
||||
await this.executionPromise?.promise;
|
||||
}
|
||||
|
||||
private refresh() {
|
||||
if (this.runningTasks.length === 0 && this.pendingTasks.length === 0) {
|
||||
this.executionPromise?.resolve()
|
||||
console.log('execution completed.')
|
||||
this.executionPromise?.resolve();
|
||||
console.log("execution completed.");
|
||||
return;
|
||||
}
|
||||
|
||||
const remainingTaskCount = this.options.maxConcurrency - this.runningTasks.length
|
||||
const remainingTaskCount =
|
||||
this.options.maxConcurrency - this.runningTasks.length;
|
||||
|
||||
if (remainingTaskCount <= 0) {
|
||||
return;
|
||||
@@ -107,30 +109,30 @@ export class TaskExecutor {
|
||||
for (const task of this.pendingTasks.slice(0, remainingTaskCount)) {
|
||||
this.updateStatus(task.id, {
|
||||
id: task.id,
|
||||
status: 'running',
|
||||
status: "running",
|
||||
task: task.task,
|
||||
promise: (async () => {
|
||||
try {
|
||||
await task.task.execute()
|
||||
await task.task.execute();
|
||||
|
||||
this.updateStatus(task.id, {
|
||||
id: task.id,
|
||||
status: 'completed',
|
||||
status: "completed",
|
||||
task: task.task,
|
||||
})
|
||||
});
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
console.error(error);
|
||||
|
||||
this.updateStatus(task.id, {
|
||||
id: task.id,
|
||||
status: 'failed',
|
||||
status: "failed",
|
||||
task: task.task,
|
||||
})
|
||||
});
|
||||
} finally {
|
||||
this.refresh()
|
||||
this.refresh();
|
||||
}
|
||||
})(),
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import { resolve } from "node:path";
|
||||
import type { Page } from "playwright";
|
||||
import { testDevices } from "../testDevices";
|
||||
import { withPlaywright } from "../utils/withPlaywright";
|
||||
import { Task } from "./TaskExecutor";
|
||||
import type { Task } from "./TaskExecutor";
|
||||
|
||||
type CaptureCase = {
|
||||
name: string;
|
||||
|
||||
Reference in New Issue
Block a user