Skip to content

feat: notify user their version of dbc is out of date#266

Open
zeroshade wants to merge 21 commits intomainfrom
dbc-version-out-of-date
Open

feat: notify user their version of dbc is out of date#266
zeroshade wants to merge 21 commits intomainfrom
dbc-version-out-of-date

Conversation

@zeroshade
Copy link
Copy Markdown
Member

closes #259

Comment thread cmd/dbc/main.go Outdated
Comment thread drivers.go
@ianmcook
Copy link
Copy Markdown
Member

@zeroshade what sets the x-dbc-latest header when a new dbc version is released?

@ianmcook
Copy link
Copy Markdown
Member

I think this should probably just fail silently if it can't fetch the latest available dbc version. Telling the user that it didn't succeed is not really helpful or actionable.

@ianmcook
Copy link
Copy Markdown
Member

@amoeba any clever ideas about how to make this less annoying for users who are making the conscious choice not to upgrade (at least not right now)?

@zeroshade
Copy link
Copy Markdown
Member Author

@zeroshade what sets the x-dbc-latest header when a new dbc version is released?

Cloudfront function on the distribution for downloading dbc (we use it for the install scripts). It maps latest -> the latest version. So I added a check for the case where the request is just / as the path

@zeroshade
Copy link
Copy Markdown
Member Author

I think this should probably just fail silently if it can't fetch the latest available dbc version. Telling the user that it didn't succeed is not really helpful or actionable.

That's currently the case. It fails silently if it fails. Notice in main.go we ignore the error returned if it's not nil and just move on

Copy link
Copy Markdown
Member

@eitsupi eitsupi left a comment

Choose a reason for hiding this comment

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

I haven't looked into how existing software implements such functionality, but I wonder if there are cases where distribution channels might want to disable such functionality?
I imagine there might be a need to be able to disable this functionality at build time.

@zeroshade
Copy link
Copy Markdown
Member Author

We could create a build flag and allow controlling whether it does this check with a build tag if everyone thinks that would be a good idea. @ianmcook @amoeba @esadek what do you think?

@zeroshade
Copy link
Copy Markdown
Member Author

I've added a build tag that can be used to disable the "latest version" notification. Is that sufficient / what we were all thinking? Or are we thinking the inverse (a build tag that enables the latest version notification)?

@zeroshade
Copy link
Copy Markdown
Member Author

@ianmcook @amoeba are we good here? Do we want this in place for 0.2.0?

@ianmcook
Copy link
Copy Markdown
Member

ianmcook commented Apr 6, 2026

Based on a discussion with @amoeba today, let's rethink how to do this. As a user, it's frustrating to get a message that says you should update but doesn't say how to update. Because we provide so many install methods, there's not one simple how. To the greatest extent possible, we should give instructions for upgrading that match how the user installed. For example, if the user installed with uv tool install dbc then we should suggest upgrading with uv tool upgrade dbc. But AIUI we don't have a reliable way to determine exactly how dbc was installed.

@zeroshade
Copy link
Copy Markdown
Member Author

That's where the idea of having a build that disables the message can come in? i.e. the binary on the cdn can have the out of data update message built into it, but other install methods can just rely on their own management?

@amoeba
Copy link
Copy Markdown
Member

amoeba commented Apr 8, 2026

The build-time flag is good. That's what uv does, for example. I think we're all in agreement that if the user didn't install directly (where "directly" means curl, dbc-cdn, or github), we shouldn't notify.

What do we think about having a subcommand to let dbc update itself? I don't like how this PR currently just notifies the user to upgrade. Examples of CLIs with different approaches to do this are,

  • tlmgr update --self
  • uv self update
  • roborev update

The command would exist in all distributions but would error for non-direct methods and tell the user. It's implementation would also error on Windows since that's one platform where we can't replace a binary while it's running. The usual ways Windows programs deal with this is to ship a separate updater program but I think we can save that for another day.

@ianmcook
Copy link
Copy Markdown
Member

ianmcook commented Apr 8, 2026

Which dbc installation methods make it impossible for us to know exactly how the user installed dbc? I think uv tool install is one—IIUC there's no truly reliable way to know for sure whether a user installed with pipx install dbc or uv tool install dbc.

@amoeba
Copy link
Copy Markdown
Member

amoeba commented Apr 8, 2026

I'll double check but I think uv tool install and uvx all install our PyPI wheels so the build flag approach can be used there to disable the self update check.

Edit: yeah, those are both just unpacking our wheels

$ uv tool install --verbose dbc 2>&1 | grep whl
DEBUG Selecting: dbc==0.2.0 [compatible] (dbc-0.2.0-py3-none-macosx_12_0_arm64.whl)
DEBUG Found fresh response for: https://files.pythonhosted.org/packages/09/84/73d85b2a529ddefa16a04db573fc84954ac94c3cbfef4da108b21674d559/dbc-0.2.0-py3-none-macosx_12_0_arm64.whl.metadata

~/src/columnar-tech/sephiroth chore/add-dependabot-config
$ uvx --verbose dbc 2>&1 | grep whl
DEBUG Selecting: dbc==0.2.0 [compatible] (dbc-0.2.0-py3-none-macosx_12_0_arm64.whl)
DEBUG Found fresh response for: https://files.pythonhosted.org/packages/09/84/73d85b2a529ddefa16a04db573fc84954ac94c3cbfef4da108b21674d559/dbc-0.2.0-py3-none-macosx_12_0_arm64.whl.metadata

@amoeba
Copy link
Copy Markdown
Member

amoeba commented Apr 8, 2026

