Skip to content

Conversation

@eablack
Copy link
Contributor

@eablack eablack commented Jan 20, 2026

Summary

This PR migrates add-on attachment name coloring from generic color.cyan() and color.green() to the semantic color.attachment() function from @heroku/heroku-cli-util. This is part 4 of 17 of the color system migration plan.

Changes:

  • Updated imports from @heroku-cli/color to @heroku/heroku-cli-util in 5 files
  • Replaced color.cyan() and color.green() with color.attachment() for attachment names
  • Also updated addon references to use color.addon() where applicable

Files modified:

  • commands/addons/attach.ts
  • commands/addons/detach.ts
  • commands/addons/index.ts
  • commands/addons/info.ts
  • commands/pg/connection-pooling/attach.ts

Type of Change

Breaking Changes (major semver update)

  • Add a ! after your change type to denote a change that breaks current behavior

Feature Additions (minor semver update)

  • feat: Introduces a new feature to the codebase

Patch Updates (patch semver update)

  • fix: Bug fix
  • perf: Performance improvement
  • deps: Dependency upgrade
  • revert: Revert a previous commit
  • docs: Documentation change
  • style: Styling update
  • chore: Change that does not affect production code
  • refactor: Refactoring existing code without changing behavior
  • tests: Add/update/remove tests
  • build: Change to the build system
  • ci: Continuous integration workflow update

Testing

Steps:

  1. Passing CI suffices for build validation
  2. Manual testing can be done by running commands like heroku addons:attach, heroku addons:detach, or heroku addons:info to verify attachment names display with the new semantic coloring

Related Issues

Part of the color system migration plan (4 of 17).

@eablack eablack requested a review from a team as a code owner January 20, 2026 18:36
@eablack eablack temporarily deployed to AcceptanceTests January 20, 2026 18:56 — with GitHub Actions Inactive
@eablack eablack temporarily deployed to AcceptanceTests January 20, 2026 18:56 — with GitHub Actions Inactive
@eablack eablack temporarily deployed to AcceptanceTests January 20, 2026 18:56 — with GitHub Actions Inactive
@eablack eablack temporarily deployed to AcceptanceTests January 20, 2026 18:56 — with GitHub Actions Inactive
This PR migrates add-on attachment name coloring from generic cyan/green
colors to the semantic color.attachment() function. This is part 4 of 17 of
the color system migration plan.

Changes:
- Updated imports from @heroku-cli/color to @heroku/heroku-cli-util
- Replaced color.cyan() and color.green() with color.attachment() for attachment names
- Also updated addon references to use color.addon()
Copy link
Contributor

@k80bowman k80bowman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks mostly good, just a couple of small questions.

@@ -1,28 +1,31 @@
import {color} from '@heroku-cli/color'
/* eslint-disable perfectionist/sort-objects */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why disable this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

disabling this because i kept trying to "fix" it. but we actually want the non-alphabetical order for displaying addon info on line 36. styledObject actually pays attention to the "order" of the keys. we should probably change the interface to styledObject to explicitly declare the output order in some other way.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add an eslint-disable-next-line on the line above the styledObject call then so it's more clear why you're disabling it? Rather than disabling it for the entire file.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for pushing me on this. i actually didn't think you could do something like that with eslint, but i learned that you can, although slightly differently than you describe. you do:

/* eslint-disable perfectionist/sort-objects */
...some code block...
/* eslint-enable perfectionist/sort-objects */

@eablack eablack force-pushed the eb/color-migration-attachment branch from 0f16b48 to e51ca3e Compare January 20, 2026 21:03
@eablack eablack temporarily deployed to AcceptanceTests January 20, 2026 21:04 — with GitHub Actions Inactive
@eablack eablack temporarily deployed to AcceptanceTests January 20, 2026 21:04 — with GitHub Actions Inactive
@eablack eablack temporarily deployed to AcceptanceTests January 20, 2026 21:04 — with GitHub Actions Inactive
@eablack eablack temporarily deployed to AcceptanceTests January 20, 2026 21:04 — with GitHub Actions Inactive
Copy link
Contributor

@sbosio sbosio left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A couple things that I think need to be corrected before merging.

return formatPrice({hourly: true, price: addon.plan?.price})
}

return color.dim(printf('(billed to %s app)', newColor.app(addon.app?.name || '')))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this case, cyan was used to differentiate the owning app (purple) from other apps (cyan). That differentiation is now lost. You can compare the outputs of both commands:

Image

Moreover, cyan being used for attachment names makes this more confusing. IMHO it's not good to rely on coloring to only differentiate stuff (because of accessibility).

My suggestions:

  • Keep all app names with same colorization (keep the current changes). Remove the cyan on apps at the end of the last phrase after the table, then use the correct attachment color for attachments word on that very same sentence.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, i think consistency is the primary goal. like, color should tell you what the thing is. inconsistently coloring really diminishes the benefit of the "oh that has a purple hexagon, must be an app" effect. there are some caveats here. for instance, when you're renaming an app and we display the name of the thing that isn't yet an app (but will be).

i think we can do better than arbitrarily coloring things just to distinguish between individual items. we should be able to show that in other ways (and we really should, for reasons you described).

i agree, cyan being used for attachment names is just a miss. i'll correct it.

the last message using a bunch of colors is interesting. i dunno how i feel about it. we tend to just use colors to denote the names of things, not words that generally describe them. i'll probably remove all the coloring from that message. i think if we tried to be consistent with that across the cli it'd be color overload.

overflow: 'wrap',
},
)
ux.stdout(`The table above shows ${color.magenta('add-ons')} and the ${color.green('attachments')} to the current app (${newColor.app(app)}) or other ${color.cyan('apps')}.\n `)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here is where I suggest changing to:

Suggested change
ux.stdout(`The table above shows ${newColor.addon('add-ons')} and the ${newColor.attachment('attachments')} to the current app (${newColor.app(app)}) or other apps.\n`)

.join(', ')

warnings.push(`This command will affect the app${(attachments.length > 1) ? 's' : ''} ${uniqueAttachments}.`)
warnings.push(`This command will affect the app${(attachments.length > 1) ? 's' : ''} ${color.attachment(uniqueAttachments)}.`)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs to be reverted and fixed.

The name uniqueAttachments is misleading. Should've been named uniqueAppNames, because through the list of attachments it composes a set of unique app names associated with the attachments. See the previous three lines. It's a list of unique app names with the correct color (for apps) already applied.

But the pluralization is wrong, because it check attachments' length when it should be checking uniqueAttachments length.

At a glance:

Suggested change
warnings.push(`This command will affect the app${(attachments.length > 1) ? 's' : ''} ${color.attachment(uniqueAttachments)}.`)
warnings.push(`This command will affect the app${(uniqueAttachments.length > 1) ? 's' : ''} ${uniqueAttachments}.`)

It's up to you if you want to rename the variable to something like uniqueAppNames to make it semantically correct, 😄 .

@eablack eablack temporarily deployed to AcceptanceTests January 21, 2026 01:14 — with GitHub Actions Inactive
@eablack eablack temporarily deployed to AcceptanceTests January 21, 2026 01:14 — with GitHub Actions Inactive
@eablack eablack temporarily deployed to AcceptanceTests January 21, 2026 01:14 — with GitHub Actions Inactive
@eablack eablack deployed to AcceptanceTests January 21, 2026 01:14 — with GitHub Actions Active
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants