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

Exception while trying to run Cake.MinVer with minver-cli installed as global tool #5

Closed
dario-griffo-cko opened this issue Nov 19, 2020 · 4 comments · Fixed by #7
Closed
Labels
bug Something isn't working
Milestone

Comments

@dario-griffo-cko
Copy link

dario-griffo-cko commented Nov 19, 2020

I have been using the Cake.MinVer as local tool without problems, but today decided to give a try as a global tool and cannot run it.
What did I do?

  • make sure there is no version of minver installed at all
  • install minver as global tool
dotnet tool install --global cake.tool
dotnet tool install --global minver-cli
  • init a repository
mkdir test
cd test
git init .
  • add a cake file with the example project in the readme of the repo named build.cake
#addin "nuget:?package=Cake.MinVer&version=0.1.0"

var version = MinVer();

Task("Example")
    .Does(context =>
{
    context.Information($"Version: {version.Version}");
    context.Information($"Major: {version.Major}");
    context.Information($"Minor: {version.Minor}");
    context.Information($"Patch: {version.Patch}");
    context.Information($"PreRelease: {version.PreRelease}");
    context.Information($"BuildMetadata: {version.BuildMetadata}");
});

RunTarget("Example");
  • create first tag
git add .
git commit -m"test"
git tag 0.1.0
  • run minver to check all is good
minver

Result

MinVer: Using { Commit: 2d5413e, Tag: '0.1.0', Version: 0.1.0, Height: 0 }.
MinVer: Calculated version 0.1.0.
0.1.0
  • run cake
dotnet cake

Result:

Could not execute because the specified command or file was not found.
Possible reasons for this include:
  * You misspelled a built-in dotnet command.
  * You intended to execute a .NET program, but dotnet-minver does not exist.
  * You intended to run a global tool, but a dotnet-prefixed executable with this name could not be found on the PATH.
Error: One or more errors occurred. (MinVer: Process returned an error (exit code 1).)
        MinVer: Process returned an error (exit code 1).

change the cake file to be

Task("Example")
    .Does(context =>
{
    context.Information("Hello");
});

RunTarget("Example");
  • run cake
dotnet cake

Result:

========================================
Example
========================================
Hello

Task                          Duration
--------------------------------------------------
Example                       00:00:00.0136457
--------------------------------------------------
Total:                        00:00:00.0136457
  • install minver cli as local tool
dotnet new tool-manifest --force
dotnet tool install minver-cli
  • now revert the file to the version with Cake.MinVer and run cake again
  • it works
@dario-griffo-cko
Copy link
Author

I wonder is this is more a cake issue...

@augustoproiete
Copy link
Member

@dario-griffo-cko Thanks for reporting this and for the detailed repro! I see the same error on my end.

I'll investigate this over the weekend and see if there's an easy fix, but at first glance it seems that the issue is on my end. I think I missed the difference between running global tools and local tools and I'm always assuming it's a local tool.

When installing MinVer as a local tool, you can only run it using either dotnet minver or dotnet tool run minver
However, when installing MinVer as a global tool, you can only run it using minver

In Cake.MinVer, I'm running dotnet minver and that's why it fails if MinVer is installed as a global tool.

@augustoproiete
Copy link
Member

augustoproiete commented Nov 22, 2020

@dario-griffo-cko I've just released a pre-release package on NuGet that should fix the issue of running MinVer as a global tool. If you have a chance, could you take it for a spin?

I'd also appreciate any feedback on the implementation, if you think there's room for improvement.

#addin "nuget:?package=Cake.MinVer&version=0.2.0-preview&prerelease=true"

var version = MinVer();

Task("Example")
    .Does(context =>
{
    context.Information($"Version: {version.Version}");
    context.Information($"Major: {version.Major}");
    context.Information($"Minor: {version.Minor}");
    context.Information($"Patch: {version.Patch}");
    context.Information($"PreRelease: {version.PreRelease}");
    context.Information($"BuildMetadata: {version.BuildMetadata}");
});

RunTarget("Example");

I'll do some more tests and I'm planning to release an RTM version some time tomorrow.


Implementation

I tried to do what I thought Microsoft was doing for me automatically (but as you found out, they weren't) of using the tool that is closer to the project, i.e.:

  • If MinVer is installed as a local tool in the repo, use that local tool (closer is better)
  • If MinVer is not installed as a local tool in the repo, but a global tool is, then use the global tool

It's easy to detect if MinVer is installed as a global tool (or is in the path), but it doesn't seem very easy to detect if MinVer is installed as a local tool - which makes giving priority to the local tool a little challenging.

I considered a few different approaches:

  1. 😞 Running dotnet tool list and parsing the result, in an attempt to detect if the local tool is there
  2. 🤢 Running dotnet minver, and if it doesn't work assume the local tool is not there, and try minver next
  3. 🙅‍♂️ Parsing the .config\dotnet-tools.json and look for minver-cli in the list of commands (probably a bad idea as I can't guarantee the working directory is the same where the tool manifest is...)
  4. 🥾 Use Cake.DotNetTool.Module to run the dotnet tool instead (also probably a bad idea as it requires manual bootstrapping of the Cake script right now, until Cake v1.0.0 is out...)

Whilst I didn't particularly love any of these approaches, I ended up going with number 2. Number 1 seemed cleaner than all the others at first but, again, because I believe this tool is going to be used as a local tool most of the time, I didn't want to add the overhead of dotnet tool list if it's going to hit the majority of users.

Thus, in a nutshell, I am running dotnet minver first, and if that doesn't work (exit code != 0) I fallback to running minver and see if that works, before giving up and throwing an error. Not perfect, but I can't think of a better approach in the state that dotnet tools are in today.

I added a couple more settings to tweak this behavior, so that if you know you're running a global tool in the path, or if you are running a global tool from a specific known location (tool-path), you can tell Cake.MinVer to skip trying to run the local tool, and run the global tool first, and you can also disable the fallback as well:

var settings = new MinVerSettings
{
    // Runs global tool first, fallback to local tool (unless NoFallback = true). Defaults to false.
    PreferGlobalTool = true,

    // Disable fallback in case of errors (i.e. only run one of the tools, either local (default)
    // or global (if PreferGlobalTool = true)). Defaults to false.
    NoFallback = true,
};

var version = MinVer(settings);

or the same thing but with the extension methods:

var version = MinVer(settings => settings
    .WithPreferGlobalTool()
    .WithNoFallback());

I'll update the README after PR #7 is merged and before an RTM version is released:

@augustoproiete augustoproiete added the bug Something isn't working label Nov 23, 2020
@augustoproiete augustoproiete added this to the 0.2.0 milestone Nov 24, 2020
@augustoproiete
Copy link
Member

@dario-griffo-cko FYI stable version v0.2.0 released to nuget.org (release notes).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants