gh-legacy
Version:
A powerful GitHub CLI tool for automatic repository ownership transfer to trusted beneficiaries after periods of inactivity
123 lines (110 loc) • 4.73 kB
JavaScript
const { Command } = require('commander');
const program = new Command();
const { init } = require('../commands/init');
const { heartbeat } = require('../commands/heartbeat');
const { addBeneficiary } = require('../commands/addBeneficiary');
const { triggerAccess } = require('../commands/triggerAccess');
const { listBeneficiaries } = require('../commands/list');
const { resendEmail } = require('../commands/resendEmail');
const encryptToken = require('../encryptToken');
const readline = require('readline');
const os = require('os');
const { execSync } = require('child_process');
require('dotenv').config();
program
.name('gh-legacy')
.description('GitHub Legacy Access CLI - Repository Ownership Transfer System')
.version('0.1.0');
program
.command('init')
.description('Initialize configuration')
.action(init);
program
.command('heartbeat')
.description('Send a heartbeat signal to reset the inactivity timer')
.action(heartbeat);
program
.command('add-beneficiary')
.description('Add a trusted beneficiary for repository ownership transfer')
.argument('<repo>', 'GitHub repository (owner/repo)')
.argument('<email>', 'Beneficiary email address')
.argument('<githubUsername>', 'Beneficiary GitHub username')
.argument('<accessAfter>', 'Delay before granting access (e.g., "3 months", "1 year")')
.action((repo, email, githubUsername, accessAfter) => {
addBeneficiary({ repo, email, githubUsername, accessAfter });
});
program
.command('trigger-access')
.description('Evaluate and grant access to beneficiaries if conditions are met')
.option('--auto', 'Skip confirmation prompt')
.option('-d, --detail <repo>', 'Process only the specified repo (owner/repo)')
.action((options) => {
triggerAccess(options);
});
program
.command('auto-trigger')
.description('Automatically check and grant access without confirmation (for scheduling)')
.option('-d, --detail <repo>', 'Process only the specified repo (owner/repo)')
.action(async (options) => {
await triggerAccess({ ...options, auto: true });
if (options.detail) {
// OS detection and scheduling
const platform = os.platform();
let scheduleCmd = '';
let scheduleMsg = '';
let interval = 1; // Default interval in minutes, now set to 1
if (platform === 'win32') {
// Windows: use schtasks
const taskName = `GH-Legacy Auto Trigger - ${options.detail.replace('/', '-')}`;
scheduleCmd = `schtasks /create /tn "${taskName}" /tr "gh-legacy auto-trigger -d ${options.detail}" /sc minute /mo ${interval}`;
scheduleMsg = `Scheduled Windows Task: ${taskName} to run every ${interval} minutes.`;
} else if (platform === 'linux' || platform === 'darwin') {
// Linux/Mac: use crontab
const cronLine = `*/${interval} * * * * gh-legacy auto-trigger -d ${options.detail}`;
scheduleCmd = `echo "${cronLine}" | crontab -l 2>/dev/null | grep -v 'gh-legacy auto-trigger -d ${options.detail}' ; echo "${cronLine}" | crontab -`;
scheduleMsg = `Added to crontab: ${cronLine}`;
}
const readline = require('readline');
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
rl.question(`\nWould you like to schedule this command to run automatically every ${interval} minutes? (Y/n) `, (answer) => {
if (answer.trim().toLowerCase() === 'y' || answer.trim() === '') {
try {
execSync(scheduleCmd, { stdio: 'inherit', shell: true });
console.log(`\n✅ ${scheduleMsg}`);
} catch (err) {
console.error('❌ Failed to schedule the task automatically. Please try manually.');
}
} else {
console.log('Skipping automatic scheduling.');
}
rl.close();
});
}
});
program
.command('resend-email')
.description('Resend emails to granted beneficiaries with updated template')
.action(resendEmail);
program
.command('list')
.description('List configured beneficiaries with detailed status')
.action(listBeneficiaries);
program
.command('status')
.description('Show current system status and pending transfers')
.action(listBeneficiaries);
program
.command('token')
.description('Configure your GitHub token for gh-legacy')
.action(() => {
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
rl.question('Enter your GitHub token: ', (token) => {
encryptToken(token);
rl.close();
});
});
program.parse();