UNPKG

@capgo/cli

Version:
88 lines (87 loc) 4.45 kB
import type { BuildCredentials } from '../../schemas/build.js'; export type CiSecretProvider = 'github' | 'gitlab'; export interface CiSecretEntry { key: string; value: string; masked: boolean; } export interface CiSecretTarget { provider: CiSecretProvider; label: string; cli: 'gh' | 'glab'; } export interface CiSecretDiscovery { targets: CiSecretTarget[]; setup: CiSecretSetupAdvice[]; notes: string[]; } export interface CiSecretSetupAdvice { target: CiSecretTarget; reason: 'not-installed' | 'not-authenticated'; message: string; commands: string[]; } interface CommandRunOptions { input?: string; } export interface CommandRunResult { status: number | null; stdout: string; stderr: string; error?: Error; } export type CommandRunner = (command: string, args: string[], options?: CommandRunOptions) => CommandRunResult; /** * Async runner. Used by the wizard so spawned `gh` / `glab` calls don't block * the Node event loop — without this, `ink-spinner`'s animation freezes for * the entire duration of every shell-out, which feels like the wizard has hung. * * Tests can pass either a sync (CommandRunner) or async runner — every helper * that calls runner.* does so via `await` so a sync runner returning a plain * result still works (Promise.resolve coerces it). */ export type AsyncCommandRunner = (command: string, args: string[], options?: CommandRunOptions) => CommandRunResult | Promise<CommandRunResult>; export declare function runCommand(command: string, args: string[], options?: CommandRunOptions): CommandRunResult; /** * Non-blocking shell-out. Mirrors `runCommand`'s shape but uses `spawn` so * the Node event loop is free to tick spinners and process input while gh / * glab work. Default for any wizard-side helper that needs to render UI * during the call. */ export declare function runCommandAsync(command: string, args: string[], options?: CommandRunOptions): Promise<CommandRunResult>; export declare function createCiSecretEntries(credentials: Partial<BuildCredentials>, apiKey?: string): CiSecretEntry[]; export declare function detectCiSecretTargets(runner?: CommandRunner): CiSecretDiscovery; export declare function getCiSecretTargetLabel(target: CiSecretTarget | null | undefined): string; /** * Resolve the concrete `owner/repo` (GitHub) or `group/project` (GitLab) the * `gh` / `glab` CLI will target from the current working directory. * * Returns null when the CLI can't determine the repo (e.g. cwd is not a git * repo, multiple remotes with no `gh-resolved` config, auth scopes missing). * * The wizard MUST show this string to the user and require explicit * confirmation before any `gh secret set` / `glab variable set` runs — those * commands silently overwrite without backup, so the user has to know which * repo they're about to mutate. */ export declare function getCiSecretRepoLabel(target: CiSecretTarget, runner?: CommandRunner): string | null; /** * Non-blocking variant of `getCiSecretRepoLabel`. Identical logic, but * `await`s the runner so the event loop can tick during the gh/glab call — * lets Ink spinners actually animate during the resolution. */ export declare function getCiSecretRepoLabelAsync(target: CiSecretTarget, runner?: AsyncCommandRunner): Promise<string | null>; export declare function listExistingCiSecretKeys(target: CiSecretTarget, keys: string[], runner?: CommandRunner): string[]; /** Non-blocking variant of `listExistingCiSecretKeys`. */ export declare function listExistingCiSecretKeysAsync(target: CiSecretTarget, keys: string[], runner?: AsyncCommandRunner): Promise<string[]>; export declare function uploadCiSecrets(target: CiSecretTarget, entries: CiSecretEntry[], existingKeys?: string[], runner?: CommandRunner): void; /** * Non-blocking variant of `uploadCiSecrets`. Calls `onProgress(current, total, * keyName)` before every `gh secret set` / `glab variable set` so the wizard * can render "Pushing N of M: <KEY>…" instead of a frozen spinner. * * Pushes are still sequential — gh/glab don't have a bulk-set API, and * parallelising would risk rate limits + makes failure semantics ambiguous. */ export declare function uploadCiSecretsAsync(target: CiSecretTarget, entries: CiSecretEntry[], existingKeys?: string[], runner?: AsyncCommandRunner, onProgress?: (current: number, total: number, keyName: string) => void): Promise<void>; export {};