feat: force overwrite core instruction files

This commit is contained in:
2026-05-18 02:50:47 +00:00
parent b51ab78a5e
commit b4c54124ec
2 changed files with 28 additions and 7 deletions
+24 -7
View File
@@ -20,6 +20,11 @@ export const SYNC_PATHS = [
'CLAUDE.md', 'CLAUDE.md',
'GEMINI.md', 'GEMINI.md',
]; ];
const FORCE_SYNC_FILE_PATHS = [
'.github/copilot-instructions.md',
'CLAUDE.md',
'GEMINI.md',
];
const SYNC_TREE_PATHS = [ const SYNC_TREE_PATHS = [
'.codex/skills/triage-findings', '.codex/skills/triage-findings',
'.claude/skills/triage-findings', '.claude/skills/triage-findings',
@@ -77,6 +82,15 @@ function copyTree(sourceRoot, repoDir, relDir) {
return copied; return copied;
} }
function copyFileOverwrite(sourceRoot, repoDir, relPath) {
const src = path.join(sourceRoot, relPath);
if (!fs.existsSync(src)) return null;
const dest = path.join(repoDir, relPath);
fs.mkdirSync(path.dirname(dest), { recursive: true });
fs.copyFileSync(src, dest);
return relPath;
}
export function getRepoState(repoDir, _spawnSync = spawnSync) { export function getRepoState(repoDir, _spawnSync = spawnSync) {
const run = makeRunner(_spawnSync); const run = makeRunner(_spawnSync);
const headSha = readGitOutput(run, ['rev-parse', 'HEAD'], repoDir); const headSha = readGitOutput(run, ['rev-parse', 'HEAD'], repoDir);
@@ -137,15 +151,18 @@ export async function commitAndPush(workspace, repoDir, _spawnSync = spawnSync,
} }
} }
// Force overwrite the direct instruction files first so the target repo always
// receives the action-owned versions even if the repo has drifted.
for (const relPath of FORCE_SYNC_FILE_PATHS) {
const copied = copyFileOverwrite(sourceRoot, repoDir, relPath);
if (copied) existingSyncPaths.add(copied);
}
// Copy standalone action files into the target repo. Existing files are overwritten. // Copy standalone action files into the target repo. Existing files are overwritten.
for (const relPath of SYNC_PATHS) { for (const relPath of SYNC_PATHS) {
const src = path.join(sourceRoot, relPath); if (FORCE_SYNC_FILE_PATHS.includes(relPath)) continue;
const dest = path.join(repoDir, relPath); const copied = copyFileOverwrite(sourceRoot, repoDir, relPath);
if (fs.existsSync(src)) { if (copied) existingSyncPaths.add(copied);
fs.mkdirSync(path.dirname(dest), { recursive: true });
fs.copyFileSync(src, dest);
existingSyncPaths.add(relPath);
}
} }
if (existingSyncPaths.size > 0) { if (existingSyncPaths.size > 0) {
+4
View File
@@ -159,11 +159,15 @@ describe('commitAndPush', () => {
const repoDir = path.join(workspace, 'repo'); const repoDir = path.join(workspace, 'repo');
fs.writeFileSync(path.join(repoDir, '.github/skills/triage-findings/SKILL.md'), 'stale'); fs.writeFileSync(path.join(repoDir, '.github/skills/triage-findings/SKILL.md'), 'stale');
fs.writeFileSync(path.join(repoDir, 'CLAUDE.md'), 'stale'); fs.writeFileSync(path.join(repoDir, 'CLAUDE.md'), 'stale');
fs.writeFileSync(path.join(repoDir, 'GEMINI.md'), 'stale');
fs.writeFileSync(path.join(repoDir, '.github/copilot-instructions.md'), 'stale');
await commitAndPush(workspace, repoDir, makeSpawn(), sourceRoot); await commitAndPush(workspace, repoDir, makeSpawn(), sourceRoot);
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, '.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'); assert.equal(fs.readFileSync(path.join(repoDir, 'CLAUDE.md'), 'utf8'), 'CLAUDE.md');
assert.equal(fs.readFileSync(path.join(repoDir, 'GEMINI.md'), 'utf8'), 'GEMINI.md');
assert.equal(fs.readFileSync(path.join(repoDir, '.github/copilot-instructions.md'), 'utf8'), '.github/copilot-instructions.md');
}); });
it('recursively overwrites skill tree files from the action source', async () => { it('recursively overwrites skill tree files from the action source', async () => {