cake-build / cake

:cake: Cake (C# Make) is a cross platform build automation system.
https://cakebuild.net
MIT License
3.87k stars 728 forks source link

Bug? "More than one build script specified" when calling build.ps1 with a custom cake script and extra parameters #1248

Open ravensorb opened 7 years ago

ravensorb commented 7 years ago

What You Are Seeing?

When I specify a custom cake script with extra parameters using the build.ps1 bootstrap file, I get the following error:

More than one build script specified.

Note: If I remove the extra parameter that I would like to pass to my script everything works

What is Expected?

Cake executes using the custom cake script file

What version of Cake are you using?

0.13.0

Are you running on a 32 or 64 bit system?

64

What environment are you running on? Windows? Linux? Mac?

Windows

Are you running on a CI Server? If so, which one?

None

How Did You Get This To Happen? (Steps to Reproduce)

.\build.ps1 -Script "3rdPartyPackages.cake" -Settings=3rdPartyPackages.settings.json

Output Log

.\build.ps1 -Script "3rdPartyPackages.cake" -Settings="3rdPartyPackages.settings.json"
Preparing to run build script (3rdPartyPackages.cake)...
Running build script...
& "E:\Projects\tools\Cake\Cake.exe" "3rdPartyPackages.cake" -target="Default" -configuration="Release" -verbosity="Verbose"    -Settings=3rdPartyPackages.settin
gs\.json
More than one build script specified.

Usage: Cake.exe [build-script] [-verbosity=value]
                [-showdescription] [-dryrun] [..]
ravensorb commented 7 years ago

Note sure if this is the most elegant way - however this seems to fix the issue.

Change the end of build.ps1 to look like this

[string] $ScriptArgsFormatted = "";
$ScriptArgs | % { 
    $temp = $_ -Split '=' 
    "{0}=`"{1}`"" -f $temp[0],$temp[1] 
} | % { $ScriptArgsFormatted += $_ }

# Start Cake
Write-Host "Running build script..."
Invoke-Expression "& `"$CAKE_EXE`" `"$Script`" -target=`"$Target`" -configuration=`"$Configuration`" -verbosity=`"$Verbosity`" $UseMono $UseDryRun $UseExperimental $ScriptArgsFormatted"
exit $LASTEXITCODE

It looks like $ScriptArgs is stripping out the " around the name/value pairs. The hard part is, the code I put in place ASSUMES that everything is a name/value pair which is not always true.

kcamp commented 7 years ago

I have seen this before, it seems to come from when the extra param value contains a '.' > .\build.ps1 -Target "my-target" -Version="1.2.3"

this fails with the same output. from the notes i have on my fix, i looked at the cake source and see that the extra arguments will support '-' or '--' syntax.

i was able to change my use-case to the following to get it to work without modifying the build script or the underlying binary. > .\build.ps1 -Target "my-target" --Version="1.2.3"

this is with 0.15.2

ravensorb commented 7 years ago

Cool, I will try that - with luck it will fix both of my issues (I had the version issue too).

phil-scott-78 commented 7 years ago

I have a PR to the cake.resources project that I think might help solve this, but it needs feedback - https://github.com/cake-build/resources/pull/12

More or less it would let you be consistent with the format of the parameters to be 100% powershell rather than mixing single dashes and equal signs depending on the parameter you are passing. It is all PS style.

devlead commented 7 years ago

@ravensorb does the suggestion in this similar stackoverflow post answer work for you? http://stackoverflow.com/questions/40046752/how-do-i-pass-my-own-custom-arguments-to-build-ps1

RehanSaeed commented 7 years ago

I'm hitting this issue too, using the -ScriptArgs= technique is not ideal but works when inside PowerShell. However, when executing PowerShell from cmd (Sadly, I'm using a Go.CD CI server) I get the following error:

build.ps1 : A positional parameter cannot be found that accepts argument '--MyParam=MyValue'

gep13 commented 7 years ago

@patriksvensson can you comment on this one? I think this is similar to an issue that you solved a while back. Thanks!

fatmanmclone90 commented 7 years ago

Having the same issue. Trying to run Cake from a GO CD task, but getting the error "Cake.exe : More than one build script specified.". It doesn't seem to let me specify the Script location

.\nuget.PackageName.1.2.3\Tools\build-cake.ps1 -Script '.\nuget.PackageName.1.2.3\Tools\build.cake' -Target 'DeployRelease' -octopusReleaseVersion '1.0.456' -OctopusApiKey='API-???????' -GoCDUsername='user_name' -GoCDPassword='123456'

devlead commented 7 years ago

If GO CI does something with the command line, perhaps a simplified bootrapper could be one option where you just pass along arguments as they're entered.

Example from Cake.Kudu/build.ps1

& tools\Cake\Cake.exe "$CakePath" $args
exit $LASTEXITCODE

But things like API keys/usernames etc. could also be passed as environment, you can add variables to an environment by editing the configuration of the environment in GO CD. And access them using the built in EnvironmentVariable aliases.

fatmanmclone90 commented 7 years ago

Actually I think the fix is even simpler in my case, the default build.ps1 isn't reading the $Script variable as a parameter. It just defaults: [CmdletBinding()] Param( [string]$Script = "build.cake",

Removed default: [CmdletBinding()] Param( [string]$Script,

It is now running the cake script that I pass in as a parameter

evil-shrike commented 6 years ago

I as many encountered the same issue - tried to pass a custom argument with dots, e.g. powershell ./build.ps1 -productVersion="1.2.3", it was failing with "More than one build script specified". Thanks to @kcamp 's tip - changing to --productVersion solved the issue. I believe it should be in the documentation.

Kralizek commented 6 years ago

Having the same issue, but no dot in the values. Here is an example .\build.ps1 -Target Information -Configuration Debug -IncludeCoverage OpenCover

nate-datafinch commented 6 years ago

This still appears to be broken...

It might also be a duplicate of https://github.com/cake-build/cake/issues/172

Here's the output of a fairly benign argument string being passed. You can see the arguments to the powershell script, below "Running build script..." I print the values of the parsed arguments. Every single argument ends up using the default value except for the first, "environment".

The first argument seems to suck in everything else. Attempting to swap the single quotes for double quotes results in "More than one build script specified."

Removing quotes for items that don't need them doesn't help.

There are no dots, there are no trailing backslashes.

[SCRIPT OUTPUT]

[Step 2/2] PowerShell arguments: -NoProfile, -NonInteractive, -ExecutionPolicy, ByPass, -File, E:\BuildAgent\work\464c071b51cb4b09\build.ps1, -ScriptArgs, "-environment='production' -octopusHost='http://octopus' -octopusApiKey='API-XXXXXX' -buildnumber='47' -branch='refs/heads/feature/build_system' -sha='bb10761154335223d2f4fb076ac2345b7c9963d7' -buildid='51944'" [22:16:51] [Step 2/2] Preparing to run build script... [22:16:55] [Step 2/2] Running build script... [22:17:06] [Step 2/2] target: CreateRelease [22:17:06] [Step 2/2] octopusHost: [22:17:06] [Step 2/2] octopusApiKey: [22:17:06] [Step 2/2] buildnumber: 0.1.0.0 [22:17:06] [Step 2/2] buildnumberFull: 0.1.0.0+branch.dev_build_no_release.sha.dev_build_no_release [22:17:06] [Step 2/2] deployChannel: Default [22:17:06] [Step 2/2] deployEnvironment: Staging [22:17:06] [Step 2/2] buildid: 1 [22:17:06] [Step 2/2] branch: dev_build_no_release [22:17:06] [Step 2/2] sha: dev_build_no_release [22:17:06] [Step 2/2] environment: 'production' -octopusHost='http://octopus' -octopusApiKey='API-XXXXXX' -buildnumber='47' -branch='refs/heads/feature/build_system' -sha='bb10761154335223d2f4fb076ac2345b7c9963d7' -buildid='51944'

nukefusion commented 6 years ago

This still appears to be broken...

@nate-datafinch If you're using TeamCity then it could be because TeamCity appears to pass script arguments to powershell as a comma separated list, which breaks arguments that need to be passed as an array (like ScriptArgs).

I got around this by avoiding the TeamCity Powershell runner and just calling powershell directly from a command line task, e.g.:

powershell -NoProfile -NonInteractive -ExecutionPolicy ByPass -File ./build.ps1 --target=Default --buildVersion=1.0.0.577

Sergej-Popov commented 6 years ago

So it seems when running from CMD params need to be passed in this format: --target=Default --buildVersion=1.0.0.577. Worked for me in TeamCity using PowerShell task. Thanks, @nukefusion !

kentcb commented 6 years ago

Getting the same when trying to specify a target via build.sh:

> ./build.sh -target Clean
More than one build script specified.
For usage, use parameter --help
> ./build.sh --target Clean
More than one build script specified.
For usage, use parameter --help

And --help doesn't even mention the ability to specify a target 😕 :

> ./build.sh --help

Usage: Cake.exe [script] [--verbosity=value]
                [--showdescription] [--dryrun] [..]

Example: Cake.exe
Example: Cake.exe build.cake --verbosity=quiet
Example: Cake.exe build.cake --showdescription

Options:
    --verbosity=value    Specifies the amount of information to be displayed.
                         (Quiet, Minimal, Normal, Verbose, Diagnostic)
    --debug              Performs a debug.
    --showdescription    Shows description about tasks.
    --dryrun             Performs a dry run.
    --version            Displays version information.
    --help               Displays usage information.

Here is relevant --version output:

Version 0.28.1+Branch.main.Sha.1da1ea266471a2bb8034fc4a89017b5dcf455268
Running on .NET Core
kentcb commented 6 years ago

Ugh, I just found #1690 which suggests the syntax I need is --target=Clean, which works fine. Seems like the main problem here is the confusing error message and the (lack of) docs.

maartenschalekamp commented 5 years ago

I believe there is still an issue but it only happens with the task in the cake script has a dot in the name.

I have added Set-PSDebug -Trace 1 in the cake.ps1 script to check the steps:

So running C:\Build\Tools\cake.ps1 -Script C:\Build\Cakes\App.cake -Target "App.Package it executes

DEBUG:    1+  >>>> & "C:\Build\Tools\tools\Cake\Cake.exe" C:\Build\Cakes\App.cake -target=App.Package

and then Cake.exe exit with More than one build script specified.

Removing the dot solves the issue C:\Build\Tools\cake.ps1 -Script C:\Build\Cakes\App.cake -Target "Package" and execute as

DEBUG:    1+  >>>> & "C:\Build\Tools\tools\Cake\Cake.exe" C:\Build\Cakes\App.cake -target=Package

which works fine.

Not sure if this is related to this issue or if I need to open a new one. This used to work fine.

Now running Cake Version: 0.32.1

nick5454 commented 4 years ago

Ugh, I just found #1690 which suggests the syntax I need is --target=Clean, which works fine. Seems like the main problem here is the confusing error message and the (lack of) docs.

I confirm this worked for me .Net Core, Azure, powershell

dasiths commented 4 years ago

This is still a problem. Both of these fail.

Cake.exe build.cake --Target Build --ScriptArgs --stagingFolderPath="C:\TempStaging" --finalFolderPath="C:\Final
Output"

Cake.exe build.cake --Target Build --ScriptArgs '--stagingFolderPath="C:\TempStaging" --finalFolderPath="C:\Final
Output"'
gep13 commented 4 years ago

@dasiths and it you try...

Cake.exe build.cake --Target=Build  --stagingFolderPath="C:\TempStaging" --finalFolderPath="C:\Final
Output"
dasiths commented 4 years ago

--stagingFolderPath="C:\TempStaging"

Calling Cake.exe directly works but not if you use the build.ps1 script

&.\cake-build.ps1 -Target $target " --finalFolderPath=`"$finalOutputDirectory`" --stagingFolderPath=`"$stagingDir`""

It's because if the incorrect way the powershell script passes arguments. (Ref: https://slai.github.io/posts/powershell-and-external-commands-done-right/)

gep13 commented 4 years ago

@dasiths are you using the most recent version of the PowerShell bootstrapper?

dasiths commented 4 years ago

@dasiths are you using the most recent version of the PowerShell bootstrapper?

I was not. I just tried the latest version which uses the following in the powershell script and it works. :) Thanks for your help. @gep13 Much appreciated.

Invoke-Expression "& $CAKE_EXE_INVOCATION $($cakeArguments -join " ")"
gep13 commented 4 years ago

@dasiths glad to hear that you were able to get this working.

AZ2Tonez commented 4 years ago

Tried all the variations on this page, none worked. This is what finally worked for us:

.\build.ps1 --% --ScriptArgs @('--targetTargetName','--exclusive','--buildUrl=%teamcity.serverUrl%/viewLog.html?buildId=%teamcity.build.id%&buildTypeId=%system.teamcity.buildType.id%')

The --% tells powershell to stop parsing text (ref: https://slai.github.io/posts/powershell-and-external-commands-done-right/) and the @('','',''...) notation is a command line string array (ref: https://www.varonis.com/blog/powershell-array/). As you can see, this was used in TeamCity and we have a url as a parameter, which complicated things.