I actually have an idea in mind. A strange one may be... but an interesting one I believe. I'm a little bit reluctant to express it before having gained credibility from all of you. But... well... let's go!
The idea is named "CodeCake". It is an alternative to scripting (I can imagine how difficult it could be for guys who designed a project around scripting to consider this approach!). It relies on a cs project in the solution that can be a console application and even a GUI application (winForm or WPF or whatever activated by a -gui (or -ui) switch.
The scripts are replaced with classes with a default ctor: below is a (working) example from the POC I'm working on:
class Build : CodeCakeHost
{
public Build()
{
var configuration = Cake.Argument( "configuration", "Release" );
// Define directories.
var buildDir = Cake.Directory( "./src/Example/bin" ) + Cake.Directory( configuration );
Task( "Clean" )
.Does( () =>
{
Cake.CleanDirectory( buildDir );
} );
Task( "Restore-NuGet-Packages" )
.IsDependentOn( "Clean" )
.Does( () =>
{
Cake.NuGetRestore( "./src/Example.sln" );
} );
Task( "Build" )
.IsDependentOn( "Restore-NuGet-Packages" )
.Does( () =>
{
Cake.MSBuild( "./src/Example.sln", new MSBuildSettings()
.UseToolVersion( MSBuildToolVersion.NET45 )
.SetVerbosity( Verbosity.Minimal )
.SetConfiguration( configuration ) );
} );
Task( "Run-Unit-Tests" )
.IsDependentOn( "Build" )
.Does( () =>
{
Cake.XUnit2( "./src/**/bin/" + configuration + "/*.Tests.dll" );
} );
Task( "Default" )
.IsDependentOn( "Run-Unit-Tests" );
}
}
There is really nothing more to it (except the required using namespaces): the Cake that appears here is a property exposed by the base CodeCakeHost class that is actually just an alias to the Context property (extension methods apply and intellisense magics operates).
The overall process of working with CodeCake is the following:
Note: To honor the "scripting promise", simply install the Cake.Scripting NuGet package in the CodeCake project and (Oh! Magic!) you can use:
Cake.CakeExecuteExpression(
"Information(\"Hello {0}!\", Argument<string>(\"name\"));",
new CakeSettings {
ToolPath="./Cake.exe" ,
Arguments = new Dictionary<string, string>{{"name", "World"}}
});
or
Cake.CakeExecuteScript("./helloworld.cake");
from your build "scripts".
This is it. My long term goal is to provide a very simple (with no coupling to the IDE or the system - NuGet packages only) way to build/deploy/distribute/use a potentially unlimited of tools for the developer (for instance the classical "licence header processor", you need it but do not want to deploy a vsix for such little things).
(Quote from @patriksvensson who answered to this in issue #337)
A minor improvement to your approach would be to use the lambda overload for Does that provides an IContext. All aliases are extension methods for IContext so this would give you intellisense out of the box.
Task( "Clean" ) .Does(cake => { cake.CleanDirectory(buildDir); });I would however want to ask of you that you do not use the Cake prefix for you NuGet packages for non-tools, especially something called Cake.Scripting since it would be very confusing.
1 - I explained the Cake in the text above: it is a simple property exposed by the base class, so you are "at home" with intellisense (without any extra parameter to write).
2 - Actually, the idea is that the current Cake.Core can be splitted in two: Cake.Core with the CakeEngine and the basics and a new Cake.Scripting.dll that supports the scripting functionality. In this scenario, Cake.exe depends on Cake.Core and Cake.Scripting (this just adds a second dll to the bin), but CodeCake/Cake.Embedded is not necessarily bound to the script support... unless, as the final developer, you install the NuGet package to script things.
(Don't worry, I will never use "Cake." prefix outside Cake project, that's exactly why I use this "CodeCake" name!)
One last word: the CodeCakeHost I posted is real (the CakeEngine does its job with it without any modification to the Cake code base - I just had to package Cake.Common to use its great extensions).
I used an awful (but safe) trick to avoid any extra parameter to the constructor - and the really annoying to write : base(...) call.
I like this because it allows for us to take advantage of C#'s great tooling, but on the flip side, half the reason I love C# Scripting, and Cake, is that I don't have to do anything special for it to "just work".
Edit: then again, nothing you're saying would forbid that....hmm.
Yes I think the two worlds can peacefully live together and offer the best experience (with Code you easily have intellisense and powerful debugging capacities, with Script you benefit of the "dynamic" approach).
What led me to this is the fact that I want the commit point in the repository to exactly reflect the whole state of my releases. As long as the build chain belongs to the Solution and is committed with the source, then "It is Code"... (I tried to externalize the build chains in other repositories and/or in unparented branches but all those approaches have terrible issues).
@patriksvensson would need to separate the logic from "Cake.exe" into a new DLL "Cake.Host" then how you call the host just becomes a personal preference script/code/vs plugin/etc.
The proof of concept works well. I created a Project template with it (and even a VSIX).
It is a console application that works with the current Cake.Core, Cake.Common and a Code.Cake.dll (here: https://github.com/Invenietis/cake/tree/f-code-cake/src/Code.Cake). [Caution: crappy, quick & dirty code!]
The sample application onto which the Project Template is based is here: https://github.com/Invenietis/CodeCakeSampleApp
It is really cool to develop (and debug!) in VS (except that you have to know the namespaces before using the extension methods).
Unfortunately, this can be tested only with Cake.Common (and Code.Cake) published in nuget feeds (I used a private feed for them).
I hope you will find this approach interesting and I'm looking forward to developing it further.
Would be rather interesting to see this paired with a DNX Console Project, so that you just could do something like dnx run -p .\tools\build.json, and still have a top level build.cs. Or I could be crazy :P
I really like the general idea here, although I haven't really taken the time to review the specifics proposed above.
For me, this addresses the following concerns/thoughts I've had since starting with Cake:
Up to this point, I've been (obviously very hackishly) writing my scripts in Visual Studio, writing my scripts in the .ctor of a custom class inheriting from a ScriptBase class, to give me intellisense and ReSharper goodness.
My ScriptBase implements ICakeContext and inherits from ScriptHost, with an additional code-gen'ed partial class containing all the method and property aliases so that I don't have to call them as extension methods.
When I'm ready to execute, I run a powershell script to scrape out the body of my script and "publish" it to a *.cake file for execution.
Of course my "solution" is (hopefully) a temporary thing until we can get some actual tooling together like @olivier-spinelli is proposing (and, BTW, I'd love to help with it).
Glad to see some interest in this beast!
Currently, my quick and dirty implementation works quite well. I am already using it and working on it (not on the core but around it: I just finished a boostraper.ps1: my goal is now to set up an AppVeyor build.
I hope that at the end of this day (Paris, France), I'll have the project setup and everybody will be able to see CodeCake in action.
Unfortunately, as long as Cake.Common.dll will not be on nuget.org, this can not easily be used by people. I made a PR for this and I'm waiting for it (I'm currently using a private nuget feed to host the Cake.Common package).
I have thought about this also. I created a wrapper for cake that does much the same thing.
It's also in POC stage but it work for me :)
The premise I was working on was that there would be a build sln that gets built first and then the resulting build.exe gets called which is the actual "script".
Up to this point, I've been (obviously very hackishly) writing my scripts in Visual Studio, writing my scripts in the .ctor of a custom class inheriting from a ScriptBase class, to give me intellisense and ReSharper goodness.
My ScriptBase implements ICakeContext and inherits from ScriptHost, with an additional code-gen'ed partial class containing all the method and property aliases so that I don't have to call them as extension methods.
When I'm ready to execute, I run a powershell script to scrape out the body of my script and "publish" it to a *.cake file for execution.
@jrnail23 I realise it's been a while and you've moved away from cake, but would you happen to have this visual studio project framework and powershell script you mentioned? Even if hacky it sounds like the best way currently to enjoy intellisense etc whilst still having a .cake script as the final product. If you could push a gist or repository or something i'd love to take a look at it.
Thanks!
@ryangribble I can't say much at the moment, but if you have some patience I will have a surprise for you in a couple of weeks that will solve your problem :smile:
cool sounds awesome @patriksvensson !
Id still be keen if @jrnail23 can post his hacky solution in the meantime :+1:
FYI, we actually use CodeCake for a while now without any issue (other than upgrading the code to follow the Cake code base). The code is not pretty at all but it works: a console app in each Solution (named CodeCakeBuilder) does the job.
The up to date VSIX is here (updated today): https://visualstudiogallery.msdn.microsoft.com/a04d0af4-d442-43a6-9c3b-7e64d08d6ea1
Example here: https://github.com/Invenietis/yodii-script/tree/master/CodeCakeBuilder
The Build script itself (the only part that actually needs to be changed across projects): https://github.com/Invenietis/yodii-script/blob/master/CodeCakeBuilder/Build.cs
You may notice some funny extensions to Cake: the support of "interactive" mode that I like very much:
if( !gitInfo.IsValid )
{
if( Cake.IsInteractiveMode()
&& Cake.ReadInteractiveOption( "Repository is not ready to be published. Proceed anyway?", 'Y', 'N' ) == 'Y' )
{
Cake.Warning( "GitInfo is not valid, but you choose to continue..." );
}
else throw new Exception( "Repository is not ready to be published." );
}
And to conclude, we use AppVeyor and a standard appveyor.yml does the job (https://github.com/Invenietis/yodii-script/blob/master/appveyor.yml) thanks to these two lines:
install:
- ps: CodeCakeBuilder\Bootstrap.ps1
build_script:
- CodeCakeBuilder\bin\Release\CodeCakeBuilder.exe -nointeraction
Bootstrap.ps1 being the small script that builds the builder.
So... as long as the build machine has MSBuild, it works.
Heresy! I'm NOT using .cake file nor do I SCRIPT anything.
Yes, totally. And we are quite happy with that...
Do we miss a major issue on this point?
Does the "Script Way" offer stuff we'll be missing one day?
If some of you have information and/or remarks, we'll be glad to hear.
(And, one more time, many, many thanks to the team for Cake build: it definitely rocks! - even without scripts!)
I guess I just preferred the idea of using a cake script rather than a compiled executable, no legitimate reason just how I had things in my mind 馃榾 also your previous comments about codecake indicated it was a work in progress and it wasn't clear how up to date it was etc
the only thing I want is to make the cake script writing process easier (ie intellisense etc) but if @jrnail23 doesn't have that wrapper anymore I might take a look at codecake whilst waiting for the "surprise in a couple of weeks"
@ryangribble You're welcome. The fact is that CodeCake is a very thin exectable layer around Cake: the script itself is exactly the same (but I like the "interaction mode" and this has not been extenalized: the extension mehods are defined in Code.Cake dll).
@ryangribble, I'm sorry, but all that code is lost forever -- It was all on my dev machine owned by my former employer.
@ryangribble There is an alpha of what we call Cake.Frosting at https://github.com/cake-build/frosting.
Feel free to try it out and leave feedback if you have any.
@jrnail23 no worries, thanks for replying :wink:
@olivier-spinelli I got up and running with CodeCake it works well thanks
@patriksvensson I'll definitely check out frosting - is this the surprise you were referring to? :grinning:
@ryangribble said...
I'll definitely check out frosting - is this the surprise you were referring to?
Yip, yip, yip. We would welcome any feedback that you have on it.
Most helpful comment
Yip, yip, yip. We would welcome any feedback that you have on it.