msbuild fails with successful robocopy exit code - msbuild

My msbuild script fails even if copying files is successful. If robocopy command exitcode < 8, it means that files copied. So how can I say to msbuild script IgnoreExitCode if exit code < 8?
I set IgnoreExitCode to true, but what if it's real error?
<Exec Command="robocopy $(SourceDir) $(DestinationDir) /mir /mt /xd $(ExcludeDir)" IgnoreExitCode="true" />

Use ExitCode output parameter of Exec task and ContinueOnError parameter instead of IgnoreExitCode:
<Exec ContinueOnError="True" Command="robocopy $(SourceDir) $(DestinationDir) /mir /mt /xd $(ExcludeDir)">
<Output TaskParameter="ExitCode" PropertyName="ErrorCode"/>
</Exec>
<Error Condition="$(ErrorCode) > 8" Message="Robocopy failed"/>

Try this workaround:
(robocopy $(SourceDir) $(DestinationDir) /mir /mt /xd $(ExcludeDir)) ^& IF %ERRORLEVEL% LEQ 1 exit 0

Related

dotnet publish -o ./dist does not set $OutDir or $OutPath in msbuild

I Have a file move event which I want to trigger after a publish
<Target Name="CopyEmailTemplates" AfterTargets="AfterPublish">
<ItemGroup>
<TemplatesFolder Include="Views\EmailTemplates\*.cshtml" />
</ItemGroup>
<Copy SourceFiles="#(TemplatesFolder)" DestinationFolder="$(OutDir)Views\EmailTemplates\" />
</Target>
I've confirmed that the command does not return the publish directory with this target:
<Target Name="OutputTest" AfterTargets="AfterPublish">
<Exec Command="echo OutPath: $(OutputPath)" />
<Exec Command="echo OutDir: $(OutDir)" />
</Target>
Expected:
OutDir is set to dist/
Actual behavior:
OutDir is set to bin/Release/netcoreapp2.0/
I am using: .NET Command Line Tools (2.1.4) on osx.10.12-x64
Publish is a two-step process. The project is built using normal build settings and then published to $(PublishDir). Use this property wherever you need to know the path of the publish output.
Self answering in hopes to prevent future headaches for people.
The dotnet publish -o ./dist command will set the $(PublishDir) variable in msbuild.
dotnet build -o ./dist does however set $(OutDir)
To be more explicit with our build I now use the msbuild command
dotnet publish -o ./dist -c Release
Becomes:
dotnet msbuild /t:publish /p:PublishDir=dist/ /p:Configuration=Release

Execute npm with ant

I want to automate the build of an application with frontend and backend. To do this I want to use maven with ant for platform independent copy and cli tasks. With some cli's like docker ... this works. But this does not work for cli's provided by npm or npm itself.
<exec executable="docker">
<arg line="version"/>
</exec>
<!--Works-->
<exec executable="C:\Program Files\nodejs\npm.cmd">
<arg line="version"/>
</exec>
<!--Doesn't work-->
<exec executable="npm">
<arg line="version"/>
</exec>
As seen in the second example, the script works if I specify the full path to the npm.cmd. But this should work at least on windows and unix. So specifying the full path is not an option.
Is there any way to run npm and its modules from ant?
Late edit:
The real problem was, that the windows node installer also placed a file named npm into the bin folder which is a bash script meant for cygwin. The npm bin folder was added to the 'global' PATH env var and the windows cmd did pick up the correct binary because it uses the PATHEXT env var to determine what is executable and what not. The ant exec plugin does not use PATHEXT and just executes the first file named npm which fails. The Solution was to rename the plain npm file in the path. This way ant sees the npm.cmd file first and everything runs smoothly.
I know this is old, but this is what I have, for others in the future. Works in our mac, unix, and windows boxes.
<macrodef name="exec-node">
<attribute name="module" description="The name of the NodeJS module to execute" />
<attribute name="failonerror" default="true" description="Fail if the exit code is not 0" />
<attribute name="dir" description="Directory to execute task" />
<element name="args" implicit="yes" description="Argument to pass to the exec task" />
<sequential>
<exec executable="cmd.exe" dir="#{dir}" failonerror="#{failonerror}" osfamily="winnt">
<arg line="/c #{module}" />
<args />
</exec>
<exec executable="#{module}" dir="#{dir}" failonerror="#{failonerror}" osfamily="unix" logError="true">
<args />
</exec>
</sequential>
</macrodef>
Then things like this can work
<exec-node dir="${node.project.dir}" module="npm" failonerror="true" >
<arg value="run" />
<arg value="lint" />
</exec-node>
You can of course hardcode module as npm, or default it, but I use this with npm and npx.
From what I can gather, its not possible to call npm directly through the antrun plugin.
I did manage to get it tu run by calling cmd (on windows) with the /c argument.
Example:
<exec executable="cmd">
<arg line="/c npm run babel -- src/main/webapp/js/es6/ --presets babel-preset-es2015 --out-dir src/main/webapp/js/"/>
</exec>
This works for me on Windows:
<exec executable="npm.cmd">
<arg value="version"/>
</exec>
If you like to use npm you should take a look at the frontend-maven-plugin.

