delqhi/sin-github-issues
0
1#!/usr/bin/env node2 3import { execFile } from 'node:child_process';4import { promisify } from 'node:util';5 6const execFileAsync = promisify(execFile);7 8function parseArgs(argv) {9 const out = {};10 for (let i = 0; i < argv.length; i += 1) {11 const token = argv[i];12 if (!token.startsWith('--')) continue;13 const key = token.slice(2);14 const next = argv[i + 1];15 if (!next || next.startsWith('--')) {16 out[key] = 'true';17 continue;18 }19 out[key] = next;20 i += 1;21 }22 return out;23}24 25async function safeGh(args) {26 try {27 const { stdout } = await execFileAsync('gh', args, { cwd: process.cwd() });28 return { ok: true, stdout };29 } catch (error) {30 return { ok: false, error: error instanceof Error ? error.message : String(error) };31 }32}33 34async function main() {35 const args = parseArgs(process.argv.slice(2));36 const repo = args.repo || 'Delqhi/sin-github-issues';37 const workflow = args.workflow || '.github/workflows/deploy-huggingface-space.yml';38 39 const repoMeta = await safeGh(['repo', 'view', repo, '--json', 'name,isPrivate,url,defaultBranchRef']);40 const secrets = await safeGh(['secret', 'list', '-R', repo, '--json', 'name,updatedAt,visibility']);41 const workflows = await safeGh(['workflow', 'list', '-R', repo, '--json', 'name,path,state,id']);42 const runs = await safeGh(['run', 'list', '-R', repo, '--workflow', workflow, '--limit', '3', '--json', 'databaseId,status,conclusion,headSha,createdAt,name,workflowName,url,jobs']);43 44 const parsedSecrets = secrets.ok ? JSON.parse(secrets.stdout || '[]') : [];45 const parsedWorkflows = workflows.ok ? JSON.parse(workflows.stdout || '[]') : [];46 const parsedRuns = runs.ok ? JSON.parse(runs.stdout || '[]') : [];47 const hasHfTokenSecret = parsedSecrets.some((entry) => entry.name === 'HF_TOKEN');48 const deployWorkflow = parsedWorkflows.find((entry) => entry.path === workflow || entry.name === workflow || entry.name === 'Deploy Hugging Face Space');49 const latestRun = parsedRuns[0] || null;50 51 const failures = [];52 if (!repoMeta.ok) failures.push('repo_view_failed');53 if (!secrets.ok) failures.push('secret_list_failed');54 if (!workflows.ok) failures.push('workflow_list_failed');55 if (!deployWorkflow) failures.push('deploy_workflow_missing');56 if (!hasHfTokenSecret) failures.push('hf_token_secret_missing');57 if (latestRun && latestRun.conclusion === 'failure' && Array.isArray(latestRun.jobs) && latestRun.jobs.length === 0) {58 failures.push('latest_deploy_run_failed_without_jobs');59 }60 61 const output = {62 ok: failures.length === 0,63 repo,64 workflow,65 repoMeta: repoMeta.ok ? JSON.parse(repoMeta.stdout) : { error: repoMeta.error },66 hasHfTokenSecret,67 deployWorkflow: deployWorkflow || null,68 latestRun,69 failures,70 };71 72 console.log(JSON.stringify(output, null, 2));73 if (failures.length > 0) process.exitCode = 1;74}75 76main().catch((error) => {77 console.error(error instanceof Error ? error.message : String(error));78 process.exit(1);79});80 