Our current distribution channels are,

  1. github releases
  2. dbc cdn (includes curl one-liner)
  3. PyPI (wheels)
  4. docker
  5. msi (includes winget)
  6. homebrew tap

Only (1) and (2) would get built with update notifications and the ability to self update. For the others, we have enough control over the dbc build to use the build flags approach to disable update notifications.

@amoeba
Copy link
Copy Markdown
Member

amoeba commented Apr 8, 2026

One thing I forgot to add to the above: It was mentioned that users might want to stay on a particular version, so adding a way to opt-out would be good. Could we do that with an env var or maybe just an empty file (which would be easier)?

@zeroshade
Copy link
Copy Markdown
Member Author

It's hard to do a self-update if they installed via any package manager (uv, homebrew, via deb/rpm package, etc) because we wouldn't be updating the package manager's understanding of what version was installed. The only one that we could reliably have a self upgrade subcommand would be if they did the curl install (or otherwise pulled it from the cdn or GitHub release...)

@amoeba
Copy link
Copy Markdown
Member

amoeba commented Apr 8, 2026

Right. Self update would only be for free-standing installs (curl, github). Are you saying maybe we don't want a self update command since it won't even work on some/most of our distribution platforms? I can get behind that.

I'm curious if others like or dislike the idea of a self update command. If we didn't have it, I think I'd make a few changes to the PR:

  1. Make the output more helpful

    $ dbc anything
    Update Available: A new version of dbc is available. You're running $old_version and $new_version is available. Run $platform_specific_command to upgrade your version.
    Changelog: $changelog_url.  Docs: $upgrading_docs_url
    
  2. A way to silence the warning, documented at $upgrading_docs_url. I propose just having the user do something like touch $dbc_config_home/.no-update in or something and have the update checking routine skip if that file exists.

@zeroshade
Copy link
Copy Markdown
Member Author

@amoeba since we'd need to have a separate name_template for the archives with the build tags, could we instead use the currently running executable path to determine whether or not to show the update message? I've pushed an update here that uses the currently running path to skip displaying the notification for homebrew/venv/conda/pip installs etc.

What do you think? Alternately, I can switch back to your original attempt and just add a proper name_template for the notify vs not notify builds.

Copy link
Copy Markdown
Member

@amoeba amoeba left a comment

Choose a reason for hiding this comment

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

Thanks for taking a crack at this. The idea made sense but it's a bit harder than I thought to get all the path detection perfect. I added some comments.

Comment thread .goreleaser.yaml Outdated
Comment thread internal/paths.go Outdated
// Directory for dbc credentials. This dir is distinct from GetUserConfigPath
// except for on macOS where it's the same
func GetCredentialPath() (string, error) {
func GetDbcConfigPath() (string, error) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Doesn't this change the location of .no-update to $HOME/.local/share on Linux? I was thinking we wanted it in XDG_CONFIG_HOME since it's not a credential and the user would probably want the file to roam.

It it helps to rename these funcs, I think paths.go just needs two functions:

  1. Return the XDG_CONFIG_HOME equivalent (for config)
  2. Return the XDG_DATA_HOME equivalent (for credentials)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

good point, this was my mistake. I undid this change and just have notifyLatest call internal.GetUserConfigPath() which uses os.UserConfigDir() which will use XDG_CONFIG_HOME etc.

Comment thread cmd/dbc/latest.go Outdated
// this is the case where we want to notify about updates
}

if runtime.GOOS == "windows" && strings.HasSuffix(filepath.Dir(exe), "\\Scripts") {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Do we need a check for the MSI installer too? It would cover manual MSI installation and also winget.

Comment thread cmd/dbc/latest.go Outdated
return true
}

if strings.Contains(exe, "conda") || strings.Contains(exe, "venv") {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

hrm, this is harder than I thought. When I install dbc into a conda env on macOS, I get a path of:

/opt/homebrew/Caskroom/miniforge/base/envs/test/bin/dbc

In a root Docker container: /root/miniforge3/bin/dbc
In a non-root Docker container: /home/test/miniforge3/envs/test/bin/dbc

Should we expand this check to include 'envs' so it at least covers a non-root miniforge3 setup? What are the conda-based setup where "conda" is part of the path? I wonder if we shouldn't change how the venv/conda check works to be more like brew. We could check env vars for being in a conda prefix or venv and compare the exe path with it.

On Windows I get C:\Users\Bryce\miniforge3\Scripts\dbc.exe so the windows check looks fine.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

That's because you're using miniforge/mamba instead of conda 😄 if you use conda directly you get conda in the path

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I figured, but I'll point out that miniforge is one of the three main ways conda recommends installing conda.

Comment thread cmd/dbc/latest.go Outdated
Comment thread cmd/dbc/latest.go Outdated
@amoeba
Copy link
Copy Markdown
Member

amoeba commented Apr 21, 2026

Two features that I think we can easily add here are,

  1. Print the update notification to stderr so it doesn't clash with piping of output unless the user opts in with redirection
  2. Only notify once per calendar day. Use a .last-update-check file in the config dir. If the file doesn't exist or if it exists and isn't set to today's date UTC, notify. Write today's UTC date in %Y-%m-%d after run.

Co-authored-by: Bryce Mecum <petridish@gmail.com>
Co-authored-by: Bryce Mecum <petridish@gmail.com>
@zeroshade
Copy link
Copy Markdown
Member Author

  • Updated the output to write to Stderr
  • Added checks for dpkg/rpm and if they exist use their methods for verifying if the exe path belongs to an installed package
  • updated conda check to check for miniforge also
  • Added check for MSI installation via registry key and path

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.

Idea: Let the user know their version of dbc is out of date

4 participants