refactor: consolidate version access to slackcontext.Version(ctx)#431
refactor: consolidate version access to slackcontext.Version(ctx)#431
Conversation
The CLIVersion field and SetVersion functional option on ClientFactory were a workaround for a circular dependency that no longer exists. The API client reads version from context via slackcontext.Version(ctx), making this indirection unnecessary. Replace with direct version.Raw() calls.
Consumers now call version.Raw() directly instead of reading from Config.Version, which was a redundant copy set in two places.
Remove re-added clients.Config.Version assignments that were intentionally deleted in the Config.Version field refactor.
Replace direct version.Raw() calls with slackcontext.Version(ctx) across all callers for improved testability via context-based dependency injection. - slackcontext.Version(ctx) now falls back to version.Raw() when the context is missing the version, returning both the fallback value and an error so callers can log a warning - ResolveLogstashHost no longer takes a cliVersion parameter; it reads the version from context internally - Tracking tests use context-based version injection instead of mutating the global version.Version variable
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #431 +/- ##
==========================================
- Coverage 70.27% 70.23% -0.04%
==========================================
Files 220 220
Lines 18498 18506 +8
==========================================
- Hits 12999 12998 -1
- Misses 4324 4331 +7
- Partials 1175 1177 +2 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
mwbrooks
left a comment
There was a problem hiding this comment.
Comments for the wise reviewers!
|
|
||
| clientsMock.Auth.On("ResolveAPIHost", mock.Anything, mock.Anything, mock.Anything). | ||
| Return("api host") | ||
| clientsMock.Auth.On("ResolveLogstashHost", mock.Anything, mock.Anything, mock.Anything). |
There was a problem hiding this comment.
note: This is the bulk of the changes - the version parameter was removed from the ResolveLogstashHost, which simplifies our testing mocks.
There was a problem hiding this comment.
🌟 praise: @mwbrooks Amazing use of the slackcontext values for gathering this now!
- ResolveLogstashHost(ctx, clients.Config.APIHostResolved, clients.Config.Version)
+ ResolveLogstashHost(ctx, clients.Config.APIHostResolved)| // TODO(slackcontext) Consolidate storing CLI version to slackcontext | ||
| clients.Config.Version = version.Raw() |
There was a problem hiding this comment.
🪓 Removing the TODO to consolidate the version to slackcontext.
| cliVersion, err := slackcontext.Version(ctx) | ||
| if err != nil { | ||
| c.io.PrintDebug(ctx, "Warning: %s", err.Error()) | ||
| } |
There was a problem hiding this comment.
note: slackcontext.Version(ctx) will return an error when ctx doesn't include the version field. This could happen if the function is called with context.Background() or t.Context(), which doesn't have the Slack CLI context properties.
When an error happens, slackcontext.Version(ctx) falls back on version.Raw(), which is set by the compiler. So, it should be very reliable at returning the correct version even if the context was incorrectly passed into the function. However, still want to handle the error by printing an warning to the debug logs, so that it can be known and fixed.
There was a problem hiding this comment.
falliing back on version.Raw() is nice!
| TeamFlag string | ||
| TokenFlag string | ||
| NoColor bool | ||
| Version string |
There was a problem hiding this comment.
🪓 shared.Config.Version
| // Version returns the CLI version associated with `ctx`. If the version is not | ||
| // found in the context, it falls back to version.Raw() and returns an error to | ||
| // signal that the context was not properly initialized. |
There was a problem hiding this comment.
note: The important design decision is written in this comment.
| setup: func(cfg *config.Config) { | ||
| cfg.Version = "v4.2.0" | ||
| ctxSetup: func(ctx context.Context) context.Context { | ||
| return slackcontext.SetVersion(ctx, "v4.2.0") |
There was a problem hiding this comment.
note: This is a safer mock now :)
| // Set context values | ||
| sessionID := uuid.New().String() | ||
| cliVersion := version.Get() | ||
| cliVersion := version.Raw() |
There was a problem hiding this comment.
💬 discussion: This is an important decision that we should feel confident in.
Originally, the version used by slackcontext and log traces was version.Get() (always prefixes the 'v'). But, Logstash and API calls used version.Raw() (git tag, which has the 'v' by convention but not guaranteed).
This wasn't a problem because our git tags always have a prefixed 'v' (e.g. v3.15.0). However, if we created a git tag without the 'v' then version would be different in different places.
:two-cents: Consistency is more important than format. This PR does introduce the consistency, I hope, because we consolidate the version access through slackcontext.Version(ctx). w.r.t the version format, I went with version.Raw() so that we know our git tag is the source of truth. If someone creates a git tag with a different format, at least we know it all lines up. But, I'm open to either.
Thoughts?
There was a problem hiding this comment.
I agree with using Raw() and i like the idea of having git tag as our source of truth! it means its less likely for our logstash, api calls, etc to have the wrong version. also if we did mistakenly make a git tag w/out the 'v', that version would be consistent everywhere else so it would be easier to correct
There was a problem hiding this comment.
💡 praise: Thanks for calling this out! I'd been stumped on what might be best too.
👾 thought: I was leaning toward using version.Get to guarantee that releases use the "v" prefix to avoid errors with the User-Agent format:
slack-cli/v3.4.5-example-2-ga7e71fe (os: darwin)
But agree that consistent formats is better! We might lean on CI to package releases to avoid nuance as well 🎁
🔭 question: Should we also remove version.Get in a follow up PR? It might be a chance to ask less from the regex package:
slack-cli/internal/version/version.go
Lines 43 to 50 in 2cf691e
|
|
||
| var ctx = context.Background() | ||
| ctx = slackcontext.SetSessionID(ctx, uuid.New().String()) | ||
| ctx = slackcontext.SetVersion(ctx, version.Raw()) |
There was a problem hiding this comment.
note: Cannot re-use the cliVersion above because this is the recovery() function.
… into mwbrooks-cli-version-refactor-1
srtaalej
left a comment
There was a problem hiding this comment.
i think consolidating into slackcontext.Version(ctx) was the right call! LGTM ⭐
zimeg
left a comment
There was a problem hiding this comment.
@mwbrooks Nice changes to these processes 📺 ✨
I left a handful of comments toward these changes without blockers! When the time is best please do merge 🚢
Most comments are around packages - I'm curious about a simple version package most.
|
|
||
| clientsMock.Auth.On("ResolveAPIHost", mock.Anything, mock.Anything, mock.Anything). | ||
| Return("api host") | ||
| clientsMock.Auth.On("ResolveLogstashHost", mock.Anything, mock.Anything, mock.Anything). |
There was a problem hiding this comment.
🌟 praise: @mwbrooks Amazing use of the slackcontext values for gathering this now!
- ResolveLogstashHost(ctx, clients.Config.APIHostResolved, clients.Config.Version)
+ ResolveLogstashHost(ctx, clients.Config.APIHostResolved)| if err != nil { | ||
| ioStream.PrintDebug(ctx, "Warning: %s", err.Error()) | ||
| } | ||
| versionString, _ := strings.CutPrefix(cliVersion, "v") |
There was a problem hiding this comment.
| versionString, _ := strings.CutPrefix(cliVersion, "v") | |
| versionString := strings.TrimPrefix(cliVersion, "v") |
🔭 suggestion(non-blocking): The unhandled "found" value might be more confusing than a different method here? No blocker since that's unchanged from before but it might be a good time to improve this for later.
| // Set context values | ||
| sessionID := uuid.New().String() | ||
| cliVersion := version.Get() | ||
| cliVersion := version.Raw() |
There was a problem hiding this comment.
💡 praise: Thanks for calling this out! I'd been stumped on what might be best too.
👾 thought: I was leaning toward using version.Get to guarantee that releases use the "v" prefix to avoid errors with the User-Agent format:
slack-cli/v3.4.5-example-2-ga7e71fe (os: darwin)
But agree that consistent formats is better! We might lean on CI to package releases to avoid nuance as well 🎁
🔭 question: Should we also remove version.Get in a follow up PR? It might be a chance to ask less from the regex package:
slack-cli/internal/version/version.go
Lines 43 to 50 in 2cf691e
Changelog
Summary
This pull request consolidates version access to
slackcontext.Version(ctx).Currently, the version is accessed with
version.Raw(),version.Get(),clients.config.Version, andslackcontext.Version(ctx). This is brittle, because it requires all version fields to be set to the same version. Additionally, the version value is passed as a parameter through some functions, which creates more risk of the incorrect version bring used.version.Raw()callers toslackcontext.Version(ctx).version.Raw(), previously it was a mix - most used.Raw(), but therecoveryFuncused.Get(). This could lead to difficulty associating log traces.clients.config.Version.version stringparameter withctxparameter.main.go.Open Questions
.Get()or.Raw().Test Steps
1. Version output
$ ./bin/slack --version # → Confirm: the version string is displayed correctly (e.g. v0.x.x or a dev build SHA)2. Version in debug output
3.. User-Agent in API debug output
4.. Log file version
Requirements