feat: sync triage skill files
This commit is contained in:
+20
-6
@@ -4,6 +4,16 @@ import path from 'path';
|
||||
import { GITEA_SERVER_URL, GITEA_REPOSITORY, GITEA_TOKEN, PR_HEAD_BRANCH, FINDINGS_PATH } from './config.js';
|
||||
|
||||
const remoteUrl = `${GITEA_SERVER_URL.replace(/\/$/, '')}/${GITEA_REPOSITORY}.git`;
|
||||
const SYNC_PATHS = [
|
||||
FINDINGS_PATH,
|
||||
'.amazonq/rules/triage-findings.md',
|
||||
'.claude/skills/triage-findings/SKILL.md',
|
||||
'.gemini/skills/triage-findings/SKILL.md',
|
||||
'.github/copilot-instructions.md',
|
||||
'.github/skills/triage-findings/SKILL.md',
|
||||
'CLAUDE.md',
|
||||
'GEMINI.md',
|
||||
];
|
||||
|
||||
function makeRunner(spawn) {
|
||||
return function run(args, cwd, env) {
|
||||
@@ -55,16 +65,20 @@ export async function commitAndPush(workspace, repoDir, _spawnSync = spawnSync)
|
||||
run(['config', 'user.email', 'ai-review[bot]@gitea'], repoDir);
|
||||
run(['config', 'user.name', 'AI Review Bot'], repoDir);
|
||||
|
||||
const srcFindings = path.join(workspace, FINDINGS_PATH);
|
||||
const destFindings = path.join(repoDir, FINDINGS_PATH);
|
||||
fs.mkdirSync(path.dirname(destFindings), { recursive: true });
|
||||
fs.copyFileSync(srcFindings, destFindings);
|
||||
// Always copy source files over the repo copy so skill files stay in sync.
|
||||
for (const relPath of SYNC_PATHS) {
|
||||
const src = path.join(workspace, relPath);
|
||||
const dest = path.join(repoDir, relPath);
|
||||
if (!fs.existsSync(src)) continue;
|
||||
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
||||
fs.copyFileSync(src, dest);
|
||||
}
|
||||
|
||||
run(['add', FINDINGS_PATH], repoDir);
|
||||
run(['add', ...SYNC_PATHS], repoDir);
|
||||
|
||||
const status = run(['status', '--porcelain'], repoDir);
|
||||
if (!status) {
|
||||
console.log(' findings.json 無變更,跳過 commit');
|
||||
console.log(' sync files 無變更,跳過 commit');
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
+41
-4
@@ -10,10 +10,21 @@ function makeTmpWorkspace() {
|
||||
const ws = fs.mkdtempSync(path.join(os.tmpdir(), 'git-test-'));
|
||||
// Pre-create repo dir so clone branch is skipped
|
||||
fs.mkdirSync(path.join(ws, 'repo'), { recursive: true });
|
||||
// Create a findings.json to copy
|
||||
const findingsDir = path.join(ws, '.gitea/ai-review');
|
||||
fs.mkdirSync(findingsDir, { recursive: true });
|
||||
fs.writeFileSync(path.join(findingsDir, 'findings.json'), '[]');
|
||||
const files = [
|
||||
'.gitea/ai-review/findings.json',
|
||||
'.amazonq/rules/triage-findings.md',
|
||||
'.claude/skills/triage-findings/SKILL.md',
|
||||
'.gemini/skills/triage-findings/SKILL.md',
|
||||
'.github/copilot-instructions.md',
|
||||
'.github/skills/triage-findings/SKILL.md',
|
||||
'CLAUDE.md',
|
||||
'GEMINI.md',
|
||||
];
|
||||
for (const relPath of files) {
|
||||
const fullPath = path.join(ws, relPath);
|
||||
fs.mkdirSync(path.dirname(fullPath), { recursive: true });
|
||||
fs.writeFileSync(fullPath, relPath);
|
||||
}
|
||||
return ws;
|
||||
}
|
||||
|
||||
@@ -85,6 +96,32 @@ describe('commitAndPush', () => {
|
||||
assert.equal(commitCalled, false, 'commit should not run when there are no changes');
|
||||
});
|
||||
|
||||
it('adds skill and entry files together with findings', async () => {
|
||||
const spawn = makeSpawn();
|
||||
await commitAndPush(workspace, path.join(workspace, 'repo'), spawn);
|
||||
const addCall = spawn.calls.find(c => c.args[0] === 'add');
|
||||
assert.ok(addCall, 'expected git add to run');
|
||||
assert.ok(addCall.args.includes('.github/skills/triage-findings/SKILL.md'));
|
||||
assert.ok(addCall.args.includes('.claude/skills/triage-findings/SKILL.md'));
|
||||
assert.ok(addCall.args.includes('.gemini/skills/triage-findings/SKILL.md'));
|
||||
assert.ok(addCall.args.includes('.github/copilot-instructions.md'));
|
||||
assert.ok(addCall.args.includes('.amazonq/rules/triage-findings.md'));
|
||||
assert.ok(addCall.args.includes('CLAUDE.md'));
|
||||
assert.ok(addCall.args.includes('GEMINI.md'));
|
||||
assert.ok(!addCall.args.includes('README.md'));
|
||||
});
|
||||
|
||||
it('overwrites existing repo copies with workspace files', async () => {
|
||||
const repoDir = path.join(workspace, 'repo');
|
||||
fs.writeFileSync(path.join(repoDir, '.github/skills/triage-findings/SKILL.md'), 'stale');
|
||||
fs.writeFileSync(path.join(repoDir, 'CLAUDE.md'), 'stale');
|
||||
|
||||
await commitAndPush(workspace, repoDir, makeSpawn());
|
||||
|
||||
assert.equal(fs.readFileSync(path.join(repoDir, '.github/skills/triage-findings/SKILL.md'), 'utf8'), '.github/skills/triage-findings/SKILL.md');
|
||||
assert.equal(fs.readFileSync(path.join(repoDir, 'CLAUDE.md'), 'utf8'), 'CLAUDE.md');
|
||||
});
|
||||
|
||||
it('does not throw when git command fails', async () => {
|
||||
const failSpawn = () => ({ status: 1, stdout: '', stderr: 'fatal: error', error: null });
|
||||
await assert.doesNotReject(() => commitAndPush(workspace, path.join(workspace, 'repo'), failSpawn));
|
||||
|
||||
Reference in New Issue
Block a user