adamralph / bullseye Goto Github PK
View Code? Open in Web Editor NEW🎯 A .NET library for running a target dependency graph.
License: Apache License 2.0
🎯 A .NET library for running a target dependency graph.
License: Apache License 2.0
E.g.
e.g from a FAKE build script:
---------------------------------------------------------------------
Build Time Report
---------------------------------------------------------------------
Target Duration
------ --------
Clean 00:00:01.5973051
ChangeVersion 00:00:00.0216123
Version 00:00:00.0449321
Restore 00:00:02.5392854
FullBuild 00:00:06.7928622
Test 00:00:26.2444011
InternalizeDependencies 00:00:08.4346894
Build 00:00:00.0017516
Release 00:00:04.1651395
Total: 00:00:49.9985537
---------------------------------------------------------------------
Status: Ok
---------------------------------------------------------------------
I really like having this be the last thing printed consistently as I often keep an eye out on task running times.
Relates to #162 and maybe even #95
Are there any plans to open up the Logger: https://github.com/Mpdreamz/bullseye/blob/master/Bullseye/Internal/Logger.cs#L12
More wondering out of my obsessive need to tinker rather than a real use case. In this case I would love to control how the tasks get ouput using something fancier then /
to separate the chain.
If exceptions would flow to the logger in the future (#162) I would love to provide diagnosers for known exceptions though.
Right now target is case sensitive, it would be nice if this was case insensitive allowing you to use nameof(Method) but pass method
on the command line
As you can see here: https://ci.appveyor.com/project/FakeItEasy/fakeiteasy/builds/20841032#L420
The text remains red on the last 3 lines. I can also reproduce the problem locally.
(using version 2.3.0-beta.3)
/cc @blairconrad
-I, --list-inputs List the targets and inputs, then exit
--parallel
, all exception details are shown.C:\Projects\elastic\net-master>build.cmd walkdog
Bullseye: Starting... (walkdog)
Bullseye/walkdog: Starting...
Bullseye/walkdog: Failed! boom! (8.34 ms)
Bullseye: Failed! (walkdog) (23.4 ms)
Unhandled Exception: System.Exception: boom!
at targets.WalkDogTarget.Exec() in C:\Projects\elastic\net-master\build\targets\Progra
m.cs:line 40
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, Co
ntextCallback callback, Object state)
--- End of stack trace from previous location where exception was thrown ---
at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot)
--- End of stack trace from previous location where exception was thrown ---
at Bullseye.Internal.ActionTarget.RunAsync(Boolean dryRun, Boolean parallel, Logger lo
g) in C:\projects\bullseye\Bullseye\Internal\ActionTarget.cs:line 25
at Bullseye.Internal.ActionTarget.RunAsync(Boolean dryRun, Boolean parallel, Logger lo
g) in C:\projects\bullseye\Bullseye\Internal\ActionTarget.cs:line 31
at Bullseye.Internal.TargetCollection.RunAsync(String name, List`1 explicitTargets, Bo
olean skipDependencies, Boolean dryRun, Boolean parallel, ConcurrentDictionary`2 targetsR
an, Logger log, Stack`1 targets) in C:\projects\bullseye\Bullseye\Internal\TargetCollecti
on.cs:line 83
at Bullseye.Internal.TargetCollection.RunAsync(List`1 names, Boolean skipDependencies,
Boolean dryRun, Boolean parallel, Logger log) in C:\projects\bullseye\Bullseye\Internal\
TargetCollection.cs:line 38
at Bullseye.Internal.TargetCollection.RunAsync(List`1 names, Boolean skipDependencies,
Boolean dryRun, Boolean parallel, Logger log) in C:\projects\bullseye\Bullseye\Internal\
TargetCollection.cs:line 47
at Bullseye.Internal.TargetCollectionExtensions.RunAsync(TargetCollection targets, Lis
t`1 args, IConsole console) in C:\projects\bullseye\Bullseye\Internal\TargetCollectionExt
ensions.cs:line 171
at targets.Program.Main(String[] args) in C:\Projects\elastic\net-master\build\targets
\Program.cs:line 26
at targets.Program.<Main>(String[] args)
C:\Projects\elastic\net-master>
If the order were different:
C:\Projects\elastic\net-master>build.cmd walkdog
Bullseye: Starting... (walkdog)
Bullseye/walkdog: Starting...
Unhandled Exception: System.Exception: boom!
at targets.WalkDogTarget.Exec() in C:\Projects\elastic\net-master\build\targets\Progra
m.cs:line 40
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, Co
ntextCallback callback, Object state)
--- End of stack trace from previous location where exception was thrown ---
at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot)
--- End of stack trace from previous location where exception was thrown ---
at Bullseye.Internal.ActionTarget.RunAsync(Boolean dryRun, Boolean parallel, Logger lo
g) in C:\projects\bullseye\Bullseye\Internal\ActionTarget.cs:line 25
at Bullseye.Internal.ActionTarget.RunAsync(Boolean dryRun, Boolean parallel, Logger lo
g) in C:\projects\bullseye\Bullseye\Internal\ActionTarget.cs:line 31
at Bullseye.Internal.TargetCollection.RunAsync(String name, List`1 explicitTargets, Bo
olean skipDependencies, Boolean dryRun, Boolean parallel, ConcurrentDictionary`2 targetsR
an, Logger log, Stack`1 targets) in C:\projects\bullseye\Bullseye\Internal\TargetCollecti
on.cs:line 83
at Bullseye.Internal.TargetCollection.RunAsync(List`1 names, Boolean skipDependencies,
Boolean dryRun, Boolean parallel, Logger log) in C:\projects\bullseye\Bullseye\Internal\
TargetCollection.cs:line 38
at Bullseye.Internal.TargetCollection.RunAsync(List`1 names, Boolean skipDependencies,
Boolean dryRun, Boolean parallel, Logger log) in C:\projects\bullseye\Bullseye\Internal\
TargetCollection.cs:line 47
at Bullseye.Internal.TargetCollectionExtensions.RunAsync(TargetCollection targets, Lis
t`1 args, IConsole console) in C:\projects\bullseye\Bullseye\Internal\TargetCollectionExt
ensions.cs:line 171
at targets.Program.Main(String[] args) in C:\Projects\elastic\net-master\build\targets
\Program.cs:line 26
at targets.Program.<Main>(String[] args)
Bullseye/walkdog: Failed! boom! (8.34 ms)
Bullseye: Failed! (walkdog) (23.4 ms)
C:\Projects\elastic\net-master>
The last lines would always indicate the faulty target and a user does not have to scroll their terminal.
When running with (-v
/--verbose
):
-s
/--skip-dependencies
)--appveyor
, --travis
, --teamcity
The CI environment is usually detected, but in some cases may not be, e.g. when running the build in a Docker container.
These method groups will run the targets and then call Environment.Exit
.
RunTargets()
and RunTargetsAsync
will be deprecated.Environment.Exit()
does not exist in .NET Standard 1.3.The advantage is that when a target fails, or when invalid arguments are supplied, or when the targets are badly defined (circular dependencies, missing dependencies, etc), the exception message will be logged and the process will exit with an appropriate exit code. Currently, the process exits with an unhandled exception, which results in the stack trace being written to the console, and an application error being written to the OS event log (at least on Windows) which usually results in a significant delay before control is returned to the console.
RunTargets(args)
And three entries in the OS event logs! Notice that two seconds elapsed between the first and last entry, and this seems to be the delay in control being returned to the console after the process exits.
RunTargetsAndExit(args)
And nothing in the OS event logs, and no delay.
Accepting a predicate that is called when an exception is thrown, which should returns true
if only the exception message should be displayed.
RunTargetsAndExit(IEnumerable<string> args, Func<Exception, bool> messageOnly)
RunTargetsAndExitAsync(IEnumerable<string> args, Func<Exception, bool> messageOnly)
Calling Environment.Exit
from RunTargetsAndExit
prevents us from doing anything after we run the targets.
Could RunTargets
(or some other method like RunTargetsAndReturn
) do the same thing as RunTargetsAndExit
, except return the exit code that should be returned from Main
, instead of calling Environment.Exit
?
Bare with me @adamralph I am just throwing tickets at you without fully knowing what I want 😸
Here I am running .NET tests by calling dotnet test
through https://github.com/nullean/proc which throws an exception on an unknown exitCode (defaulting to anything not 0
).
The result is a bit noisy:
I am only interested in the first stracktrace from the failing tests.
It would be nice if I could mark ProcExecException
somehow to only display the ex.Message
.
These were deprecated in 1.1.0.
-s build -s pack
-c, --clear Clear the console before execution
Ported from https://github.com/adamralph/simple-targets-csx
This is not an issue, but a question.
I have created a console project in dotnet core 2.2 to build a bunch of projects. As per the documentation and examples, I use
Target("default", DependsOn(_targetNames.ToArray()));
RunTargetsAndExit(args);
When debugging in my IDE (visual studio in this case) the command line window disappears too fast to see the errors or the reporting on each task. This is expected behaviour of RunTargetsAndExit. However, how can I prevent the commandline window to close so that I can see all the errors?
Thank you in advance for the help and for creating this useful tool.
Under Bullseye 2.2.0, on Azure pipelines, the build output is not coloured, instead displaying the ANSI escape codes:
(from https://dev.azure.com/blairconrad/SendComics/_build/results?buildId=9&view=logs)
I'd offer to help, but I am not sure where to start!
Currently there's no easy way to pass custom command line arguments to a Bullseye-based program.
I suggest:
string GetArgument(string argumentName)
, which would allow passing arguments in the form --foo=bar
RunTargets
(or adding an overload with a bool ignoreUnknownArguments
parameter)Hi. Just thought I'd give bullseye a very quick whirl in Linqpad and I see a couple of (cosmetic) issues:
RunTargets(args)
but I see that's being deprecated...I appreciate Linqpad's not been targeted for support, but if the problems are easy to fix then it would be neat to be able to use it with bullseye.
-p, --parallel Run targets in parallel
Note that in a typical build script, this can cause havoc in the console, since the output from the external tools that are run in parallel targets will be interleaved. It is perhaps best used to use this option only to speed up local builds on a developer workstation. Builds on a CI server may better off without it, to preserve the readability of build logs.
This may be an uncommon use case, but I find myself running a local build, and skipping dependencies (because I don't want to run a restore
target, or something that calculates the next released version number), but executing targets that depend on others, such as a build
and a test
target. In such cases, I must take pains to order the targets properly, or they will be executed in the wrong order. Consider:
Target("build", DoesNothing);
Target("subtest1", DependsOn("build"));
Target("subtest2", DependsOn("build"));
Target("test", DependsOn("subtest1", "subtest2"));
Target("default", DependsOn("test"));
When I run with Bullseye 2.0.0-rc.2+build.115:
λ dotnet run -s build test
Bullseye: Starting... (build test) (skip dependencies)
Bullseye/build: Starting...
Bullseye/build: Succeeded. (4.57 ms)
Bullseye/test: Succeeded.
Bullseye: Succeeded. (build test) (skip dependencies) (19.6 ms)
D:\Sandbox\try-bullseye
λ dotnet run -s test build
Bullseye: Starting... (test build) (skip dependencies)
Bullseye/test: Succeeded.
Bullseye/build: Starting...
Bullseye/build: Succeeded. (3.51 ms)
Bullseye: Succeeded. (test build) (skip dependencies) (15.7 ms)
But I would've hoped the order of execution would be the same. Just because I don't want to run (unasked-for) dependencies, I don't want to throw my usual target-ordering rules out the window.
@adamralph, if you've interest in this change (or at least are not opposed), I'd be happy to work on a PR.
See https://superuser.com/a/1050078/26617
Virtual terminal processing (including ANSI colours) was added to the console in Windows 10. Unfortunately, it's disabled by default, which means running Bullseye targets in a vanilla console window looks like this (unless the --no-color
/-N
option is specified):
With this enhancement, Bullseye uses the Win32 API (when on Windows) to attempt to switch on virtual terminal processing. Any failure to do so is ignored and logged at the verbose level (--verbose
/-v
). It works in most cases (i.e. on a developer machine):
It fails on Appveyor, but Appveyor already redirects console output and understands ANSI colour codes, so builds on Appveyor are already in glorious colour. 🌈
Some console apps, such as ConEmu, already enable virtual terminal processing so this change has no observable effect when using those apps.
"
, /
, and :
is flawed. It's easy to construct target names which make the resulting string ambiguous.hell"o
actually succeeded.And some extra colour to boot. 🌈
using static Bullseye.Targets;
...
Target("default", () => System.Console.WriteLine("Hello, world!"));
RunTargets(args);
With Add()
and Run()
deprecated.
Feedback from @blairconrad and @thomaslevesque was that Add()
and Run()
are too general in their bare forms when using static
. An alternative is AddTargets()
and RunTargets()
, although that is a little verbose when you consider Targets.AddTarget()
, Targets.RunTargets()
. Ideally it would be great to have an API which looks great in both scenarios although I'm not sure that's possible.
This would include a deprecation of the previous methods, and their removal in 2.0.
Final decision was Target()
and RunTargets()
.
As pointed out by @blairconrad in #168 (comment).
Currently, they are inconsistent: min
and s
.
Consistent would be:
min
and sec
, orm
and s
For the sake of brevity, the latter is probably better.
Expected : I was expecting it to execute default1 target
Actual : "Bullseye: Unknown option --foo=bar. "--help" for usage."
Same can be tried without changing name , just specify target name , say default it will throw same error.
> build.cmd drink-tea
Bullseye: Starting... (drink-tea)
Bullseye: Failed! (drink-tea) (3.96 ms)
Unhandled Exception: System.Exception: The following target was not found: drink-te
a.
at Bullseye.Internal.TargetCollection.Validate(List`1 names) in C:\projects\bull
seye\Bullseye\Internal\TargetCollection.cs:line 150
at Bullseye.Internal.TargetCollection.RunAsync(List`1 names, Boolean skipDepende
ncies, Boolean dryRun, Boolean parallel, Logger log) in C:\projects\bullseye\Bullse
ye\Internal\TargetCollection.cs:line 30
at Bullseye.Internal.TargetCollection.RunAsync(List`1 names, Boolean skipDepende
ncies, Boolean dryRun, Boolean parallel, Logger log) in C:\projects\bullseye\Bullse
ye\Internal\TargetCollection.cs:line 47
at Bullseye.Internal.TargetCollectionExtensions.RunAsync(TargetCollection target
s, List`1 args, IConsole console) in C:\projects\bullseye\Bullseye\Internal\TargetC
ollectionExtensions.cs:line 171
at targets.Program.Main(String[] args) in C:\Projects\elastic\net-master\build\t
argets\Program.cs:line 26
at targets.Program.<Main>(String[] args)
Is rather verbose and panicky, a smaller output for these validation failure cases would make for a smoother CLI experience in my opinion.
> build.cmd drink-tea
Bullseye: Starting... (drink-tea)
Bullseye: Failed! (drink-tea) The following target was not found: drink-tea. (3.96 ms)
Similarly the reporting of unknown command line switches do not need to yield a full stacktrace IMHO.
I realised this as I was writing the new README.md. 😿
Target(
"eat-biscuits",
ForEach("digestives", "chocolate hob nobs"),
biscuits => Console.WriteLine($"Mmm...{biscuits}! Nom nom."));
In this case the name, dependsOn, action
overload is being called, and obviously targets named "digestives" and "chocolate hob nobs" are not found.
The fix is to add the parameter name (ugly):
Target(
"eat-biscuits",
forEach: ForEach("digestives", "chocolate hob nobs"),
action: biscuits => Console.WriteLine($"Mmm...{biscuits}! Nom nom."));
And then it's better not to use ForEach
, and use an array initializer instead (less ugly):
Target(
"eat-biscuits",
forEach: new[] {"digestives", "chocolate hob nobs"},
action: biscuits => Console.WriteLine($"Mmm...{biscuits}! Nom nom."));
This issue may become "Deprecate DependsOn and ForEach". They were only added because C# doesn't have a pretty array initializer. I had a feeling they might come and bite me eventually.
I would like to be able to run an action before and after each target run.
My particular use case is that I want to write a TC service message before and after each Task.
BeforeTarget((targetName) => Console.WriteLine($"##teamcity[blockOpened name='{targetName}']");
AfterTarget((targetName) => Console.WriteLine($"##teamcity[blockClosed name='{targetName}']");
Happy to attempt a PR if agreeable. My current workaround is to have my own TargetTC
methods that wrap Target
and it's a bit meh
private static void TargetTC(string name, Action action)
{
Target(name, () =>
{
Console.WriteLine($"##teamcity[blockOpened name='{name}']");
action();
Console.WriteLine($"##teamcity[blockClosed name='{name}']");
});
}
One thing I love about FAKE is that it promotes the separation of defining targets and defining dependency chains.
e.g part of our current build that I am converting over to BullsEye
"Start"
=?> ("Clean", Commandline.needsClean )
=?> ("Version", hasBuildParam "version")
==> "Restore"
=?> ("FullBuild", Commandline.needsFullBuild)
=?> ("Test", (not Commandline.skipTests && Commandline.target <> "canary"))
=?> ("InternalizeDependencies", (not isMono))
==> "InheritDoc"
=?> ("Documentation", (not Commandline.skipDocs))
==> "Build"
=?>
denotes a conditional target which will only run if the predicate is true
.
Not sure how to work this into the current DSL but I found there was a bit of cognitive overload on my end trying to rework this as arguments to the target creation.
-h, --help Show this help (case insensitive) (or -?)
-h, --help, -? Show this help, then exit (case insensitive)
Currently, diagnostics (any message printed by Bullseye while running targets) are printed to stdout. They should be printed to stderr.
--help
should print to stdout--list-dependencies
, --list-inputs
, --list-targets
, and/or --list-tree
should print to stdout.For reference: https://www.jstorimer.com/blogs/workingwithcode/7766119-when-to-use-stderr-instead-of-stdout
As discussed in #226.
And also drop the overloads which do not accept args.
Run Bullseye with an unknown option flag, e.g. -b
. The error that spews out is akin to
Unknown options {unknownOptions.Quote()}. "--help" for usage.
This is less than ideal.
With support for Appveyor, Travis CI, and TeamCity.
For reference, this is how the output looks in a local console:
And these are the various colour palettes:
Local console | Appveyor - Windows | Appveyor - Linux | Travis CI | TeamCity |
---|---|---|---|---|
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.