Skip to content
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

A new option to allow dotnet tool install should return exit code 0 if tool is already installed #10310

Closed
wli3 opened this issue Jun 6, 2019 · 22 comments
Assignees
Milestone

Comments

@wli3
Copy link

wli3 commented Jun 6, 2019

Continue of https://github.com/dotnet/cli/issues/11259 to make the topic more specific. Even thought "dotnet update" with "--version" could solve the similar issue, but it is hard to discover.

@wli3 wli3 self-assigned this Jun 6, 2019
@wli3
Copy link
Author

wli3 commented Jun 6, 2019

@KathleenDollard @natemcmaster @Shoh

thoughts on having different command to do similar work?
and will adding a flag actually solve the discoverability issue?
what will the flag be called? --skip-if-installed?

@wli3
Copy link
Author

wli3 commented Jun 6, 2019

@cottsak
Copy link

cottsak commented Jun 6, 2019

A new option!!? This should be the default behaviour.

Everyone back to https://github.com/dotnet/cli/issues/9482 please.

@wli3
Copy link
Author

wli3 commented Jun 6, 2019

That would be a breaking change. We would need be to be more careful about it

@natemcmaster
Copy link
Contributor

That would be a breaking change.

Who does it break and how?

@KathleenDollard
Copy link

The break would be that someone is running a script that depends on 1 as the return value.

I'm not sure we got this right, but will need a bit of convincing that no one is relying on the 1 return value.

@DonkeyKongJr
Copy link

If it's not possible to invert the current behaviour I am supporting the additional flag like --skip-if-installed.

@ylorph
Copy link

ylorph commented Jul 18, 2019

What about would be the behavior of "--skip-if-installed " when there is a version mismatch between what's installed and available to install ?

@guitarrapc
Copy link

I wonder how about adding --install option like helm offers helm upgrade --install?

# nothing change as it were today
dotnet tool install
# nothing change as it were today
dotnet tool update
# new: update if exists, install if not exists
dotnet tool update --install

ref: https://helm.sh/docs/helm/#helm-upgrade

@msftgits msftgits transferred this issue from dotnet/cli Jan 31, 2020
@msftgits msftgits added this to the Discussion milestone Jan 31, 2020
@Lonli-Lokli
Copy link

What is the timeline for this option? It's really surprising that multiple installations exits with code 1.
You know, even installers do not do that.

@wli3
Copy link
Author

wli3 commented Apr 30, 2020

Sorry I don't have a timeline

@augustoproiete
Copy link

Would creating a separate command make it easier to get this implemented sooner? E.g. dotnet ensure <toolname> that would:

  • Do nothing if the tool & exact version is installed, and returns 0 exit code
  • Installs the tool if the tool is not yet installed, and returns 0 exit code
  • Updates the tool to the specified version, if a different version is already installed, and returns 0 exit code

e.g.

dotnet tool ensure --global Cake.Tool --version 0.38.5
  • If Cake.Tool is not installed, install it specifically with version 0.38.5
  • If Cake.Tool is already installed, but a lower version, automatically upgrade to 0.38.5
  • If Cake.Tool is already installed, but a higher version, automatically downgrade to 0.38.5

All cases would return 0 as exit code. The only reason for returning a non-zero exit code would be failure to download the tool, write to disk, etc. Exceptions...


A common scenario is CI builds where you just want to make sure that the tools you depend on for the build are present.

@rafaelrruiz
Copy link

Any news on this? The option has been discussed for almost two years.

@Lonli-Lokli
Copy link

@rafaelrruiz you should use dotnet tool restore instead, it will install if deps is missed and skip if already installed.
It requires newer SDK

@augustoproiete
Copy link

@rafaelrruiz you should use dotnet tool restore instead, it will install if deps is missed and skip if already installed.
It requires newer SDK

@Lonli-Lokli This is really not the same thing that is being asked. To use dotnet tool restore, you'd need to have installed the tool beforehand and have a tool manifest in the specified directory. The goal here is to have an idempotent way to install .NET tools with a single command that Just Work™.

@Lonli-Lokli
Copy link

Lonli-Lokli commented May 17, 2021

@augustoproiete it cannot be idempotent even by your definition - first installation should not only install dep, but create tools manifest, while second run not.