MSBuild and Webpack

I am developing an Angular2 application in VS2015 and have a webpack bundling and minification environment set up for the same.
This is my webpack.conf.js
switch (process.env.NODE_ENV) {
case 'prod':
case 'production':
module.exports = require('./config/webpack.prod');
break;
case 'test':
case 'testing':
//module.exports = require('./config/webpack.test');
break;
case 'dev':
case 'development':
default:
module.exports = require('./config/webpack.dev');
}
I have also installed a webpack task runner which invokes this with the following commands
cmd /c SET NODE_ENV=development&& webpack -d --color
and
cmd /c SET NODE_ENV=production&& webpack -p --color
The setup seems to work fine. However, I want to integrate this with my TFS builds CI. The webpack command should fire after the project is built and report a build failure incase the webpack build fails. I have tried to incorporate the following code in my .csproj file
<Target Name="AfterBuild">
<Exec Condition="$(Configuration) == 'Debug'" Command="cmd /c SET NODE_ENV=production&& webpack -p --color">
</Exec>
</Target>
It failed with an error 9009
After that I tried, starting the command up from the node_modules folder where webpack was installed
<Target Name="AfterBuild">
<Exec Condition="$(Configuration) == 'Debug'" Command="./node_modules/.bin cmd /c SET NODE_ENV=production&& webpack -p --color">
</Exec>
</Target>
still in vain. Even if I get this to work, I am not sure if it would cause the VS build to fail if it encounters an error in webpack.
How do I go ahead with this?
Put different scripts in package.json for development and production mode. Then on 'AfterBuild' event of visual studio, call those scripts on different configurations.
Add following two scripts, 'buildDev' and 'buildProd' in package.json:
"scripts": {
"buildDev": "SET NODE_ENV=development && webpack -d --color",
"buildProd": "SET NODE_ENV=production && webpack -p --color",
}
In AfterBuild events of visual studio add these two conditional commands:
<Target Name="AfterBuild">
<Exec Condition="$(Configuration) == 'Debug'" Command="npm run buildDev" />
<Exec Condition="$(Configuration) == 'Release'" Command="npm run buildProd" />
</Target>
And finally webpack.conf.js like this:
switch (process.env.NODE_ENV.trim()) {
case 'prod':
case 'production':
module.exports = require('./config/webpack.prod');
break;
case 'dev':
case 'development':
default:
module.exports = require('./config/webpack.dev');
break;
}
Important Note: Make sure to use trim() function with process.env.NODE_ENV as cmd will treat the blank space in the command "SET NODE_ENV=development && webpack -d --color as character and append it in NODE_ENV variable. So when we are setting it as 'development', it actually gets set as (development + whitespace).
For TFS CI build, you can refer to these steps to achieve your requirement.
Add npm step
Add Command Line step
Note: There is –bail argument, which is required otherwise the step/task will be succeed even though webpack command throws exception.
Also, you can add variable in build definition (variable tab)

Setting a robocopy log file to a variable

Robocopy is stalling when reading options /Z /MIR and LOG+ from a variable.
ROBOCOPY %BACKUP_FAVS% %PATH_FAVS% %R_OPT%
Where R_OPT= /Z /MIR /LOG+:%RLOG_Restore% and is set by:
IF %ACTION%==Restore SET R_OPT=/Z /MIR /LOG+:%RLOG_Restore%
Where RLOG_Restore is set by:
SET RLOG_Restore=%BACKUP_FOLDER%\Robocopy_Log_Restore.txt
When the code executes, its stops at the robocopy line and does not continue on to the code after the robocopy line. The robocopy line returns:
Log File : H:\VDI_Backup\Robocopy_Log_Restore.txt
An Echo of the Robocopy results in:
ROBOCOPY H:\VDI_Backup\Favorites C:\user\Favorites /Z /MIR /LOG+:H:\VDI_Backup\Robocopy_Log_Restore.txt
I tried enclosing /Z /MIR /LOG+:%RLOG_Restore% in quotes resulting in invalid parameters error. Where is this going wrong?
The problem is access denied to the destination folder.
Nothing wrong with robocopy code.

Exec Task in MSBuild for execution of command on remote machine

I am using following command to install a service via MSBuild file. This works great
<Exec Command= 'c:\test\myService.Appservices.exe install' ContinueOnError='false' />
But the above command install the service on local machine. I want to install the service on a remote machine. How can I specify the machine name using this command?
As per Mike Vine's comment, MSBuild doesn't include tools for remote execution. You could however use something like psexec. e.g.
<Exec Command='psexec -accepteula -s \\RemoteServer "C:\Path To EXE on Remote Machine\my.EXE"' IgnoreExitCode="false" ContinueOnError="false" Timeout="600000" >
<Output TaskParameter="ExitCode" PropertyName="exitCode1"/>
</Exec>