From 208b0f054aa69e6d981f27c3e1674713abaccd82 Mon Sep 17 00:00:00 2001 From: Joshua Miller Date: Sat, 1 Jun 2019 11:23:42 -0400 Subject: [PATCH 1/5] console initial --- Jenkins.Net.Console/Arguments.cs | 10 ++++ .../Internal/ArgumentsGroup.cs | 7 +++ .../Jenkins.Net.Console.csproj | 8 +++ Jenkins.Net.Console/Program.cs | 60 +++++++++++++++++++ Jenkins.Net.sln | 6 ++ 5 files changed, 91 insertions(+) create mode 100644 Jenkins.Net.Console/Arguments.cs create mode 100644 Jenkins.Net.Console/Internal/ArgumentsGroup.cs create mode 100644 Jenkins.Net.Console/Jenkins.Net.Console.csproj create mode 100644 Jenkins.Net.Console/Program.cs diff --git a/Jenkins.Net.Console/Arguments.cs b/Jenkins.Net.Console/Arguments.cs new file mode 100644 index 0000000..73cae8b --- /dev/null +++ b/Jenkins.Net.Console/Arguments.cs @@ -0,0 +1,10 @@ +namespace Jenkins.Net.Console +{ + internal class Arguments + { + public void Parse(string[] args) + { + // + } + } +} diff --git a/Jenkins.Net.Console/Internal/ArgumentsGroup.cs b/Jenkins.Net.Console/Internal/ArgumentsGroup.cs new file mode 100644 index 0000000..2cdd380 --- /dev/null +++ b/Jenkins.Net.Console/Internal/ArgumentsGroup.cs @@ -0,0 +1,7 @@ +namespace Jenkins.Net.Console.Internal +{ + internal class ArgumentsGroup + { + // + } +} diff --git a/Jenkins.Net.Console/Jenkins.Net.Console.csproj b/Jenkins.Net.Console/Jenkins.Net.Console.csproj new file mode 100644 index 0000000..2eba7d9 --- /dev/null +++ b/Jenkins.Net.Console/Jenkins.Net.Console.csproj @@ -0,0 +1,8 @@ + + + + Exe + netcoreapp2.2 + + + diff --git a/Jenkins.Net.Console/Program.cs b/Jenkins.Net.Console/Program.cs new file mode 100644 index 0000000..27bbd4f --- /dev/null +++ b/Jenkins.Net.Console/Program.cs @@ -0,0 +1,60 @@ +using System; +using SysConsole = System.Console; + +namespace Jenkins.Net.Console +{ + internal static class Program + { + #if !NET_ASYNC + public static int Main(string[] args) + { + SysConsole.ForegroundColor = ConsoleColor.White; + SysConsole.WriteLine("Jenkins.NET Console"); + + try { + var arguments = new Arguments(); + arguments.Parse(args); + + // TODO: ... + + return 0; + } + catch (Exception error) { + SysConsole.ForegroundColor = ConsoleColor.Red; + SysConsole.WriteLine("[ERROR] "); + SysConsole.ForegroundColor = ConsoleColor.DarkRed; + SysConsole.WriteLine(error.Message); + return 1; + } + finally { + SysConsole.ResetColor(); + } + } + #else + public static async Task Main(string[] args) + { + SysConsole.ForegroundColor = ConsoleColor.White; + SysConsole.WriteLine("Jenkins.NET Console"); + + try { + var arguments = new Arguments(); + arguments.Parse(args); + + // TODO: ... + + return 0; + } + catch (Exception error) { + SysConsole.ForegroundColor = ConsoleColor.Red; + SysConsole.WriteLine("[ERROR] "); + SysConsole.ForegroundColor = ConsoleColor.DarkRed; + SysConsole.WriteLine(error.Message); + return 1; + } + finally { + SysConsole.ResetColor(); + } + } + #endif + } +} diff --git a/Jenkins.Net.sln b/Jenkins.Net.sln index b2b7a6a..256dfff 100644 --- a/Jenkins.Net.sln +++ b/Jenkins.Net.sln @@ -7,6 +7,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Jenkins.Net", "Jenkins.Net\ EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Jenkins.Net.Tests", "Jenkins.Net.Tests\Jenkins.Net.Tests.csproj", "{C39D7FDD-F85E-4FEF-8E30-A23B04DD1787}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jenkins.Net.Console", "Jenkins.Net.Console\Jenkins.Net.Console.csproj", "{DC01C670-176F-4587-B574-7FA73795F335}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -21,6 +23,10 @@ Global {C39D7FDD-F85E-4FEF-8E30-A23B04DD1787}.Debug|Any CPU.Build.0 = Debug|Any CPU {C39D7FDD-F85E-4FEF-8E30-A23B04DD1787}.Release|Any CPU.ActiveCfg = Release|Any CPU {C39D7FDD-F85E-4FEF-8E30-A23B04DD1787}.Release|Any CPU.Build.0 = Release|Any CPU + {DC01C670-176F-4587-B574-7FA73795F335}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DC01C670-176F-4587-B574-7FA73795F335}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DC01C670-176F-4587-B574-7FA73795F335}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DC01C670-176F-4587-B574-7FA73795F335}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From a4e18fa22a763833b56a8471efef7cd1a4887038 Mon Sep 17 00:00:00 2001 From: Joshua Miller Date: Sat, 1 Jun 2019 12:07:48 -0400 Subject: [PATCH 2/5] console build fix --- Jenkins.Net.Console/Arguments.cs | 2 +- .../Internal/ArgumentsGroup.cs | 2 +- .../Jenkins.Net.Console.csproj | 22 ++++++++++++++++--- Jenkins.Net.Console/Program.cs | 6 ++++- Jenkins.Net/Jenkins.Net.csproj | 2 -- 5 files changed, 26 insertions(+), 8 deletions(-) diff --git a/Jenkins.Net.Console/Arguments.cs b/Jenkins.Net.Console/Arguments.cs index 73cae8b..7588905 100644 --- a/Jenkins.Net.Console/Arguments.cs +++ b/Jenkins.Net.Console/Arguments.cs @@ -1,4 +1,4 @@ -namespace Jenkins.Net.Console +namespace JenkinsNET.Console { internal class Arguments { diff --git a/Jenkins.Net.Console/Internal/ArgumentsGroup.cs b/Jenkins.Net.Console/Internal/ArgumentsGroup.cs index 2cdd380..7a9769f 100644 --- a/Jenkins.Net.Console/Internal/ArgumentsGroup.cs +++ b/Jenkins.Net.Console/Internal/ArgumentsGroup.cs @@ -1,4 +1,4 @@ -namespace Jenkins.Net.Console.Internal +namespace JenkinsNET.Console.Internal { internal class ArgumentsGroup { diff --git a/Jenkins.Net.Console/Jenkins.Net.Console.csproj b/Jenkins.Net.Console/Jenkins.Net.Console.csproj index 2eba7d9..2e78709 100644 --- a/Jenkins.Net.Console/Jenkins.Net.Console.csproj +++ b/Jenkins.Net.Console/Jenkins.Net.Console.csproj @@ -1,8 +1,24 @@  - Exe - netcoreapp2.2 + netstandard2.0;net40;net45 + JenkinsNET.Console + 1.0.5 + 1.0.5 + 1.0.5 + latest - + + NETCORE;NETSTANDARD;NETSTANDARD2_0;NET_ASYNC + + + NETFULL;NET45;NET_ASYNC + + + NET40 + + + + + diff --git a/Jenkins.Net.Console/Program.cs b/Jenkins.Net.Console/Program.cs index 27bbd4f..dd4d38d 100644 --- a/Jenkins.Net.Console/Program.cs +++ b/Jenkins.Net.Console/Program.cs @@ -1,7 +1,11 @@ using System; using SysConsole = System.Console; -namespace Jenkins.Net.Console +#if NET_ASYNC +using System.Threading.Tasks; +#endif + +namespace JenkinsNET.Console { internal static class Program { diff --git a/Jenkins.Net/Jenkins.Net.csproj b/Jenkins.Net/Jenkins.Net.csproj index 88db5c6..56381ae 100644 --- a/Jenkins.Net/Jenkins.Net.csproj +++ b/Jenkins.Net/Jenkins.Net.csproj @@ -1,8 +1,6 @@  net40;net45;netstandard2.0 - - JenkinsNET jenkinsnet null511 From 48b33a29bffd89ac2744dc0b06a03cb363d1a599 Mon Sep 17 00:00:00 2001 From: Joshua Miller Date: Sat, 1 Jun 2019 15:09:29 -0400 Subject: [PATCH 3/5] publish console with release --- .travis.yml | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/.travis.yml b/.travis.yml index 527db46..fe672f4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,25 +4,20 @@ dotnet: 2.0.0 install: - export FrameworkPathOverride=$(dirname $(which mono))/../lib/mono/4.5/ - #- curl -L -o nuget.exe https://dist.nuget.org/win-x86-commandline/latest/nuget.exe - dotnet restore script: - dotnet build -c Debug --no-restore -v m #- dotnet test Jenkins.Net.Tests/Jenkins.Net.Tests.csproj -c Debug --no-build --filter Category=Unit - dotnet pack Jenkins.Net/Jenkins.Net.csproj -c Debug --no-build --no-restore -o bin + - dotnet publish Jenkins.Net.Console/Jenkins.Net.Console.csproj -c Release -f net45 -o bin -v m --no-restore -p:PublishSingleFile=true deploy: provider: releases api_key: $GITHUB_APIKEY - file: "Jenkins.Net/bin/jenkinsnet.*.nupkg" + file: + - "Jenkins.Net/bin/jenkinsnet.*.nupkg" + - "Jenkins.Net.Console/bin/Jenkins.Net.Console.exe" skip_cleanup: true on: tags: true - -# deploy: -# skip_cleanup: true -# provider: script -# script: dotnet nuget push Jenkins.Net/bin/jenkinsnet.*.nupkg -k $NUGET_APIKEY -s $NUGET_SOURCE -# on: -# branch: master From 7f971a21071e366279a412d4730a4ae4f170bad7 Mon Sep 17 00:00:00 2001 From: Joshua Miller Date: Sat, 1 Jun 2019 18:11:26 -0400 Subject: [PATCH 4/5] console arguments initial --- Jenkins.Net.Console/Arguments.cs | 50 ++++++++- .../Internal/ArgumentsGroup.cs | 104 +++++++++++++++++- .../Internal/ExceptionExtensions.cs | 24 ++++ .../Jenkins.Net.Console.csproj | 19 ++-- Jenkins.Net.Console/Program.cs | 41 ++----- .../Properties/launchSettings.json | 8 ++ Jenkins.Net.Console/RunArguments.cs | 88 +++++++++++++++ Jenkins.Net/Jenkins.Net.csproj | 2 +- Jenkins.Net/Utilities/JenkinsJobRunner.cs | 45 ++++---- .../Utilities/ProgressiveTextReader.cs | 5 +- 10 files changed, 309 insertions(+), 77 deletions(-) create mode 100644 Jenkins.Net.Console/Internal/ExceptionExtensions.cs create mode 100644 Jenkins.Net.Console/Properties/launchSettings.json create mode 100644 Jenkins.Net.Console/RunArguments.cs diff --git a/Jenkins.Net.Console/Arguments.cs b/Jenkins.Net.Console/Arguments.cs index 7588905..71e1fb6 100644 --- a/Jenkins.Net.Console/Arguments.cs +++ b/Jenkins.Net.Console/Arguments.cs @@ -1,10 +1,52 @@ -namespace JenkinsNET.Console +using System; +using JenkinsNET.Console.Internal; +using System.Threading; +using System.Threading.Tasks; +using SysConsole = System.Console; + +namespace JenkinsNET.Console { - internal class Arguments + internal class Arguments : ArgumentsGroup { - public void Parse(string[] args) + public RunArguments RunGroup {get;} + public Actions Action {get; private set;} + + + public Arguments() { - // + RunGroup = new RunArguments(); + + Map("run").ToGroup(RunGroup, () => Action = Actions.Run); + Map("-help", "-?").ToAction(v => Action = Actions.Help); + } + + public Task RunAsync(CancellationToken token = default) + { + switch (Action) { + case Actions.Run: + return RunGroup.RunAsync(token); + default: + PrintHelp(); + break; + } + + return Task.CompletedTask; + } + + private static void PrintHelp() + { + SysConsole.ResetColor(); + SysConsole.WriteLine("Arguments:"); + SysConsole.ForegroundColor = ConsoleColor.White; + SysConsole.WriteLine(" run ..."); + SysConsole.WriteLine(" -help | -?"); + } + + public enum Actions + { + Undefined, + Run, + Help, } } } diff --git a/Jenkins.Net.Console/Internal/ArgumentsGroup.cs b/Jenkins.Net.Console/Internal/ArgumentsGroup.cs index 7a9769f..f9fe6b2 100644 --- a/Jenkins.Net.Console/Internal/ArgumentsGroup.cs +++ b/Jenkins.Net.Console/Internal/ArgumentsGroup.cs @@ -1,7 +1,107 @@ -namespace JenkinsNET.Console.Internal +using System; +using System.Collections.Generic; +using System.Linq; +using SysConsole = System.Console; + +namespace JenkinsNET.Console.Internal { internal class ArgumentsGroup { - // + private readonly Dictionary groupMap; + private readonly Dictionary> actionMap; + + + public ArgumentsGroup() + { + groupMap = new Dictionary(StringComparer.OrdinalIgnoreCase); + actionMap = new Dictionary>(StringComparer.OrdinalIgnoreCase); + } + + public void Parse(string[] args) + { + for (var i = 0; i < args.Length; i++) { + var arg = args[i]; + + if (i == 0 && groupMap.TryGetValue(arg, out var groupItem)) { + var subArgs = args.Skip(1).ToArray(); + groupItem.Action?.Invoke(); + groupItem.Group.Parse(subArgs); + return; + } + + var x = arg.IndexOfAny(new[] {'=', ':'}); + var key = x >= 0 ? arg.Substring(0, x) : arg; + var value = x >= 0 ? arg.Substring(x + 1) : null; + + if (actionMap.TryGetValue(key, out var action)) { + action.Invoke(value); + continue; + } + + SysConsole.ForegroundColor = ConsoleColor.DarkYellow; + SysConsole.WriteLine($"Unknown argument '{arg}'!"); + } + } + + public ArgumentActionBuilder Map(params string[] args) + { + return new ArgumentActionBuilder(args, this); + } + + public class ArgumentActionBuilder + { + private readonly string[] arguments; + private readonly ArgumentsGroup parentGroup; + + + public ArgumentActionBuilder(string[] arguments, ArgumentsGroup parentGroup) + { + this.arguments = arguments; + this.parentGroup = parentGroup; + } + + public ArgumentActionBuilder ToGroup(ArgumentsGroup group, Action action = null) + { + foreach (var arg in arguments) + parentGroup.groupMap[arg] = new ArgumentGroupAction(group, action); + + return this; + } + + public ArgumentActionBuilder ToAction(Action action) + { + foreach (var arg in arguments) + parentGroup.actionMap[arg] = action; + + return this; + } + + public ArgumentActionBuilder ToAction(Action action, T defaultValue = default) + { + foreach (var arg in arguments) { + parentGroup.actionMap[arg] = value => { + var valueT = value != null + ? (T)Convert.ChangeType(value, typeof(T)) + : defaultValue; + + action.Invoke(valueT); + }; + } + + return this; + } + } + + private class ArgumentGroupAction + { + public ArgumentsGroup Group {get;} + public Action Action {get;} + + public ArgumentGroupAction(ArgumentsGroup group, Action action) + { + this.Group = group; + this.Action = action; + } + } } } diff --git a/Jenkins.Net.Console/Internal/ExceptionExtensions.cs b/Jenkins.Net.Console/Internal/ExceptionExtensions.cs new file mode 100644 index 0000000..6e5fa1a --- /dev/null +++ b/Jenkins.Net.Console/Internal/ExceptionExtensions.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace JenkinsNET.Console.Internal +{ + internal static class ExceptionExtensions + { + public static IEnumerable UnfoldExceptions(this Exception error) + { + var e = error; + while (e != null) { + yield return e; + e = e.InnerException; + } + } + + public static string UnfoldMessages(this Exception error) + { + var errors = error.UnfoldExceptions().Select(x => x.Message); + return string.Join(" ", errors); + } + } +} diff --git a/Jenkins.Net.Console/Jenkins.Net.Console.csproj b/Jenkins.Net.Console/Jenkins.Net.Console.csproj index 2e78709..527165a 100644 --- a/Jenkins.Net.Console/Jenkins.Net.Console.csproj +++ b/Jenkins.Net.Console/Jenkins.Net.Console.csproj @@ -1,24 +1,21 @@  Exe - netstandard2.0;net40;net45 + net472 JenkinsNET.Console 1.0.5 1.0.5 1.0.5 latest + JenkinsNet.Console - - NETCORE;NETSTANDARD;NETSTANDARD2_0;NET_ASYNC - - - NETFULL;NET45;NET_ASYNC - - - NET40 - - + + + + + + diff --git a/Jenkins.Net.Console/Program.cs b/Jenkins.Net.Console/Program.cs index dd4d38d..c9ccf73 100644 --- a/Jenkins.Net.Console/Program.cs +++ b/Jenkins.Net.Console/Program.cs @@ -1,50 +1,23 @@ -using System; -using SysConsole = System.Console; - -#if NET_ASYNC +using JenkinsNET.Console.Internal; +using System; using System.Threading.Tasks; -#endif +using SysConsole = System.Console; namespace JenkinsNET.Console { internal static class Program { - #if !NET_ASYNC - public static int Main(string[] args) - { - SysConsole.ForegroundColor = ConsoleColor.White; - SysConsole.WriteLine("Jenkins.NET Console"); - - try { - var arguments = new Arguments(); - arguments.Parse(args); - - // TODO: ... - - return 0; - } - catch (Exception error) { - SysConsole.ForegroundColor = ConsoleColor.Red; - SysConsole.WriteLine("[ERROR] "); - SysConsole.ForegroundColor = ConsoleColor.DarkRed; - SysConsole.WriteLine(error.Message); - return 1; - } - finally { - SysConsole.ResetColor(); - } - } - #else public static async Task Main(string[] args) { SysConsole.ForegroundColor = ConsoleColor.White; SysConsole.WriteLine("Jenkins.NET Console"); + SysConsole.WriteLine(); try { var arguments = new Arguments(); arguments.Parse(args); - // TODO: ... + await arguments.RunAsync(); return 0; } @@ -52,13 +25,13 @@ public static async Task Main(string[] args) SysConsole.ForegroundColor = ConsoleColor.Red; SysConsole.WriteLine("[ERROR] "); SysConsole.ForegroundColor = ConsoleColor.DarkRed; - SysConsole.WriteLine(error.Message); + SysConsole.WriteLine(error.UnfoldMessages()); + return 1; } finally { SysConsole.ResetColor(); } } - #endif } } diff --git a/Jenkins.Net.Console/Properties/launchSettings.json b/Jenkins.Net.Console/Properties/launchSettings.json new file mode 100644 index 0000000..6e793c1 --- /dev/null +++ b/Jenkins.Net.Console/Properties/launchSettings.json @@ -0,0 +1,8 @@ +{ + "profiles": { + "Jenkins.Net.Console": { + "commandName": "Project", + "commandLineArgs": "run -job=\"Test Job\" -p:Arg1=Hello -p:Arg2=\"World!\"" + } + } +} \ No newline at end of file diff --git a/Jenkins.Net.Console/RunArguments.cs b/Jenkins.Net.Console/RunArguments.cs new file mode 100644 index 0000000..88f3db1 --- /dev/null +++ b/Jenkins.Net.Console/RunArguments.cs @@ -0,0 +1,88 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using JenkinsNET.Console.Internal; +using System.Threading; +using System.Threading.Tasks; +using JenkinsNET.Utilities; +using SysConsole = System.Console; + +namespace JenkinsNET.Console +{ + internal class RunArguments : ArgumentsGroup + { + public Dictionary JobParameters {get;} + public string JobName {get; private set;} + public bool ShowHelp {get; private set;} + + + public RunArguments() + { + Map("-job").ToAction(v => JobName = v); + Map("-p").ToAction(AddProperty); + Map("-help", "-?").ToAction(v => ShowHelp = v, false); + + JobParameters = new Dictionary(); + } + + public async Task RunAsync(CancellationToken token) + { + if (ShowHelp) { + PrintHelp(); + return; + } + + SysConsole.ForegroundColor = ConsoleColor.Cyan; + SysConsole.WriteLine($"Starting Job \"{JobName}\"..."); + + var client = new JenkinsClient { + BaseUrl = "http://localhost:8080/", + // TODO: Load from local file + }; + + var runner = new JenkinsJobRunner(client) { + MonitorConsoleOutput = true, + // TODO: Setup + }; + + runner.StatusChanged += () => { + SysConsole.ForegroundColor = ConsoleColor.White; + SysConsole.WriteLine($"[STATUS] {runner.Status}"); + }; + + runner.ConsoleOutputChanged += text => { + SysConsole.ResetColor(); + SysConsole.Write(text); + }; + + if (JobParameters.Any()) { + await runner.RunWithParametersAsync(JobName, JobParameters, token); + } + else { + await runner.RunAsync(JobName, token); + } + } + + private void AddProperty(string property) + { + var x = property.IndexOf('='); + if (x < 0) throw new ApplicationException($"No value specified in property string '{property}'!"); + + var key = property.Substring(0, x); + var value = property.Substring(x + 1); + JobParameters[key] = value; + } + + private static void PrintHelp() + { + SysConsole.ResetColor(); + SysConsole.Write("Arguments: "); + SysConsole.ForegroundColor = ConsoleColor.DarkCyan; + SysConsole.WriteLine("run"); + SysConsole.ForegroundColor = ConsoleColor.White; + SysConsole.WriteLine(" -job "); + SysConsole.WriteLine(" -p:="); + SysConsole.WriteLine(" -help | -?"); + } + } +} diff --git a/Jenkins.Net/Jenkins.Net.csproj b/Jenkins.Net/Jenkins.Net.csproj index 56381ae..5ae3860 100644 --- a/Jenkins.Net/Jenkins.Net.csproj +++ b/Jenkins.Net/Jenkins.Net.csproj @@ -1,6 +1,6 @@  - net40;net45;netstandard2.0 + netstandard2.0;net40;net45 JenkinsNET jenkinsnet null511 diff --git a/Jenkins.Net/Utilities/JenkinsJobRunner.cs b/Jenkins.Net/Utilities/JenkinsJobRunner.cs index 2110c61..61c1d4e 100644 --- a/Jenkins.Net/Utilities/JenkinsJobRunner.cs +++ b/Jenkins.Net/Utilities/JenkinsJobRunner.cs @@ -28,10 +28,11 @@ namespace JenkinsNET.Utilities /// public class JenkinsJobRunner { - public JenkinsClient Client {get;} protected ProgressiveTextReader textReader; protected bool isJobStarted; + public JenkinsClient Client {get;} + /// /// Occurs when the status of the running Jenkins Job changes. /// @@ -127,7 +128,7 @@ public JenkinsBuildBase Run(string jobName) /// /// /// - public async Task RunAsync(string jobName) + public async Task RunAsync(string jobName, CancellationToken token = default) { if (isJobStarted) throw new JenkinsNetException("This JobRunner instance has already been started! Separate JenkinsJobRunner instances are required to run multiple jobs."); isJobStarted = true; @@ -135,12 +136,10 @@ public async Task RunAsync(string jobName) SetStatus(JenkinsJobStatus.Pending); var queueStartTime = DateTime.Now; - var buildResult = await Client.Jobs.BuildAsync(jobName); + var buildResult = await Client.Jobs.BuildAsync(jobName, token); + if (buildResult == null) throw new JenkinsJobBuildException("An empty build response was returned!"); - if (buildResult == null) - throw new JenkinsJobBuildException("An empty build response was returned!"); - - return await ProcessAsync(jobName, buildResult, queueStartTime); + return await ProcessAsync(jobName, buildResult, queueStartTime, token); } #endif @@ -161,9 +160,7 @@ public JenkinsBuildBase RunWithParameters(string jobName, IDictionary /// /// - public async Task RunWithParametersAsync(string jobName, IDictionary jobParameters) + public async Task RunWithParametersAsync(string jobName, IDictionary jobParameters, CancellationToken token = default) { if (isJobStarted) throw new JenkinsNetException("This JobRunner instance has already been started! Separate JenkinsJobRunner instances are required to run multiple jobs."); isJobStarted = true; @@ -185,12 +182,10 @@ public async Task RunWithParametersAsync(string jobName, IDict SetStatus(JenkinsJobStatus.Pending); var queueStartTime = DateTime.Now; - var buildResult = await Client.Jobs.BuildWithParametersAsync(jobName, jobParameters); - - if (buildResult == null) - throw new JenkinsJobBuildException("An empty build response was returned!"); + var buildResult = await Client.Jobs.BuildWithParametersAsync(jobName, jobParameters, token); + if (buildResult == null) throw new JenkinsJobBuildException("An empty build response was returned!"); - return await ProcessAsync(jobName, buildResult, queueStartTime); + return await ProcessAsync(jobName, buildResult, queueStartTime, token); } #endif @@ -251,7 +246,7 @@ private JenkinsBuildBase Process(string jobName, JenkinsBuildResult buildResult, /// /// /// - private async Task ProcessAsync(string jobName, JenkinsBuildResult buildResult, DateTime queueStartTime) + private async Task ProcessAsync(string jobName, JenkinsBuildResult buildResult, DateTime queueStartTime, CancellationToken token = default) { QueueItemNumber = buildResult.GetQueueItemNumber(); if (!QueueItemNumber.HasValue) throw new JenkinsNetException("Queue-Item number not found!"); @@ -259,16 +254,17 @@ private async Task ProcessAsync(string jobName, JenkinsBuildRe SetStatus(JenkinsJobStatus.Queued); while (true) { + token.ThrowIfCancellationRequested(); if (!QueueItemNumber.HasValue) throw new JenkinsNetException("Queue-Item number not found!"); - var queueItem = await Client.Queue.GetItemAsync(QueueItemNumber.Value); + var queueItem = await Client.Queue.GetItemAsync(QueueItemNumber.Value, token); BuildNumber = queueItem?.Executable?.Number; if (BuildNumber.HasValue) break; if (QueueTimeout > 0 && DateTime.Now.Subtract(queueStartTime).TotalSeconds > QueueTimeout) throw new JenkinsNetException("Timeout occurred while waiting for build to start!"); - await Task.Delay(PollInterval); + await Task.Delay(PollInterval, token); } SetStatus(JenkinsJobStatus.Building); @@ -279,22 +275,25 @@ private async Task ProcessAsync(string jobName, JenkinsBuildRe JenkinsBuildBase buildItem = null; while (string.IsNullOrEmpty(buildItem?.Result)) { + token.ThrowIfCancellationRequested(); if (!BuildNumber.HasValue) throw new JenkinsNetException("Build number not found!"); - buildItem = await Client.Builds.GetAsync(jobName, BuildNumber.Value.ToString()); + buildItem = await Client.Builds.GetAsync(jobName, BuildNumber.Value.ToString(), token); if (!string.IsNullOrEmpty(buildItem?.Result)) break; if (BuildTimeout > 0 && DateTime.Now.Subtract(buildStartTime).TotalSeconds > BuildTimeout) throw new JenkinsNetException("Timeout occurred while waiting for build to complete!"); if (MonitorConsoleOutput && !textReader.IsComplete) - await textReader.UpdateAsync(); + await textReader.UpdateAsync(token); - await Task.Delay(PollInterval); + await Task.Delay(PollInterval, token); } while (MonitorConsoleOutput && !textReader.IsComplete) { - await textReader.UpdateAsync(); + token.ThrowIfCancellationRequested(); + + await textReader.UpdateAsync(token); } SetStatus(JenkinsJobStatus.Complete); diff --git a/Jenkins.Net/Utilities/ProgressiveTextReader.cs b/Jenkins.Net/Utilities/ProgressiveTextReader.cs index c002b1e..7b1b597 100644 --- a/Jenkins.Net/Utilities/ProgressiveTextReader.cs +++ b/Jenkins.Net/Utilities/ProgressiveTextReader.cs @@ -1,6 +1,7 @@ using System; #if NET_ASYNC +using System.Threading; using System.Threading.Tasks; #endif @@ -78,11 +79,11 @@ public void Update() /// Retrieves and appends any additional text returned /// by the running Jenkins Job asynchronously. /// - public async Task UpdateAsync() + public async Task UpdateAsync(CancellationToken token = default) { if (IsComplete) return; - var result = await client.Builds.GetProgressiveTextAsync(jobName, buildNumber, readPos); + var result = await client.Builds.GetProgressiveTextAsync(jobName, buildNumber, readPos, token); if (result.Size > 0) { Text += result.Text; From 26326a4fbd3137935c08631dcfcbd4f21edb0cd5 Mon Sep 17 00:00:00 2001 From: Joshua Miller Date: Sat, 1 Jun 2019 18:18:59 -0400 Subject: [PATCH 5/5] build fix --- .travis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index fe672f4..2926e1c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,10 +7,10 @@ install: - dotnet restore script: - - dotnet build -c Debug --no-restore -v m + #- dotnet build -c Debug --no-restore -v m #- dotnet test Jenkins.Net.Tests/Jenkins.Net.Tests.csproj -c Debug --no-build --filter Category=Unit - - dotnet pack Jenkins.Net/Jenkins.Net.csproj -c Debug --no-build --no-restore -o bin - - dotnet publish Jenkins.Net.Console/Jenkins.Net.Console.csproj -c Release -f net45 -o bin -v m --no-restore -p:PublishSingleFile=true + - dotnet pack Jenkins.Net/Jenkins.Net.csproj -c Debug -o bin -v m + - dotnet publish Jenkins.Net.Console/Jenkins.Net.Console.csproj -c Release -f net45 -o bin -v m -p:PublishSingleFile=true deploy: provider: releases