From 0b465c8e57a1835b1bc5d991d9ca1c493d21aa19 Mon Sep 17 00:00:00 2001 From: Greg Huels Date: Mon, 20 Jul 2026 14:28:41 -0500 Subject: [PATCH] fix: add checkmark prefix to created/synced output lines and fix progress bar counter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Prefix successful Created/Synced output lines with a green ✓ - Progress bar ✓ counter now tracks both created and synced flags (renamed field to `saved`) Co-Authored-By: Claude Sonnet 4.6 (1M context) --- src/components/MigrationRunner.tsx | 10 +++++----- src/eppo/migrate.tsx | 10 +++++----- src/launchdarkly/migrate.tsx | 10 +++++----- tests/migration-runner.test.tsx | 4 ++-- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/components/MigrationRunner.tsx b/src/components/MigrationRunner.tsx index 5b10130..42689e8 100644 --- a/src/components/MigrationRunner.tsx +++ b/src/components/MigrationRunner.tsx @@ -10,7 +10,7 @@ const MAX_SETTLED = 500; export type SettleStatus = 'created' | 'synced' | 'skipped' | 'failed'; export type ProgressBarStats = { - created: number; + saved: number; skipped: number; failed: number; retrying?: number; @@ -48,9 +48,9 @@ type ViewState = { function renderBarLine(state: ViewState): string { const { value, total, stats, eta, columns } = state; - const { created, skipped, failed, retrying } = stats; + const { saved, skipped, failed, retrying } = stats; const pct = total === 0 ? 0 : Math.round((value / total) * 100); - const suffixPlain = ` ${value}/${total} · ${pct}% · ✓ ${created} ⚠ ${skipped} ✗ ${failed} ⏳ ${retrying} · ETA ${eta}`; + const suffixPlain = ` ${value}/${total} · ${pct}% · ✓ ${saved} ⚠ ${skipped} ✗ ${failed} ⏳ ${retrying} · ETA ${eta}`; const barWidth = Math.max(5, Math.min(30, columns - suffixPlain.length - 4)); const filled = total === 0 @@ -65,7 +65,7 @@ function renderBarLine(state: ViewState): string { chalk.yellow(`${pct}%`) + chalk.gray(' · ') + chalk.green('✓') + - ` ${created} ` + + ` ${saved} ` + chalk.yellow('⚠') + ` ${skipped} ` + chalk.red('✗') + @@ -130,7 +130,7 @@ export function migrationRunner(opts: { total: opts.total, subheader: opts.subheader, value: 0, - stats: { created: 0, skipped: 0, failed: 0, retrying: 0 }, + stats: { saved: 0, skipped: 0, failed: 0, retrying: 0 }, currentFlag: null, currentText: '', settled: [], diff --git a/src/eppo/migrate.tsx b/src/eppo/migrate.tsx index 8d2f9f3..222a713 100644 --- a/src/eppo/migrate.tsx +++ b/src/eppo/migrate.tsx @@ -472,10 +472,10 @@ async function confirmMigration( // Local non-null alias so downstream code doesn't need `!` on every call. const activeRunner: MigrationRunnerHandle = runner; const settleStats = (): { - created: number; + saved: number; skipped: number; failed: number; - } => ({ created, skipped, failed: errored }); + } => ({ saved: created + synced, skipped, failed: errored }); const doSkip = (key: string, message: string, reason: string): void => { skippedFlags.push({ key, reason }); skipped++; @@ -669,7 +669,7 @@ async function confirmMigration( doSync( dryRun ? `${chalk.dim('[dry run]')} Would sync ${chalk.cyan(flag.key)} (${syncTags.length} tag(s)${variantLabel})` - : `Synced ${chalk.cyan(flag.key)} (${syncTags.length} tag(s)${variantLabel})`, + : `${chalk.green('✓')} Synced ${chalk.cyan(flag.key)} (${syncTags.length} tag(s)${variantLabel})`, ); continue; } @@ -863,7 +863,7 @@ async function confirmMigration( const enableLabel = enabledCount > 0 ? `, enabled in ${enabledCount} env(s)` : ''; doSync( - `Synced ${chalk.cyan(flag.key)} (${syncedAllocCount} targeting filter(s)${syncedRuleLabel}${variantLabel}${tagLabel}${enableLabel})`, + `${chalk.green('✓')} Synced ${chalk.cyan(flag.key)} (${syncedAllocCount} targeting filter(s)${syncedRuleLabel}${variantLabel}${tagLabel}${enableLabel})`, ); } catch (err) { const error = formatAxiosError(err); @@ -976,7 +976,7 @@ async function confirmMigration( const enableLabel = enabledCount > 0 ? `, enabled in ${enabledCount} env(s)` : ''; doCreate( - `Created ${chalk.cyan(flag.key)} (${allFilterLabel}${allRuleLabel}${enableLabel})`, + `${chalk.green('✓')} Created ${chalk.cyan(flag.key)} (${allFilterLabel}${allRuleLabel}${enableLabel})`, ); } catch (err) { const error = formatAxiosError(err); diff --git a/src/launchdarkly/migrate.tsx b/src/launchdarkly/migrate.tsx index 26a0f63..a0fc172 100644 --- a/src/launchdarkly/migrate.tsx +++ b/src/launchdarkly/migrate.tsx @@ -1039,10 +1039,10 @@ async function executeMigration( }); const activeRunner: MigrationRunnerHandle = runner; const settleStats = (): { - created: number; + saved: number; skipped: number; failed: number; - } => ({ created, skipped, failed: errored }); + } => ({ saved: created + synced, skipped, failed: errored }); const doSkip = (key: string, message: string, reason: string): void => { skippedFlags.push({ key, reason }); skipped++; @@ -1330,7 +1330,7 @@ async function executeMigration( doSync( dryRun ? `${chalk.dim('[dry run]')} Would sync ${chalk.cyan(flag.key)} (${tagLabel}${variantLabel}${policyLabel})` - : `Synced ${chalk.cyan(flag.key)} (${tagLabel}${variantLabel}${policyLabel})`, + : `${chalk.green('✓')} Synced ${chalk.cyan(flag.key)} (${tagLabel}${variantLabel}${policyLabel})`, ); continue; } @@ -1546,7 +1546,7 @@ async function executeMigration( enabledCount > 0 ? `, enabled in ${enabledCount} env(s)` : ''; syncedFlagKeys.push(flag.key); doSync( - `Synced ${chalk.cyan(flag.key)} (${syncedAllocCount} targeting filter(s)${syncedRuleLabel}${variantLabel}${tagLabel}${enableLabel})`, + `${chalk.green('✓')} Synced ${chalk.cyan(flag.key)} (${syncedAllocCount} targeting filter(s)${syncedRuleLabel}${variantLabel}${tagLabel}${enableLabel})`, ); } catch (err) { const error = formatAxiosError(err); @@ -1667,7 +1667,7 @@ async function executeMigration( const enableLabel = enabledCount > 0 ? `, enabled in ${enabledCount} env(s)` : ''; doCreate( - `Created ${chalk.cyan(ddKey)} (${allFilterLabel}${allRuleLabel}${enableLabel})`, + `${chalk.green('✓')} Created ${chalk.cyan(ddKey)} (${allFilterLabel}${allRuleLabel}${enableLabel})`, ); } catch (err) { const error = formatAxiosError(err); diff --git a/tests/migration-runner.test.tsx b/tests/migration-runner.test.tsx index 1d90665..2929301 100644 --- a/tests/migration-runner.test.tsx +++ b/tests/migration-runner.test.tsx @@ -53,12 +53,12 @@ describe('migrationRunner (non-TTY)', () => { runner.settleFlag({ status: 'created', message: 'Created foo', - stats: { created: 1, skipped: 0, failed: 0 }, + stats: { saved: 1, skipped: 0, failed: 0 }, }); runner.settleFlag({ status: 'failed', message: 'Failed bar', - stats: { created: 1, skipped: 0, failed: 1 }, + stats: { saved: 1, skipped: 0, failed: 1 }, }); expect(writeSpy).toHaveBeenCalledWith('Created foo\n'); expect(writeSpy).toHaveBeenCalledWith('Failed bar\n');