ubon
Version:
Security scanner for AI-generated apps (Cursor, Lovable, Windsurf, v0). Catches hardcoded secrets, prompt injection, hallucinated imports, Server Actions / Edge runtime mistakes, and the vibe-coded vulnerabilities traditional linters miss.
97 lines • 3.92 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.getChangedFilesSince = getChangedFilesSince;
exports.getRecentCommitHashes = getRecentCommitHashes;
exports.ensureGitRepo = ensureGitRepo;
exports.createBranchCommitPush = createBranchCommitPush;
exports.tryOpenPullRequest = tryOpenPullRequest;
const child_process_1 = require("child_process");
function getChangedFilesSince(ref, cwd) {
try {
const out = (0, child_process_1.execFileSync)('git', ['diff', '--name-only', ref], { cwd, encoding: 'utf8' });
return out.split('\n').map(s => s.trim()).filter(Boolean);
}
catch {
return [];
}
}
function getRecentCommitHashes(depth, cwd) {
try {
const out = (0, child_process_1.execFileSync)('git', ['rev-list', `--max-count=${depth}`, 'HEAD'], { cwd, encoding: 'utf8' });
return out.split('\n').map(s => s.trim()).filter(Boolean);
}
catch {
return [];
}
}
function ensureGitRepo(cwd) {
try {
(0, child_process_1.execFileSync)('git', ['rev-parse', '--is-inside-work-tree'], { cwd, stdio: 'ignore' });
return true;
}
catch {
return false;
}
}
function isValidBranchName(branch) {
const res = (0, child_process_1.spawnSync)('git', ['check-ref-format', '--branch', branch], {
encoding: 'utf8',
stdio: 'ignore'
});
return res.status === 0;
}
function createBranchCommitPush(options) {
const base = options.baseBranch || 'main';
const branch = options.featureBranch;
if (!isValidBranchName(branch))
return { pushed: false };
try {
// Ensure up-to-date
try {
(0, child_process_1.execFileSync)('git', ['fetch', '--all', '--prune'], { cwd: options.cwd, stdio: 'ignore' });
}
catch { }
// Create and switch to feature branch
(0, child_process_1.execFileSync)('git', ['checkout', '-B', branch, base], { cwd: options.cwd, stdio: 'inherit' });
// Stage and commit
(0, child_process_1.execFileSync)('git', ['add', '-A'], { cwd: options.cwd, stdio: 'inherit' });
// If nothing to commit, skip commit step
try {
(0, child_process_1.execFileSync)('git', ['commit', '-m', options.title], { cwd: options.cwd, stdio: 'inherit' });
}
catch { }
// Push branch
(0, child_process_1.execFileSync)('git', ['push', '-u', 'origin', branch], { cwd: options.cwd, stdio: 'inherit' });
// Get repo url
const remote = (0, child_process_1.execFileSync)('git', ['config', '--get', 'remote.origin.url'], { cwd: options.cwd, encoding: 'utf8' }).trim();
const remoteUrl = remote.replace(/^git@github.com:/, 'https://github.com/').replace(/\.git$/, '');
return { pushed: true, remoteUrl };
}
catch {
return { pushed: false };
}
}
function tryOpenPullRequest(cwd, base, head, title, body) {
// Try with GitHub CLI if available
try {
(0, child_process_1.execFileSync)('gh', ['--version'], { cwd, stdio: 'ignore' });
const args = ['pr', 'create', '-B', base, '-H', head, '-t', title];
if (body)
args.push('-b', body);
(0, child_process_1.execFileSync)('gh', args, { cwd, stdio: 'inherit' });
// Best-effort; URL is printed by gh
return { created: true };
}
catch { }
// Fallback: provide compare URL
try {
const remote = (0, child_process_1.execFileSync)('git', ['config', '--get', 'remote.origin.url'], { cwd, encoding: 'utf8' }).trim();
const remoteUrl = remote.replace(/^git@github.com:/, 'https://github.com/').replace(/\.git$/, '');
const url = `${remoteUrl}/compare/${base}...${head}?expand=1&title=${encodeURIComponent(title)}`;
return { created: false, url };
}
catch {
return { created: false };
}
}
//# sourceMappingURL=git.js.map