-
Notifications
You must be signed in to change notification settings - Fork 10
feat: notify user their version of dbc is out of date #266
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 14 commits
7b072ea
2fa5633
5c767fa
b93b954
50273ff
152bee8
a12e7a0
4ec8bea
a007b82
c367112
30f8604
54389ca
d8f8a71
b04dd37
91b6219
490f173
ac29758
6142e98
7bb90e8
88159f8
d37a094
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,113 @@ | ||
| // Copyright 2026 Columnar Technologies Inc. | ||
| // | ||
| // Licensed under the Apache License, Version 2.0 (the "License"); | ||
| // you may not use this file except in compliance with the License. | ||
| // You may obtain a copy of the License at | ||
| // | ||
| // http://www.apache.org/licenses/LICENSE-2.0 | ||
| // | ||
| // Unless required by applicable law or agreed to in writing, software | ||
| // distributed under the License is distributed on an "AS IS" BASIS, | ||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| // See the License for the specific language governing permissions and | ||
| // limitations under the License. | ||
|
|
||
| package main | ||
|
|
||
| import ( | ||
| "errors" | ||
| "os" | ||
| "os/exec" | ||
| "path/filepath" | ||
| "runtime" | ||
| "strings" | ||
|
|
||
| "charm.land/lipgloss/v2" | ||
| "github.com/Masterminds/semver/v3" | ||
| "github.com/cli/safeexec" | ||
| "github.com/columnar-tech/dbc" | ||
| "github.com/columnar-tech/dbc/internal" | ||
| ) | ||
|
|
||
| func isUnderHomebrew(bin string) bool { | ||
| brewExe, err := safeexec.LookPath("brew") | ||
| if err != nil { | ||
| return false | ||
| } | ||
|
|
||
| brewPrefixBytes, err := exec.Command(brewExe, "--prefix").Output() | ||
| if err != nil { | ||
| return false | ||
| } | ||
|
|
||
| brewBinPrefix := filepath.Join(strings.TrimSpace( | ||
| string(brewPrefixBytes)), "bin") + string(filepath.Separator) | ||
| return strings.HasPrefix(bin, brewBinPrefix) | ||
| } | ||
|
|
||
| func isPkgMgrInstall() bool { | ||
| exe, err := os.Executable() | ||
| if err != nil { | ||
| return false | ||
| } | ||
|
|
||
| if isUnderHomebrew(exe) { | ||
| return true | ||
| } | ||
|
|
||
| exe, err = filepath.EvalSymlinks(exe) | ||
| if err != nil { | ||
| return false | ||
| } | ||
|
|
||
| switch filepath.Dir(exe) { | ||
| case "/usr/local/bin": | ||
| // pip installs here on linux | ||
| return true | ||
| case "/usr/bin": | ||
| // likely a system package manager, but could be other things too | ||
| return true | ||
| default: | ||
| // likely a local user install via script | ||
| // or via msi on windows etc. | ||
| // this is the case where we want to notify about updates | ||
| } | ||
|
|
||
| if runtime.GOOS == "windows" && strings.HasSuffix(filepath.Dir(exe), "\\Scripts") { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. |
||
| // likely a pip install on windows | ||
| return true | ||
| } | ||
|
|
||
| if strings.Contains(exe, "conda") || strings.Contains(exe, "venv") { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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:
In a root Docker container: 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
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. |
||
| // likely a conda or virtual environment install | ||
| return true | ||
| } | ||
|
|
||
| return false | ||
| } | ||
|
|
||
| func notifyLatest() { | ||
| if isPkgMgrInstall() { | ||
| // skip notifying if installed via package manager, | ||
| // since they likely have their own update mechanism | ||
| return | ||
| } | ||
|
|
||
| configDir, err := internal.GetDbcConfigPath() | ||
| if err != nil { | ||
| return | ||
| } | ||
|
|
||
| // skip notifying if $dbc_config_home/.no-update exists | ||
| _, err = os.Stat(filepath.Join(configDir, ".no-update")) | ||
| if errors.Is(err, os.ErrNotExist) { | ||
| latestVer, err := dbc.GetLatestDbcVersion() | ||
| if dbc.Version != "(devel)" && err == nil { | ||
| if semver.MustParse(dbc.Version).LessThan(latestVer) { | ||
| lipgloss.Printf(descStyle.Render("Update available: A new version of dbc is available. You're running %s and v%s is available. Please upgrade.\nChangelog: %s. Docs: %s"), | ||
|
zeroshade marked this conversation as resolved.
Outdated
|
||
| dbc.Version, latestVer, "https://github.com/columnar-tech/dbc/releases/tag/"+latestVer.String(), "https://docs.columnar.tech/dbc/getting_started/installation/") | ||
|
zeroshade marked this conversation as resolved.
Outdated
|
||
| lipgloss.Println() | ||
| } | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -41,9 +41,7 @@ func GetUserConfigPath() (string, error) { | |
| return finalDir, nil | ||
| } | ||
|
|
||
| // 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) { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Doesn't this change the location of It it helps to rename these funcs, I think paths.go just needs two functions:
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 |
||
| dir := os.Getenv("XDG_DATA_HOME") | ||
| if dir == "" { | ||
| switch runtime.GOOS { | ||
|
|
@@ -58,7 +56,7 @@ func GetCredentialPath() (string, error) { | |
| if err != nil { | ||
| return "", fmt.Errorf("failed to get user config directory: %w", err) | ||
| } | ||
| return filepath.Join(userdir, "credentials", "credentials.toml"), nil | ||
| return userdir, nil | ||
| default: // unix | ||
| home, err := os.UserHomeDir() | ||
| if err != nil { | ||
|
|
@@ -70,5 +68,16 @@ func GetCredentialPath() (string, error) { | |
| return "", errors.New("path in $XDG_DATA_HOME is relative") | ||
| } | ||
|
|
||
| return filepath.Join(dir, "dbc", "credentials", "credentials.toml"), nil | ||
| return filepath.Join(dir, "dbc"), nil | ||
| } | ||
|
|
||
| // Directory for dbc credentials. This dir is distinct from GetUserConfigPath | ||
| // except for on macOS where it's the same | ||
| func GetCredentialPath() (string, error) { | ||
| dir, err := GetDbcConfigPath() | ||
| if err != nil { | ||
| return "", fmt.Errorf("failed to get dbc config path: %w", err) | ||
| } | ||
|
|
||
| return filepath.Join(dir, "credentials", "credentials.toml"), nil | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.