Code Monkey home page Code Monkey logo

Comments (11)

sayedihashimi avatar sayedihashimi commented on June 12, 2024

OK I sent you a PR #2 with a bunch of changes. Note: since I don't have this working on my box I never was able to actually test this, but I tried to be careful to not introduce any errors.

Can I make the targets extensible in some way? Actually I wrote some code for Bower, Grunt, Gulp and Tsd...I missed Karma for example. I will add it as soon as possible but what if I would like to let user extend the process?

I have added DependsOn properties for each of your targets

I changed the targets to use Before something instead of target override. Is this the right way to do this thing?

I modified it to use BuildDependsOn and CleanDependsOn instead of BeforeTargets & AfterTargets.

I'd like to perform a good research of tools before emit errors. For example, for NodeJs I'd like to search in PATH (npm), then in .bin folder (for some nuget packages). For Bower I'd like to search in PATH, .bin folder and node_modules/.bin/. If nothing, emit a warning (the target failed...)
I'd like to avoid a init.ps1 script and set the right path for property every time., but looks like MsBuild properties can be only constants or simple powershell scripts. How to overtake this problem?

I think I'm following you but not 100% sure. Let me re-phrase my understanding. When accessing $(npm) you'd like to perform some search/validation to ensure that it's on the box first. In MSBuild you're looking to do this with some property functionality but you are not finding that.

You're correct that properties can't be extended in this way. What I would do instead of this is to create a target, let's call it ValidateNodeTools. Then before your targets execute you ensure that the ValidateNodeTools target is run. In your case just add that target to RestoreNodeJsPackagesDependsOn and RunJsBuildTasksDependsOn. Then inside of that target you can search for npm and populate the Npm property, which callers access via $(npm). If you don't find it you throw an error. Does that make sense?

Let me know if you have any more questions.

from nodejsmsbuild.

XVincentX avatar XVincentX commented on June 12, 2024

Hello again,
thank you for your pull request. I've downloaded and studied it and here are my considerations about it.

Does DelFolder have a dependency on RoboCopy? If so that may not work. Best option would be to convert that to standard MSBuild.

Yes I know, but as I explained in the original article:

You may see that node_modules directories and subdirectories are deleted using a DelFolder script and not through the remove dir. This is because node_modules are very deep directory and RemoveDir target cannot delete paths longer that 256 characters. For this reason, I use to include a script in my source control (not in the project, however) with these lines...

Do you see a better way to handle this use case?

What's the intention of .\ here? I don't think this should be .\ but I just
took from the previous version.

I wrote it to have the full path of executable... ./.bin/gulp...what is wrong with that?

Then inside of that target you can search for npm and populate the Npm property, which callers access via $(npm) . If you don't find it you throw an error. Does that make sense?

Yes it does, but I have not understood how to search for node tools from MsBuild task! Am I missing something?

For this type of behavior I don't believe you should be populating any known items, instead create a new one and delete from there.

I did not understand this. Should I create a new item for each folder to delete and make CleanNodeJsFiles target depending from them?

I have (of course) accepted your pull request!
Regards,
V.Chianese

from nodejsmsbuild.

sayedihashimi avatar sayedihashimi commented on June 12, 2024

Yes I know, but as I explained in the original article:
...
Do you see a better way to handle this use case?

OK I see what you mean now. I think you should be able to achieve the same result without using robocopy. Try this, instead of Delete or RemoveDir tasks try using the Exec task and calling rmdir. So it would be something like <Exec Command="rmdir c:\path /S /Q" />

I wrote it to have the full path of executable... ./.bin/gulp...what is wrong with that?

What is the ./ relative to? Are you expecting the build to be invoked from a certain directory? You should test with a variety of configurations.

Yes it does, but I have not understood how to search for node tools from MsBuild task! Am I missing something?

OK let me try and explain this a bit better. I saw on your readme.md the following content

<PropertyGroup>
  <HasNpm>$(Get-Command "npm" -errorAction SilentlyContinue || Get-Command ".bin/npm" -errorAction SilentlyContinue)</HasNpm>
  <HasGulp>$(Get-Command "gulp" -errorAction SilentlyContinue || Get-Command ".bin/gulp" -errorAction SilentlyContinue) || Get-Command ".node_modules/.bin/gulp" -errorAction SilentlyContinue)</HasGulp>
  <HasGrunt>$(Get-Command "grunt" -errorAction SilentlyContinue || Get-Command ".bin/grunt" -errorAction SilentlyContinue) || Get-Command ".node_modules/.bin/grunt" -errorAction SilentlyContinue)</HasGrunt>
  <HasBower>$(Get-Command "bower" -errorAction SilentlyContinue || Get-Command ".bin/bower" -errorAction SilentlyContinue) || Get-Command ".node_modules/.bin/bower" -errorAction SilentlyContinue)</HasBower>
  <HasTsd>$(Get-Command "tsd" -errorAction SilentlyContinue || Get-Command ".bin/tsd" -errorAction SilentlyContinue) || Get-Command ".node_modules/.bin/tsd" -errorAction SilentlyContinue)</HasTsd>
