Files
antigravity-skills-reference/tools/scripts/apply_skill_optimization.cjs

212 lines
5.8 KiB
JavaScript

#!/usr/bin/env node
const fs = require('node:fs');
const path = require('node:path');
const { execFileSync } = require('node:child_process');
const REVIEW_HEADING = '## Tessl Skill Review';
function getRequiredEnv(name) {
const value = process.env[name];
if (!value) {
throw new Error(`${name} is required`);
}
return value;
}
async function githubRequest(pathname, options = {}) {
const token = getRequiredEnv('GITHUB_TOKEN');
const response = await fetch(`https://api.github.com${pathname}`, {
...options,
headers: {
Accept: 'application/vnd.github+json',
Authorization: `Bearer ${token}`,
'User-Agent': 'antigravity-awesome-skills/apply-skill-optimization',
...(options.headers || {}),
},
});
if (!response.ok) {
const text = await response.text();
throw new Error(`GitHub API ${pathname} failed (${response.status}): ${text}`);
}
if (response.status === 204) {
return null;
}
return response.json();
}
function runGit(args, options = {}) {
return execFileSync('git', args, {
cwd: process.cwd(),
encoding: 'utf8',
stdio: ['ignore', 'pipe', 'pipe'],
...options,
});
}
function extractKeyImprovements(body) {
const section = body.match(/\*\*Key improvements:\*\*\n((?:- .+\n?)+)/);
if (!section) {
return [];
}
return [...section[1].matchAll(/^- (.+)$/gm)].map((match) => match[1]);
}
function extractOptimizedContent(body) {
const sections = new Map();
const normalized = body.replace(/\r\n/g, '\n');
const regex =
/### `([^`]+)`[\s\S]*?View full optimized SKILL\.md[\s\S]*?```markdown\n([\s\S]*?)\n```/g;
let match;
while ((match = regex.exec(normalized)) !== null) {
const skillPath = match[1];
const content = match[2].replace(/` ` `/g, '```');
sections.set(skillPath, content);
}
return sections;
}
function ensureRepoRelative(filePath) {
const cwd = process.cwd();
const resolved = path.resolve(cwd, filePath);
const relative = path.relative(cwd, resolved);
if (relative.startsWith('..') || path.isAbsolute(relative)) {
throw new Error(`Path traversal detected: ${filePath}`);
}
if (!filePath.endsWith('SKILL.md')) {
throw new Error(`Unexpected file path (expected SKILL.md): ${filePath}`);
}
return resolved;
}
async function findLatestReviewComment(owner, repo, prNumber) {
let page = 1;
let latest = null;
while (true) {
const comments = await githubRequest(
`/repos/${owner}/${repo}/issues/${prNumber}/comments?per_page=100&page=${page}`,
);
for (const comment of comments) {
if (comment.body && comment.body.includes(REVIEW_HEADING)) {
latest = comment;
}
}
if (comments.length < 100) {
return latest;
}
page += 1;
}
}
async function postComment(owner, repo, prNumber, body) {
await githubRequest(`/repos/${owner}/${repo}/issues/${prNumber}/comments`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ body }),
});
}
async function main() {
const repoSlug = getRequiredEnv('GITHUB_REPOSITORY');
const [owner, repo] = repoSlug.split('/');
const prNumber = process.env.PR_NUMBER || JSON.parse(
fs.readFileSync(getRequiredEnv('GITHUB_EVENT_PATH'), 'utf8'),
).inputs?.pr_number;
if (!prNumber) {
throw new Error('PR_NUMBER or workflow_dispatch input pr_number is required');
}
const pr = await githubRequest(`/repos/${owner}/${repo}/pulls/${prNumber}`);
if (pr.head.repo.full_name !== repoSlug) {
throw new Error(
'Auto-apply is only supported for PR branches that live in the base repository.',
);
}
const reviewComment = await findLatestReviewComment(owner, repo, prNumber);
if (!reviewComment || !reviewComment.body) {
throw new Error('No Tessl skill review comment found on this PR. Run the review first.');
}
const optimizedFiles = extractOptimizedContent(reviewComment.body);
if (optimizedFiles.size === 0) {
throw new Error('No optimized SKILL.md content found in the latest Tessl review comment.');
}
const branch = pr.head.ref;
console.log(`Applying optimization to PR #${prNumber} on ${branch}`);
runGit(['fetch', 'origin', branch]);
runGit(['checkout', '-B', branch, `origin/${branch}`]);
for (const [filePath, content] of optimizedFiles.entries()) {
const resolved = ensureRepoRelative(filePath);
fs.writeFileSync(resolved, content);
console.log(`Updated ${filePath}`);
}
runGit(['config', 'user.name', 'tessl-skill-review[bot]']);
runGit(['config', 'user.email', 'skill-review[bot]@users.noreply.github.com']);
runGit(['add', ...optimizedFiles.keys()]);
let committed = true;
try {
runGit(['commit', '-m', 'Apply optimized SKILL.md from Tessl review']);
} catch (error) {
const output = `${error.stdout || ''}\n${error.stderr || ''}`;
if (output.includes('nothing to commit')) {
committed = false;
} else {
throw error;
}
}
if (!committed) {
await postComment(
owner,
repo,
prNumber,
'⚠️ No changes to apply. The PR branch already matches the latest Tessl optimization.',
);
return;
}
runGit(['push', 'origin', `HEAD:${branch}`]);
const shortSha = runGit(['rev-parse', '--short', 'HEAD']).trim();
const updatedFiles = [...optimizedFiles.keys()].map((item) => `\`${item}\``).join(', ');
const improvements = extractKeyImprovements(reviewComment.body);
let body = `✅ Applied optimized ${updatedFiles} (${shortSha}).`;
if (improvements.length > 0) {
body += '\n\n**What changed:**';
for (const item of improvements.slice(0, 3)) {
body += `\n- ${item}`;
}
}
await postComment(owner, repo, prNumber, body);
}
main().catch((error) => {
console.error(error instanceof Error ? error.stack : String(error));
process.exitCode = 1;
});