From 93be1cbd778d422547955ab9743a8fe11bc017ae Mon Sep 17 00:00:00 2001 From: Eric Dahl Date: Fri, 2 Oct 2026 14:12:08 -0400 Subject: [PATCH] Use American spelling Rename the internal StoplightGrey constant to StoplightGray and fix grey/colour/recognise in comments, docs and test messages. Claude-Session: https://claude.ai/code/session_01XGS7UUxZFhvaK4bnErEfvW --- CONTEXT.md | 2 +- docs/screenshot.svg | 4 ++-- internal/cfn/cfn.go | 2 +- internal/cfn/fetch_internal_test.go | 8 ++++---- internal/ecs/ecs.go | 4 ++-- internal/fix/fix_test.go | 6 +++--- internal/health/health.go | 8 ++++---- internal/health/health_test.go | 6 +++--- internal/health/service.go | 2 +- internal/health/service_test.go | 2 +- internal/health/stack.go | 4 ++-- internal/health/stack_test.go | 6 +++--- internal/poller/fetch.go | 2 +- internal/poller/fetch_test.go | 6 +++--- internal/poller/poller.go | 4 ++-- internal/poller/poller_test.go | 22 +++++++++++----------- internal/state/state.go | 8 ++++---- internal/state/state_test.go | 10 +++++----- internal/ui/autoexpand_test.go | 2 +- main.go | 2 +- 20 files changed, 55 insertions(+), 55 deletions(-) diff --git a/CONTEXT.md b/CONTEXT.md index 161a2de..0f392ec 100644 --- a/CONTEXT.md +++ b/CONTEXT.md @@ -38,7 +38,7 @@ The visual health indicator for a Pipeline. Derived from the latest Execution st | 🔴 Red | Broken or blocked | `Failed`, `Stopped` | | 🟡 Yellow | In progress | `InProgress` | | ⏸ Awaiting approval | Waiting on a person | `InProgress` at a manual approval action with an open approval token | -| ⚪ Grey | No signal | `Superseded`, no executions yet | +| ⚪ Gray | No signal | `Superseded`, no executions yet | Awaiting approval ranks between Yellow and Red: it needs a person, not more time, but a failure still outranks it. It is raised in `state.NewPipeline` from the action's approval token, because execution statuses alone can't tell an approval gate from a running build. diff --git a/docs/screenshot.svg b/docs/screenshot.svg index 92936a7..11b2505 100644 --- a/docs/screenshot.svg +++ b/docs/screenshot.svg @@ -9,7 +9,7 @@ .green { fill: #22c55e; } .yellow { fill: #eab308; } .red { fill: #ef4444; } - .grey { fill: #64748b; } + .gray { fill: #64748b; } .hint { fill: #94a3b8; opacity: 0.55; } @@ -36,7 +36,7 @@ ✓ Source ✓ Build ● Deploy 2m34s - ○ Approve + ○ Approve stacks diff --git a/internal/cfn/cfn.go b/internal/cfn/cfn.go index 178461e..ddd8ea2 100644 --- a/internal/cfn/cfn.go +++ b/internal/cfn/cfn.go @@ -53,7 +53,7 @@ func (c *Client) FetchStacks(ctx context.Context, names []string) ([]state.Stack result = append(result, state.StackState{ Name: name, Status: "NOT_FOUND", - Stoplight: health.StoplightGrey, + Stoplight: health.StoplightGray, }) continue } diff --git a/internal/cfn/fetch_internal_test.go b/internal/cfn/fetch_internal_test.go index 671e90d..49486a5 100644 --- a/internal/cfn/fetch_internal_test.go +++ b/internal/cfn/fetch_internal_test.go @@ -30,7 +30,7 @@ func (f fakeDescribeStacks) DescribeStacks(_ context.Context, in *cloudformation } // A failed call has to reach the poller as an error, so it keeps the last -// known stacks on screen marked stale instead of turning them grey. +// known stacks on screen marked stale instead of turning them gray. func TestFetchStacksReturnsCallErrors(t *testing.T) { c := &Client{svc: fakeDescribeStacks{ stacks: map[string]cfntypes.StackStatus{"ok": cfntypes.StackStatusUpdateComplete}, @@ -42,7 +42,7 @@ func TestFetchStacksReturnsCallErrors(t *testing.T) { } // A stack that doesn't exist is an answer, not a failed call: AWS reports it -// as a ValidationError, and it shows grey without marking the fetch stale. +// as a ValidationError, and it shows gray without marking the fetch stale. func TestFetchStacksReportsMissingStackAsNotFound(t *testing.T) { c := &Client{svc: fakeDescribeStacks{ stacks: map[string]cfntypes.StackStatus{"ok": cfntypes.StackStatusUpdateComplete}, @@ -60,7 +60,7 @@ func TestFetchStacksReportsMissingStackAsNotFound(t *testing.T) { if got[0].Stoplight != health.StoplightGreen { t.Errorf("ok: Stoplight = %v, want green", got[0].Stoplight) } - if got[1].Status != "NOT_FOUND" || got[1].Stoplight != health.StoplightGrey { - t.Errorf("gone: got %+v, want NOT_FOUND grey", got[1]) + if got[1].Status != "NOT_FOUND" || got[1].Stoplight != health.StoplightGray { + t.Errorf("gone: got %+v, want NOT_FOUND gray", got[1]) } } diff --git a/internal/ecs/ecs.go b/internal/ecs/ecs.go index 80d6b2f..6e2d93a 100644 --- a/internal/ecs/ecs.go +++ b/internal/ecs/ecs.go @@ -90,7 +90,7 @@ func (c *Client) FetchServices(ctx context.Context, cluster string, services []s result = append(result, sd) } - // For any requested service not returned, add a grey entry. + // For any requested service not returned, add a gray entry. found := make(map[string]bool, len(result)) for _, sd := range result { found[sd.Name] = true @@ -100,7 +100,7 @@ func (c *Client) FetchServices(ctx context.Context, cluster string, services []s result = append(result, state.ECSServiceState{ Name: svcName, Cluster: cluster, - Stoplight: health.StoplightGrey, + Stoplight: health.StoplightGray, }) } } diff --git a/internal/fix/fix_test.go b/internal/fix/fix_test.go index a1f6c43..05db160 100644 --- a/internal/fix/fix_test.go +++ b/internal/fix/fix_test.go @@ -26,11 +26,11 @@ func TestPlan_noActionWhenGreen(t *testing.T) { } } -func TestPlan_noActionWhenGrey(t *testing.T) { - p := proj(health.StoplightGrey, nil, nil) +func TestPlan_noActionWhenGray(t *testing.T) { + p := proj(health.StoplightGray, nil, nil) plan := fix.Plan(p, 30*time.Minute) if plan != nil { - t.Errorf("expected nil plan for grey project, got %v", plan) + t.Errorf("expected nil plan for gray project, got %v", plan) } } diff --git a/internal/health/health.go b/internal/health/health.go index 354807c..244d7d8 100644 --- a/internal/health/health.go +++ b/internal/health/health.go @@ -4,7 +4,7 @@ package health type Stoplight int const ( - StoplightGrey Stoplight = iota // no executions, or superseded + StoplightGray Stoplight = iota // no executions, or superseded StoplightGreen // succeeded StoplightYellow // in progress // StoplightAwaitingApproval is a pipeline paused at a manual approval. It @@ -50,14 +50,14 @@ func statusToStoplight(s ExecutionStatus) Stoplight { case StatusInProgress: return StoplightYellow default: - return StoplightGrey + return StoplightGray } } // Aggregate returns the worst-case Stoplight across all provided execution statuses. -// Red > Yellow > Green > Grey. +// Red > Yellow > Green > Gray. func Aggregate(statuses []ExecutionStatus) Stoplight { - result := StoplightGrey + result := StoplightGray for _, s := range statuses { light := statusToStoplight(s) if light > result { diff --git a/internal/health/health_test.go b/internal/health/health_test.go index d8a4739..8105bd5 100644 --- a/internal/health/health_test.go +++ b/internal/health/health_test.go @@ -8,8 +8,8 @@ import ( func TestAggregate_empty(t *testing.T) { got := health.Aggregate(nil) - if got != health.StoplightGrey { - t.Errorf("expected grey, got %v", got) + if got != health.StoplightGray { + t.Errorf("expected gray, got %v", got) } } @@ -49,7 +49,7 @@ func TestStoplight_String(t *testing.T) { {health.StoplightGreen, "🟢"}, {health.StoplightRed, "🔴"}, {health.StoplightYellow, "🟡"}, - {health.StoplightGrey, "⚪"}, + {health.StoplightGray, "⚪"}, } for _, tc := range cases { if got := tc.light.String(); got != tc.want { diff --git a/internal/health/service.go b/internal/health/service.go index 647ffc3..6ff27a7 100644 --- a/internal/health/service.go +++ b/internal/health/service.go @@ -17,7 +17,7 @@ type Service struct { func (s Service) Stoplight() Stoplight { switch { case s.Desired == 0 && s.Running == 0: - return StoplightGrey + return StoplightGray case s.Running == 0 && s.Desired > 0: return StoplightRed case s.FailingTasks > 0: diff --git a/internal/health/service_test.go b/internal/health/service_test.go index fc21cea..f141546 100644 --- a/internal/health/service_test.go +++ b/internal/health/service_test.go @@ -29,7 +29,7 @@ func TestServiceStoplight(t *testing.T) { {"deploying", health.Service{Running: 2, Desired: 2, ActiveDeployment: true}, health.StoplightYellow}, {"scaling_up", health.Service{Running: 1, Desired: 2}, health.StoplightYellow}, {"pending_tasks", health.Service{Running: 2, Desired: 2, Pending: 1}, health.StoplightYellow}, - {"zero_desired_zero_running", health.Service{}, health.StoplightGrey}, + {"zero_desired_zero_running", health.Service{}, health.StoplightGray}, {"down", health.Service{Running: 0, Desired: 2}, health.StoplightRed}, {"failing_tasks", health.Service{Running: 2, Desired: 2, FailingTasks: 1}, health.StoplightRed}, {"failing_tasks_with_running", health.Service{Running: 1, Desired: 2, FailingTasks: 2}, health.StoplightRed}, diff --git a/internal/health/stack.go b/internal/health/stack.go index 28c0df9..4f9e7b0 100644 --- a/internal/health/stack.go +++ b/internal/health/stack.go @@ -65,10 +65,10 @@ func (s StackStatus) Stoplight() Stoplight { strings.HasPrefix(status, "DELETE_"): return StoplightRed case status == "REVIEW_IN_PROGRESS": - return StoplightGrey + return StoplightGray case strings.HasSuffix(status, "_IN_PROGRESS"): return StoplightYellow default: - return StoplightGrey + return StoplightGray } } diff --git a/internal/health/stack_test.go b/internal/health/stack_test.go index 6cc382d..a938155 100644 --- a/internal/health/stack_test.go +++ b/internal/health/stack_test.go @@ -19,7 +19,7 @@ func TestStackStuckReason(t *testing.T) { {"CREATE_FAILED", "stack_failed"}, {"UPDATE_ROLLBACK_FAILED", "stack_failed"}, {"DELETE_FAILED", "stack_failed"}, - // A change set waiting on review shows grey: it's parked on a person, + // A change set waiting on review shows gray: it's parked on a person, // not a wedged deploy. {"REVIEW_IN_PROGRESS", ""}, } @@ -46,8 +46,8 @@ func TestStackStoplight(t *testing.T) { {"CREATE_IN_PROGRESS", health.StoplightYellow}, {"UPDATE_IN_PROGRESS", health.StoplightYellow}, {"UPDATE_ROLLBACK_IN_PROGRESS", health.StoplightYellow}, - {"REVIEW_IN_PROGRESS", health.StoplightGrey}, - {"", health.StoplightGrey}, + {"REVIEW_IN_PROGRESS", health.StoplightGray}, + {"", health.StoplightGray}, } for _, tc := range cases { diff --git a/internal/poller/fetch.go b/internal/poller/fetch.go index feacf98..35966ca 100644 --- a/internal/poller/fetch.go +++ b/internal/poller/fetch.go @@ -40,7 +40,7 @@ func fetchProject(ctx context.Context, proj config.Project, c accountClients, pr out.Pipeline = prev.Pipeline out.Pipeline.FetchStatus = stale(noClient("", proj.Account, c.pipelineErr)) case proj.Pipeline.Name == "": - out.Pipeline = state.PipelineState{Account: proj.Account, Stoplight: health.StoplightGrey} + out.Pipeline = state.PipelineState{Account: proj.Account, Stoplight: health.StoplightGray} default: data, err := c.pipeline.FetchPipeline(ctx, proj.Pipeline.Name) if err != nil { diff --git a/internal/poller/fetch_test.go b/internal/poller/fetch_test.go index ee28114..e791031 100644 --- a/internal/poller/fetch_test.go +++ b/internal/poller/fetch_test.go @@ -180,7 +180,7 @@ func TestFetchProjectRecordsFailureWithNothingToCarry(t *testing.T) { } } -// A project with only stacks gets a grey pipeline placeholder and no +// A project with only stacks gets a gray pipeline placeholder and no // pipeline call. func TestFetchProjectWithoutPipeline(t *testing.T) { proj := appProject() @@ -192,7 +192,7 @@ func TestFetchProjectWithoutPipeline(t *testing.T) { if len(pipes.fetched()) != 0 { t.Errorf("expected no pipeline fetch, got %v", pipes.fetched()) } - if got.Pipeline.Stoplight != health.StoplightGrey || got.Pipeline.Account != "prod" { - t.Errorf("expected a grey placeholder for prod, got %+v", got.Pipeline) + if got.Pipeline.Stoplight != health.StoplightGray || got.Pipeline.Account != "prod" { + t.Errorf("expected a gray placeholder for prod, got %+v", got.Pipeline) } } diff --git a/internal/poller/poller.go b/internal/poller/poller.go index b1d5561..feb64f8 100644 --- a/internal/poller/poller.go +++ b/internal/poller/poller.go @@ -65,7 +65,7 @@ func New(cfg *config.Config, factory ClientFactory, cfnFactory CFNClientFactory, Pipeline: state.PipelineState{ Account: p.Account, Name: p.Pipeline.Name, - Stoplight: health.StoplightGrey, + Stoplight: health.StoplightGray, }, } } @@ -213,7 +213,7 @@ func servicesForCluster(services []state.ECSServiceState, cluster string) []stat // carryForward rebases a project's last known state onto its new config entry. // Rebuilding every row from zero on a config edit would blank the health of -// every project until the next poll returns — the same "grey means both +// every project until the next poll returns — the same "gray means both // 'unknown' and 'was fine a second ago'" ambiguity that carried-forward fetches // exist to avoid. State the edit invalidated is dropped rather than carried, so // the edit still shows up immediately. diff --git a/internal/poller/poller_test.go b/internal/poller/poller_test.go index 40cd972..07bf0f6 100644 --- a/internal/poller/poller_test.go +++ b/internal/poller/poller_test.go @@ -235,8 +235,8 @@ name = "beta-pipeline" if snap.Projects[0].Name != "beta" { t.Errorf("expected beta, got %q", snap.Projects[0].Name) } - if snap.Projects[0].Pipeline.Stoplight != health.StoplightGrey { - t.Errorf("expected seeded state to be grey, got %v", snap.Projects[0].Pipeline.Stoplight) + if snap.Projects[0].Pipeline.Stoplight != health.StoplightGray { + t.Errorf("expected seeded state to be gray, got %v", snap.Projects[0].Pipeline.Stoplight) } } @@ -340,7 +340,7 @@ func TestPrevPipelineMatchesByAccountAndName(t *testing.T) { if got := prevPipeline(prev, "beta", "prod"); got.Name != "beta-pipeline" || got.Stoplight != health.StoplightRed { t.Errorf("expected beta's pipeline, got %+v", got) } - if got := prevPipeline(prev, "gamma", "prod"); got.Name != "" || got.Stoplight != health.StoplightGrey { + if got := prevPipeline(prev, "gamma", "prod"); got.Name != "" || got.Stoplight != health.StoplightGray { t.Errorf("expected zero PipelineState for an unknown project, got %+v", got) } if got := prevPipeline(nil, "alpha", "prod"); got.Name != "" { @@ -535,10 +535,10 @@ name = "delta-pipeline" if got.Pipeline.Name != "gamma-pipeline" { t.Errorf("expected gamma-pipeline, got %q", got.Pipeline.Name) } - // gamma is new to the config, so there is nothing to carry and grey is - // the honest starting colour. - if got.Pipeline.Stoplight != health.StoplightGrey { - t.Errorf("expected grey for a project new to the config, got %v", got.Pipeline.Stoplight) + // gamma is new to the config, so there is nothing to carry and gray is + // the honest starting color. + if got.Pipeline.Stoplight != health.StoplightGray { + t.Errorf("expected gray for a project new to the config, got %v", got.Pipeline.Stoplight) } } @@ -583,8 +583,8 @@ name = "gamma-pipeline" if got := byName["beta"].Pipeline.Stoplight; got != health.StoplightRed { t.Errorf("expected beta's red to survive the reload, got %v", got) } - if got := byName["gamma"].Pipeline.Stoplight; got != health.StoplightGrey { - t.Errorf("expected the new project to start grey, got %v", got) + if got := byName["gamma"].Pipeline.Stoplight; got != health.StoplightGray { + t.Errorf("expected the new project to start gray, got %v", got) } } @@ -656,8 +656,8 @@ services = ["keep-svc"] if got.Pipeline.Name != "renamed-pipeline" || len(got.Pipeline.Stages) != 0 { t.Errorf("expected the renamed pipeline to start over, got %+v", got.Pipeline) } - if got.Pipeline.Stoplight != health.StoplightGrey { - t.Errorf("expected the renamed pipeline grey, got %v", got.Pipeline.Stoplight) + if got.Pipeline.Stoplight != health.StoplightGray { + t.Errorf("expected the renamed pipeline gray, got %v", got.Pipeline.Stoplight) } if len(got.Stacks) != 1 || got.Stacks[0].Name != "keep-stack" { t.Errorf("expected only the still-configured stack, got %+v", got.Stacks) diff --git a/internal/state/state.go b/internal/state/state.go index 7761285..94a5056 100644 --- a/internal/state/state.go +++ b/internal/state/state.go @@ -158,9 +158,9 @@ func (p ProjectState) Stoplight() health.Stoplight { } // StacksStoplight returns the worst-case stoplight across the project's -// stacks, or grey when it has none. +// stacks, or gray when it has none. func (p ProjectState) StacksStoplight() health.Stoplight { - worst := health.StoplightGrey + worst := health.StoplightGray for _, s := range p.Stacks { worst = max(worst, s.Stoplight) } @@ -168,9 +168,9 @@ func (p ProjectState) StacksStoplight() health.Stoplight { } // ECSStoplight returns the worst-case stoplight across the project's ECS -// services, or grey when it has none. +// services, or gray when it has none. func (p ProjectState) ECSStoplight() health.Stoplight { - worst := health.StoplightGrey + worst := health.StoplightGray for _, s := range p.ECSServices { worst = max(worst, s.Stoplight) } diff --git a/internal/state/state_test.go b/internal/state/state_test.go index ad4af83..c5be97e 100644 --- a/internal/state/state_test.go +++ b/internal/state/state_test.go @@ -21,12 +21,12 @@ func TestProjectState_stoplightFromPipeline(t *testing.T) { } } -func TestProjectState_stoplightGrey_noPipeline(t *testing.T) { +func TestProjectState_stoplightGray_noPipeline(t *testing.T) { proj := state.ProjectState{ Name: "empty-project", } - if proj.Stoplight() != health.StoplightGrey { - t.Errorf("expected grey, got %v", proj.Stoplight()) + if proj.Stoplight() != health.StoplightGray { + t.Errorf("expected gray, got %v", proj.Stoplight()) } } @@ -141,7 +141,7 @@ func TestProjectState_perKindStoplights(t *testing.T) { if got := proj.ECSStoplight(); got != health.StoplightYellow { t.Errorf("ECSStoplight() = %v, want yellow", got) } - if got := (state.ProjectState{}).StacksStoplight(); got != health.StoplightGrey { - t.Errorf("no stacks: StacksStoplight() = %v, want grey", got) + if got := (state.ProjectState{}).StacksStoplight(); got != health.StoplightGray { + t.Errorf("no stacks: StacksStoplight() = %v, want gray", got) } } diff --git a/internal/ui/autoexpand_test.go b/internal/ui/autoexpand_test.go index 3555b20..211cb08 100644 --- a/internal/ui/autoexpand_test.go +++ b/internal/ui/autoexpand_test.go @@ -37,7 +37,7 @@ func TestAutoExpandOnFirstSighting(t *testing.T) { {health.StoplightYellow, true}, {health.StoplightAwaitingApproval, true}, {health.StoplightGreen, false}, - {health.StoplightGrey, false}, + {health.StoplightGray, false}, } { d := NewDashboard(snapWith(tc.light), nil, context.Background()) if got := d.expanded[projKey]; got != tc.want { diff --git a/main.go b/main.go index b389098..c0e2b31 100644 --- a/main.go +++ b/main.go @@ -235,7 +235,7 @@ Usage: // runCommand handles the non-TUI invocations. It reports whether args were // handled here, along with the exit code to use when they were. Anything it -// does not recognise falls through to launching the dashboard. +// does not recognize falls through to launching the dashboard. func runCommand(args []string, out io.Writer) (int, bool) { if len(args) == 0 { return 0, false