There is no silver bullet for now, there was a discussion before and honestly speaking it's better to install dependency first with dotnet install locally, save manifest in git and use dotnet restore after.

@augustoproiete
Copy link

@Lonli-Lokli I'm not sure I follow. Creating the manifest automatically (if installing as local tool) is one of the possible missing steps that would make it idempotent - which is the end goal. And, of course, if installing as a global tool, no manifest needed - but still fails today if tool already exists so another missing piece.

dotnet restore is a workaround for some scenarios only. .NET tools is lacking the ability to have a simple command that does exactly what it's being asked: Ensure that a .NET tool is installed and exit gracefully.

The current state leave us with poor a UX:

image
https://www.nuget.org/packages/dotnet-reportgenerator-globaltool/

You should be able to copy/paste the instructions on how to install a .NET tool, and it should work on any machine regardless if the tool is installed or not, manifest or not... But that's not where we are today.

@wli3 wli3 removed their assignment Sep 29, 2021
@hotchkj
Copy link

hotchkj commented Oct 21, 2022

It's deeply disappointing that all of these related issues have been present, discussed, and unaddressed for two or more years. The scenarios outlined appear to be legitimate use-cases for tooling. The Cake example is a perfect one. As I come to finally try and get off the ancient and now-unsupported Cake bootstrapper, I immediately run into the problems outlined in this and the linked issues (and frankly have no idea which one to comment on - they all describe the same pain - so apologies if this belongs elsewhere).

it's better to install dependency first with dotnet install locally, save manifest in git and use dotnet restore after

I believe this misses the point - nobody wants to update countless Git repos with tooling versions, that's a maintenance nightmare - CI is typically centrally managed, has to be local, and due to the unique way tool manifests are designed, can't just be copied in at CI build time either, as usual build tools would be.

I just want my NET tools installed locally for CI. I don't want to update & maintain 200+ repos with manifest files that can get out of sync in yet another tooling ecosystem. I don't want to pollute build agents with global state, and global tools also just don't work for some cases. I just want the tool installed idempotently. Why is this challenging? The NET SDK itself recognised this immediately, and gave us dotnet-install.ps1. Instant local NET SDK, job done. Where is a local NET tool equivalent?

If I have an existing Git repo with zero or more tool manifests

  • I can't just run dotnet new tool-manifest, it'd either fail or overwrite the existing ones if they're there, and the exit code doesn't tell me anything
  • Only the NET SDK seems to know what is and isn't a valid tool manifest, so I can't even write reliable code to detect it
    • Also why make the decision that it has to be a hardcoded path & name, yet give us a --tool-manifest option in install that will happily take any filename?!?
    • This is not documented, either
  • I need to install a CI-only local tool - but install will fail if there's no manifest or if the tool is already present, with unhelpful exit codes
  • update uninstalls and reinstalls the tool, instead of just ensuring the current version is present, requiring re-download time

I would ask the question more generally as to why the wheel has been reinvented here (again). With NuGet & PackageReference, for example, there's a nice standard convention of 'request package, package gets cached in location that is either global or specified by environment variable, package is installed where requested if it isn't already present'. dotnet tool does not satisfy any of these idempotency criteria today.

@nabeelio
Copy link

nabeelio commented Nov 8, 2022

This behavior also breaks Azure Pipelines if you're using Task Groups several times in one job (with different parameters) which has a tool install step

@ChristopherHaws
Copy link

We had to tell our Azure Pipeline to ignore errors in this task because it returns an error code =(

- task: DotNetCoreCLI@2
  displayName: install sqlpackage
  # dotnet tool install returns error code 1 if the package is already installed =(
  # https://github.com/dotnet/sdk/issues/10310
  continueOnError: true
  inputs:
    command: custom
    custom: tool
    arguments: install -g microsoft.sqlpackage

I would be fine with there being an option to ignore this error to prevent it from being a breaking change, but it really should just be the default behavior. The flag should be if you want it to throw if already installed...

@JL03-Yue
Copy link
Member

JL03-Yue commented Sep 5, 2023

#35088 return exit code 0 if tool is installed when using dotnet tool install

@baronfel
Copy link
Member

I'm going to close this one because the linked PR merged in 8.0.2xx. Thanks for the feedback!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests