mirror of
https://github.com/lobehub/lobehub.git
synced 2026-09-20 04:56:13 +08:00
8bf9734dfb
* ✨ feat(task-dock): promote the upload dock into an app-level task dock Background work of every kind now shares one dock instead of the uploads-only one mounted inside the resource manager. - `features/TaskDock` renders a `DockTask[]` collected from producer hooks; producers own their copy, actions and results. - One task renders as a result card, two or more as a panel grouped by producer. The shape follows the task count and waits 400ms before shrinking so a burst of dismissals cannot morph it repeatedly. - A finished task with nothing to hand back clears itself after 3s; one that left a result waits for the user, and a failure always does. - File uploads keep their store untouched and are adapted into tasks; `business/client/features/DockTasks` lets a distribution add its own. - Mounted in `SPAGlobalProvider`, so the dock outlives the page that started the work. Claude-Session: https://claude.ai/code/session_014iyxmqssnrPopmKV1xKJ7k * 🐛 fix(task-dock): batch a producer's cancel-all and label the expand toggle - `DockTask.groupCancel` lets a producer cancel its whole set in one operation. Walking `cancel` per task turned a folder upload's batched cancel into one full-list update per file. - The header toggle said "Collapse" while collapsed, i.e. the opposite of what it does. Claude-Session: https://claude.ai/code/session_014iyxmqssnrPopmKV1xKJ7k * 🐛 fix(task-dock): lazy-load the dock and turn the size gate into a review The dock pulled the upload/file chunks into the first-screen static graph; it now loads through `lazy()` like the other global hosts. The web and ASAR size gates no longer fail their jobs. A failing gate submits a REQUEST_CHANGES review from github-actions that links the report comment, updates it while still failing, and dismisses it once the gate passes again. Claude-Session: https://claude.ai/code/session_01BBCjqExuP6Ux5PRVJbU2ru
86 lines
2.5 KiB
JavaScript
86 lines
2.5 KiB
JavaScript
const assert = require('node:assert/strict');
|
|
const { test } = require('node:test');
|
|
|
|
const sizeGateComment = require('./size-gate-comment.cjs');
|
|
|
|
const MARKER = '<!-- SIZE-GATE-REVIEW-web -->';
|
|
|
|
const fakeGithub = ({ comments = [], reviews = [] } = {}) => {
|
|
const calls = [];
|
|
const record =
|
|
(name, data = {}) =>
|
|
async (params) => {
|
|
calls.push({ name, params });
|
|
return { data };
|
|
};
|
|
return {
|
|
calls,
|
|
paginate: async (fn, params) => (await fn(params)).data,
|
|
rest: {
|
|
issues: {
|
|
createComment: record('createComment', { id: 42 }),
|
|
listComments: record('listComments', comments),
|
|
updateComment: record('updateComment'),
|
|
},
|
|
pulls: {
|
|
createReview: record('createReview', { id: 7 }),
|
|
dismissReview: record('dismissReview'),
|
|
listReviews: record('listReviews', reviews),
|
|
updateReview: record('updateReview'),
|
|
},
|
|
},
|
|
};
|
|
};
|
|
|
|
const run = (github, failed) =>
|
|
sizeGateComment({
|
|
context: { repo: { owner: 'o', repo: 'r' } },
|
|
failed,
|
|
github,
|
|
identifier: 'web',
|
|
issueNumber: 1,
|
|
report: 'report',
|
|
title: 'Web dist',
|
|
});
|
|
|
|
test('a failing gate requests changes once and links the report comment', async () => {
|
|
const github = fakeGithub();
|
|
await run(github, true);
|
|
const review = github.calls.find((c) => c.name === 'createReview');
|
|
assert.equal(review.params.event, 'REQUEST_CHANGES');
|
|
assert.ok(review.params.body.includes(MARKER));
|
|
assert.ok(review.params.body.includes('#issuecomment-42'));
|
|
});
|
|
|
|
test('a still-failing gate updates the open review instead of stacking another', async () => {
|
|
const github = fakeGithub({
|
|
reviews: [{ body: `${MARKER} old`, id: 9, state: 'CHANGES_REQUESTED' }],
|
|
});
|
|
await run(github, true);
|
|
assert.equal(
|
|
github.calls.some((c) => c.name === 'createReview'),
|
|
false,
|
|
);
|
|
assert.equal(github.calls.find((c) => c.name === 'updateReview').params.review_id, 9);
|
|
});
|
|
|
|
test('a passing gate dismisses only its own open review', async () => {
|
|
const github = fakeGithub({
|
|
reviews: [
|
|
{ body: `${MARKER} old`, id: 9, state: 'CHANGES_REQUESTED' },
|
|
{ body: 'human review', id: 10, state: 'CHANGES_REQUESTED' },
|
|
{ body: `${MARKER} done`, id: 11, state: 'DISMISSED' },
|
|
],
|
|
});
|
|
await run(github, false);
|
|
const dismissed = github.calls.filter((c) => c.name === 'dismissReview');
|
|
assert.deepEqual(
|
|
dismissed.map((c) => c.params.review_id),
|
|
[9],
|
|
);
|
|
assert.equal(
|
|
github.calls.some((c) => c.name === 'createReview'),
|
|
false,
|
|
);
|
|
});
|