Skip to content

Commit bcc2654

Browse files
committed
Skip online repository interaction for packaged builds
Enable TiUP to operate correctly and robustly when installed via an external package manager (e.g., Debian, RPM, Homebrew). Allow TiUP to run without requiring network access to its online repository for initial setup or updates, which is crucial for production systems and environments with restricted connectivity. Achieve this by introducing the boolean flag `IsPackagedBuild`, which is intended to be hard-coded to `true` in binaries produced by package maintainers. When `IsPackagedBuild` is true: - The initial environment setup skips connecting to the online repository, relying instead on local files. - The automatic update check before running a component is skipped. - A message is printed to stderr indicating that online interaction is skipped, informing the user of the different behavior. - Functions related to *forced* self-updating TiUP return an error, explicitly disabling these operations in packaged builds. Users should still be able to install/update when explicitly running those commands. - Use the system-wide location `/usr/share/tiup/root.json` for initial trust setup and assume this file came with the package. This aligns with typical system package practices.
1 parent e769cc5 commit bcc2654

File tree

5 files changed

+37
-13
lines changed

5 files changed

+37
-13
lines changed

cmd/list.go

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,8 @@ func (lr *listResult) print() {
9090
}
9191

9292
func showComponentList(env *environment.Environment, opt listOptions) (*listResult, error) {
93-
if !opt.installedOnly {
93+
// Skip online update in packaged builds
94+
if !opt.installedOnly && !environment.IsPackagedBuild {
9495
err := env.V1Repository().UpdateComponentManifests()
9596
if err != nil {
9697
tui.ColorWarningMsg.Fprint(os.Stderr, "Warn: Update component manifest failed, err_msg=[", err.Error(), "]\n")
@@ -182,8 +183,16 @@ func showComponentList(env *environment.Environment, opt listOptions) (*listResu
182183
}
183184

184185
func showComponentVersions(env *environment.Environment, component string, opt listOptions) (*listResult, error) {
186+
versions, err := env.Profile().InstalledVersions(component)
187+
if err != nil {
188+
return nil, err
189+
}
190+
installed := set.NewStringSet(versions...)
191+
192+
var cmpTable [][]string
193+
cmpTable = append(cmpTable, []string{"Version", "Installed", "Release", "Platforms"})
194+
185195
var comp *v1manifest.Component
186-
var err error
187196
if opt.installedOnly {
188197
comp, err = env.V1Repository().LocalComponentManifest(component, false)
189198
} else {
@@ -193,15 +202,6 @@ func showComponentVersions(env *environment.Environment, component string, opt l
193202
return nil, errors.Annotate(err, "failed to fetch component")
194203
}
195204

196-
versions, err := env.Profile().InstalledVersions(component)
197-
if err != nil {
198-
return nil, err
199-
}
200-
installed := set.NewStringSet(versions...)
201-
202-
var cmpTable [][]string
203-
cmpTable = append(cmpTable, []string{"Version", "Installed", "Release", "Platforms"})
204-
205205
platforms := make(map[string][]string)
206206
released := make(map[string]string)
207207

pkg/environment/env.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ import (
3333
var (
3434
// ErrInstallFirst indicates that a component/version is not installed
3535
ErrInstallFirst = errors.New("component not installed")
36+
37+
// IsPackagedBuild is hard-coded to 'true' in binaries produced by packaged builds
38+
// (e.g., Debian, RPM, Homebrew) to change their behavior to be more like real system programs.
39+
IsPackagedBuild = true
3640
)
3741

3842
// Mirror return mirror of tiup.
@@ -81,6 +85,13 @@ func InitEnv(options repository.Options, mOpt repository.MirrorOptions) (*Enviro
8185
return env, nil
8286
}
8387

88+
// Always initialize the repository. In packaged builds,
89+
// specific functions (like automatic updates) will check IsPackagedBuild
90+
// and adapt their behavior. Explicit install/list should work.
91+
if IsPackagedBuild {
92+
fmt.Fprintln(os.Stderr, "Online version check and repository interaction skipped in packaged build.")
93+
}
94+
8495
initRepo := time.Now()
8596
profile := localdata.InitProfile()
8697

@@ -148,6 +159,9 @@ func (env *Environment) UpdateComponents(specs []string, nightly, force bool) er
148159

149160
// SelfUpdate updates TiUP.
150161
func (env *Environment) SelfUpdate() error {
162+
if IsPackagedBuild {
163+
return errors.New("tiup self-update is disabled in this packaged build")
164+
}
151165
if err := env.v1Repo.DownloadTiUP(env.LocalPath("bin")); err != nil {
152166
return err
153167
}

pkg/exec/run.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,11 @@ func PrepareCommand(p *PrepareCommandParams) (*exec.Cmd, error) {
173173
}
174174

175175
func cmdCheckUpdate(component string, version utils.Version) {
176+
// Skip online check in binaries installed by a package manager
177+
if environment.IsPackagedBuild {
178+
return
179+
}
180+
176181
const (
177182
slowTimeout = 1 * time.Second // Timeout to display checking message
178183
cancelTimeout = 2 * time.Second // Timeout to cancel the check

pkg/repository/v1_repository.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -541,6 +541,11 @@ func (r *V1Repository) PurgeTimestamp() {
541541
// has the same value of our local one. (not hashing the snapshot file itself)
542542
// Return weather the manifest is changed compared to the one in local ts and the FileHash of snapshot.
543543
func (r *V1Repository) fetchTimestamp() (changed bool, manifest *v1manifest.Manifest, err error) {
544+
// Ideally a repository check was not mandatory to simply run a program, but as it is,
545+
// an uninitialized repository would cause a nil pointer dereference, so return an error.
546+
if r == nil {
547+
return false, nil, errors.New("repo is nil")
548+
}
544549
// check cache first
545550
if r.timestamp != nil {
546551
return false, r.timestamp, nil

pkg/repository/v1manifest/local_manifests.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -198,9 +198,9 @@ func (ms *FsManifests) load(filename string) (string, error) {
198198
file, err := os.Open(fullPath)
199199
if err != nil {
200200
if os.IsNotExist(err) {
201-
// Use the hardcode root.json if there is no root.json currently
201+
// Use system root.json if none was found in the local profile directory
202202
if filename == ManifestFilenameRoot {
203-
initRoot, err := filepath.Abs(filepath.Join(ms.profile.Root(), "bin/root.json"))
203+
initRoot, err := filepath.Abs(filepath.Join("/usr/share/tiup/root.json"))
204204
if err != nil {
205205
return "", errors.Trace(err)
206206
}

0 commit comments

Comments
 (0)