</PropertyGroup>

<!--Draft, it does not work yet-->

As you state this does not work. Before I go into how to solve this let me define two things to ensure we are on the same page. A Task is a single unit of work in MSBuild and it's backed by a .NET class that implements ITask. For example <Message ..., <Copy ..., <Csc ..., etc. Tasks must be called inside of a Target. You can think of a Target as a block of tasks that will execute one after another (simplified definition).

OK so the question is 'How can I search for tools like npm, bower, etc' in MSBuild. You can setup a target, let's call it FindTools, which is responsible for discovering the tools that your build depends on. This target can be as smart or as stupid about discovering those as you want. Let's take a look at a few examples. The idea is since Properties cannot be smart we have to encapsulate the logic in a Target and then populate the properties which point to the tools.

Below is a version that just hard codes everything.

<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="RunTools" ToolsVersion="4.0">
  <Target Name="FindTools">
    <PropertyGroup>
      <npm>c:\temp\npm</npm>
      <bower>c:\temp\bower</bower>
      <grunt>c:\temp\grunt</grunt>
    </PropertyGroup>
  </Target>

  <Target Name="RunTools" DependsOnTargets="FindTools">
    <Message Text="
Npm: $(npm)
Bower: $(bower)
Grunt: $(grunt)" Importance="high"/>
  </Target>
</Project>

If you can search for a few known paths then you can add some conditions on the properties. For example

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="RunTools" ToolsVersion="4.0">
  <Target Name="FindTools">
    <PropertyGroup>
       <!--Check for npm in project .tools\ folder--> 
      <npm Condition=" Exists('$(MSBuildProjectDirectory)\.tools\npm')">$(MSBuildProjectDirectory)\.tools\npm</npm>
       <!--default to global install--> 
      <npm Condition=" '$(Npm)'=='' ">c:\temp\npm</npm>

      <bower Condition=" Exists('$(MSBuildProjectDirectory)\.tools\bower')">$(MSBuildProjectDirectory)\.tools\bower</bower>
      <bower Condition=" '$(bower)'=='' ">c:\temp\bower</bower>

      <grunt Condition=" Exists('$(MSBuildProjectDirectory)\.tools\grunt')">$(MSBuildProjectDirectory)\.tools\grunt</grunt>
      <grunt Condition=" '$(grunt)'=='' ">c:\temp\grunt</grunt>
    </PropertyGroup>
  </Target>

  <Target Name="RunTools" DependsOnTargets="FindTools">
    <Message Text="
Npm: $(Npm)
Bower: $(Bower)
Grunt: $(Grunt)" Importance="high"/>
  </Target>  
</Project>

In this case you look for npm under the project first using $(MSBuildProjectDirectory)\.tools\npm, if it's there you populate the npm property with it. If not then populate it with the default value for the global install. You can also do things like look in the registry for the location. You can see how I use this in this sample

  <PropertyGroup>
    <WebDeployPackageName Condition=" '$(WebDeployPackageName)'=='' ">$(MSBuildProjectName).zip</WebDeployPackageName>
    <!--Unless specified otherwise, the tools will go to HKLM\SOFTWARE\Microsoft\IIS Extensions\MSDeploy\1 to get the installpath for msdeploy.exe.-->
    <MSDeployPath Condition="'$(MSDeployPath)'==''">$(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\IIS Extensions\MSDeploy\3@InstallPath)</MSDeployPath>
    <MSDeployPath Condition="'$(MSDeployPath)'==''">$(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\IIS Extensions\MSDeploy\2@InstallPath)</MSDeployPath>
    <MSDeployPath Condition="'$(MSDeployPath)'==''">$(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\IIS Extensions\MSDeploy\1@InstallPath)</MSDeployPath>
    <MSDeployExe Condition=" '$(MSDeployExe)'=='' ">$(MSDeployPath)msdeploy.exe</MSDeployExe>
  </PropertyGroup>

As you can see the above samples using Conditions on properties is limiting and can be cumbesome. If you need to perform complex logic you can create a Task, which you can call in the FindTools target. When you call the task you can have it output the path to the tool and then you populate the properties using that. For example.

<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="RunTools" ToolsVersion="4.0">

  <!-- Import custom tasks -->
  <UsingTask TaskName="FindNpm" AssemblyFile="myassembly.dll"/>
  <UsingTask TaskName="FindBower" AssemblyFile="myassembly.dll"/>
  <UsingTask TaskName="FindGrunt" AssemblyFile="myassembly.dll"/>

  <!-- Here we call custom tasks to do complex look ups -->
  <Target Name="FindTools">
    <FindNpm>
      <Output PropertyName ="npm" TaskParameter="Npm"/>
    </FindNpm>

    <FindBower>
      <Output PropertyName ="bower" TaskParameter="Npm"/>
    </FindBower>

    <FindGrunt>
      <Output PropertyName ="npm" TaskParameter="Grunt"/>
    </FindGrunt>

  </Target>

  <Target Name="RunTools" DependsOnTargets="FindTools">
    <Message Text="
Npm: $(npm)
Bower: $(bower)
Grunt: $(grunt)" Importance="high"/>
  </Target>
</Project>

Here FindNpm,FindBower, and FindGrunt would be custom MSBuild tasks that you write in C# (or any other .net lang) that is called from the target. So at that point you can do any searching that's possible with .net.

I hope that clears it up :)

I did not understand this. Should I create a new item for each folder to delete and make CleanNodeJsFiles target depending from them?

I was just saying don't populate '''TypeScriptGenerated'''. I've already made the changes for this.

FYI once we are done if you could summarize the leanings in a blog post that would be wonderful. Hopefully we can share with others besides those just looking here.

from nodejsmsbuild.

XVincentX avatar XVincentX commented on June 12, 2024

Hello Sayed,
here are the daily updates

OK I see what you mean now. I think you should be able to achieve the same result without using robocopy. Try this, instead of Delete or RemoveDir tasks try using the Exec task and calling rmdir. So it would be something like

It still does not work. It returns an error saying me the path is too long.

If you can search for a few known paths then you can add some conditions on the properties
This is a good idea. I think that checking these 3 paths should be enough

  • projectpath/.bin/
  • projectpath/node_modules/.bin/
  • %PATH%

While the first two are easy to, I have no idea of how checking that. _Exists('npm') returns false since it checks for file existence. How would you do that? I'd like to avoid C# tasks, if possible. The only idea I have got now is to use Exec tasks and check for return code. If != 1 the command does not exists.

FYI once we are done if you could summarize the leanings in a blog post that would be wonderful. Hopefully we can share with others besides those just looking here.

Yes of course I'm available to share all knowledge you're giving to me in this journey.
Have a nice day
V.Chianese

from nodejsmsbuild.

sayedihashimi avatar sayedihashimi commented on June 12, 2024

It still does not work. It returns an error saying me the path is too long.

Sorry about that, I thought it was possible. I spent some time trying to figure out a method w/o an external tool but it doesn't look possible as you stated.

Searching %path% is not going to be reliable. I'd look through any possible locations and then provide a good error stating how users can specify the value. Trying to see the error code may work as well.

from nodejsmsbuild.

XVincentX avatar XVincentX commented on June 12, 2024

Hello again,
I've just push some new commits about tools search.
As you will see, I created 2 targets (1 for npm tools, one for task tools) and are found evaluating answer of tool -v. If not found, I will try to search on some wellknown folders.

I will make some tests as soon as possible.
I decided to have fun with appveyorn, so I'm now having a CI system: Build status that will publish a nuget package in a personal feed.

Let me know what you think about this,
V.Chianese

from nodejsmsbuild.

sayedihashimi avatar sayedihashimi commented on June 12, 2024

I looked at the latest version and it looks good. The only thing I found is BowerParam needs a condition.

AppVeyor is cool, I haven't tried the custom NuGet feed but it sounds useful. I may employ it.

from nodejsmsbuild.

XVincentX avatar XVincentX commented on June 12, 2024

Great,
looks like we have now got a real testable version.
I've made the change for Bower param and today I will make some general tests.

And later? Are we going to spread it somehow?

from nodejsmsbuild.

XVincentX avatar XVincentX commented on June 12, 2024

I added a check for git presence, because without it bower and ysd cannot work at all

from nodejsmsbuild.

sayedihashimi avatar sayedihashimi commented on June 12, 2024

Sorry about the delay here. I'm not using these tools too much today so I'm not sure how much I can help out. I saw you had a specific need for some MSBuild so I was chipping in from that perspective.

from nodejsmsbuild.

XVincentX avatar XVincentX commented on June 12, 2024

Got it.
I opened a discussion here, I hope we may find an agreement! 👍

from nodejsmsbuild.

Related Issues (1)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.