diff --git a/TeamCity.ServiceMessages.Tests/Write/Specials/TeamCityBuildStatusWriterTest.cs b/TeamCity.ServiceMessages.Tests/Write/Specials/TeamCityBuildStatusWriterTest.cs index 0ba25db..e7b7c2c 100644 --- a/TeamCity.ServiceMessages.Tests/Write/Specials/TeamCityBuildStatusWriterTest.cs +++ b/TeamCity.ServiceMessages.Tests/Write/Specials/TeamCityBuildStatusWriterTest.cs @@ -20,6 +20,12 @@ public void TestBuildNumber() DoTest(x => x.WriteBuildNumber("100500.5"), "##teamcity[buildNumber '100500.5']"); } + [Test] + public void TestBuildProblemWithoutIdentity() + { + DoTest(x => x.WriteBuildProblem("aaaa"), "##teamcity[buildProblem description='aaaa']"); + } + [Test] public void TestBuildProblem() { diff --git a/TeamCity.ServiceMessages.Tests/Write/Specials/TeamCityProgressWriterTest.cs b/TeamCity.ServiceMessages.Tests/Write/Specials/TeamCityProgressWriterTest.cs new file mode 100644 index 0000000..5c2c88a --- /dev/null +++ b/TeamCity.ServiceMessages.Tests/Write/Specials/TeamCityProgressWriterTest.cs @@ -0,0 +1,29 @@ +namespace JetBrains.TeamCity.ServiceMessages.Tests.Write.Specials +{ + using NUnit.Framework; + using ServiceMessages.Write.Special; + using ServiceMessages.Write.Special.Impl.Writer; + + [TestFixture] + public class TeamCityProgressWriterTest : TeamCityWriterBaseTest + { + protected override ITeamCityProgressWriter Create(IServiceMessageProcessor proc) + { + return new TeamCityProgressWriter(proc); + } + + [Test] + public void TestProgressMessage() + { + DoTest(x => x.WriteProgress("aaaa"), "##teamcity[progressMessage 'aaaa']"); + } + + [Test] + public void OpenProgressBlock() + { + DoTest(x => x.OpenProgress("aaaa").Dispose(), + "##teamcity[progressStart 'aaaa']", + "##teamcity[progressFinish 'aaaa']"); + } + } +} \ No newline at end of file diff --git a/TeamCity.ServiceMessages/TeamCity.ServiceMessages.csproj b/TeamCity.ServiceMessages/TeamCity.ServiceMessages.csproj index 2dc16d9..5cc8a61 100644 --- a/TeamCity.ServiceMessages/TeamCity.ServiceMessages.csproj +++ b/TeamCity.ServiceMessages/TeamCity.ServiceMessages.csproj @@ -12,7 +12,7 @@ true true - netstandard1.3;net35;net40;net45;netcoreapp1.0;netcoreapp2.0;netcoreapp3.0 + netstandard1.3;netstandard2.0;net35;net40;net45;netcoreapp1.0;netcoreapp2.0;netcoreapp3.0;net6.0;net8.0 TeamCity.ServiceMessages TeamCity.ServiceMessages JetBrains.TeamCity.ServiceMessages diff --git a/TeamCity.ServiceMessages/Write/Special/ITeamCityBuildStatusWriter.cs b/TeamCity.ServiceMessages/Write/Special/ITeamCityBuildStatusWriter.cs index 6a35f2e..8a3375e 100644 --- a/TeamCity.ServiceMessages/Write/Special/ITeamCityBuildStatusWriter.cs +++ b/TeamCity.ServiceMessages/Write/Special/ITeamCityBuildStatusWriter.cs @@ -18,6 +18,12 @@ public interface ITeamCityBuildStatusWriter void WriteBuildNumber([NotNull] string buildNumber); + /// + /// Generates build problem service message + /// + /// problem message + void WriteBuildProblem([NotNull] string description); + /// /// Generates build problem service message /// diff --git a/TeamCity.ServiceMessages/Write/Special/ITeamCityFlowWriter.cs b/TeamCity.ServiceMessages/Write/Special/ITeamCityFlowWriter.cs index cd64b9a..83863bb 100644 --- a/TeamCity.ServiceMessages/Write/Special/ITeamCityFlowWriter.cs +++ b/TeamCity.ServiceMessages/Write/Special/ITeamCityFlowWriter.cs @@ -6,9 +6,9 @@ namespace JetBrains.TeamCity.ServiceMessages.Write.Special /// /// Starts another flowId reporting starting. This call would emmit - ///
##teamcity[flowStarted flowId='%lt;new flow id>' parent='current flow id']
+ ///
##teamcity[flowStarted flowId='<new flow id>' parent='current flow id']
/// and - ///
##teamcity[flowFinished flowId='%lt;new flow id>']
+ ///
##teamcity[flowFinished flowId='<new flow id>']
/// on writer dispose ///
/// diff --git a/TeamCity.ServiceMessages/Write/Special/ITeamCityProgressWriter.cs b/TeamCity.ServiceMessages/Write/Special/ITeamCityProgressWriter.cs new file mode 100644 index 0000000..974cf5a --- /dev/null +++ b/TeamCity.ServiceMessages/Write/Special/ITeamCityProgressWriter.cs @@ -0,0 +1,41 @@ +namespace JetBrains.TeamCity.ServiceMessages.Write.Special +{ + using System; + + /// + /// + /// Use method to add progress message + ///
+    ///     ##teamcity[progressMessage '<message text>' ]
+    /// 
+ ///
+ /// + /// + /// Use method to add progress message + ///
##teamcity[progressStart '<message>']
+ /// and + ///
##teamcity[progressFinish '<message>']
+ /// on writer dispose. + ///
+ /// + /// http://confluence.jetbrains.net/display/TCD18/Build+Script+Interaction+with+TeamCity#BuildScriptInteractionwithTeamCity-ReportingMessagesForBuildLog + /// + ///
+ /// + /// Implementation is not thread-safe. Create an instance for each thread instead. + /// + public interface ITeamCityProgressWriter + { + /// + /// Writes normal message + /// + /// text + void WriteProgress([NotNull] string message); + + /// + /// Generates start flow message and returns disposable object to close flow + /// + /// + IDisposable OpenProgress(string message); + } +} \ No newline at end of file diff --git a/TeamCity.ServiceMessages/Write/Special/ITeamCityWriter.cs b/TeamCity.ServiceMessages/Write/Special/ITeamCityWriter.cs index 852ea7a..09db964 100644 --- a/TeamCity.ServiceMessages/Write/Special/ITeamCityWriter.cs +++ b/TeamCity.ServiceMessages/Write/Special/ITeamCityWriter.cs @@ -13,7 +13,7 @@ namespace JetBrains.TeamCity.ServiceMessages.Write.Special /// /// Implementation is not thread-safe. Create an instance for each thread instead. /// - public interface ITeamCityWriter : ITeamCityBlockWriter, ITeamCityFlowWriter, ITeamCityMessageWriter, ITeamCityTestsWriter, ITeamCityCompilationBlockWriter, ITeamCityArtifactsWriter, ITeamCityBuildStatusWriter, IDisposable + public interface ITeamCityWriter : ITeamCityBlockWriter, ITeamCityFlowWriter, ITeamCityMessageWriter, ITeamCityTestsWriter, ITeamCityCompilationBlockWriter, ITeamCityArtifactsWriter, ITeamCityBuildStatusWriter, ITeamCityProgressWriter, IDisposable { /// /// Allows sending bare service message diff --git a/TeamCity.ServiceMessages/Write/Special/Impl/TeamCityWriterFacade.cs b/TeamCity.ServiceMessages/Write/Special/Impl/TeamCityWriterFacade.cs index f1c9b98..57bd859 100644 --- a/TeamCity.ServiceMessages/Write/Special/Impl/TeamCityWriterFacade.cs +++ b/TeamCity.ServiceMessages/Write/Special/Impl/TeamCityWriterFacade.cs @@ -14,6 +14,7 @@ public class TeamCityWriterFacade : ITeamCityWriter private readonly ITeamCityMessageWriter _messageWriter; private readonly IServiceMessageProcessor _processor; private readonly ITeamCityBuildStatusWriter _statusWriter; + private readonly ITeamCityProgressWriter _progressWriter; private readonly ITeamCityTestsWriter _testsWriter; private volatile bool _isDisposed; @@ -26,6 +27,7 @@ public TeamCityWriterFacade( [NotNull] ITeamCityArtifactsWriter artifactsWriter, [NotNull] ITeamCityBuildStatusWriter statusWriter, [NotNull] ITeamCityFlowWriter flowWriter, + [NotNull] ITeamCityProgressWriter progressWriter, [NotNull] IDisposable disposeCallback) { if (processor == null) throw new ArgumentNullException(nameof(processor)); @@ -36,6 +38,7 @@ public TeamCityWriterFacade( if (artifactsWriter == null) throw new ArgumentNullException(nameof(artifactsWriter)); if (statusWriter == null) throw new ArgumentNullException(nameof(statusWriter)); if (flowWriter == null) throw new ArgumentNullException(nameof(flowWriter)); + if (progressWriter == null) throw new ArgumentNullException(nameof(progressWriter)); if (disposeCallback == null) throw new ArgumentNullException(nameof(disposeCallback)); _processor = processor; _blockWriter = blockWriter; @@ -45,6 +48,7 @@ public TeamCityWriterFacade( _artifactsWriter = artifactsWriter; _statusWriter = statusWriter; _flowWriter = flowWriter; + _progressWriter = progressWriter; _dispose = disposeCallback; } @@ -61,6 +65,13 @@ public void WriteBuildNumber(string buildNumber) _statusWriter.WriteBuildNumber(buildNumber); } + public void WriteBuildProblem(string description) + { + if (description == null) throw new ArgumentNullException(nameof(description)); + CheckConsistency(); + _statusWriter.WriteBuildProblem(description); + } + public void WriteBuildProblem(string identity, string message) { if (identity == null) throw new ArgumentNullException(nameof(identity)); @@ -106,6 +117,20 @@ public void WriteError(string text, string errorDetails = null) _messageWriter.WriteError(text, errorDetails); } + public void WriteProgress(string message) + { + if (message == null) throw new ArgumentNullException(nameof(message)); + CheckConsistency(); + _progressWriter.WriteProgress(message); + } + + public IDisposable OpenProgress(string message) + { + if (message == null) throw new ArgumentNullException(nameof(message)); + CheckConsistency(); + return _progressWriter.OpenProgress(message); + } + public virtual void Dispose() { _isDisposed = true; diff --git a/TeamCity.ServiceMessages/Write/Special/Impl/TeamCityWriterImpl.cs b/TeamCity.ServiceMessages/Write/Special/Impl/TeamCityWriterImpl.cs index b440164..68680ca 100644 --- a/TeamCity.ServiceMessages/Write/Special/Impl/TeamCityWriterImpl.cs +++ b/TeamCity.ServiceMessages/Write/Special/Impl/TeamCityWriterImpl.cs @@ -21,6 +21,7 @@ public TeamCityWriterImpl( new TeamCityMessageWriter(processor), new TeamCityArtifactsWriter(processor), new TeamCityBuildStatusWriter(processor), + new TeamCityProgressWriter(processor), dispose) { if (processor == null) throw new ArgumentNullException(nameof(processor)); @@ -36,8 +37,9 @@ private TeamCityWriterImpl( [NotNull] ITeamCityMessageWriter messageWriter, [NotNull] ITeamCityArtifactsWriter artifactsWriter, [NotNull] ITeamCityBuildStatusWriter statusWriter, + [NotNull] ITeamCityProgressWriter progressWriter, [NotNull] IDisposable dispose) - : base(processor, blockWriter, compilationWriter, testsWriter, messageWriter, artifactsWriter, statusWriter, flowWriter, dispose) + : base(processor, blockWriter, compilationWriter, testsWriter, messageWriter, artifactsWriter, statusWriter, flowWriter, progressWriter, dispose) { if (processor == null) throw new ArgumentNullException(nameof(processor)); if (flowWriter == null) throw new ArgumentNullException(nameof(flowWriter)); @@ -47,6 +49,7 @@ private TeamCityWriterImpl( if (messageWriter == null) throw new ArgumentNullException(nameof(messageWriter)); if (artifactsWriter == null) throw new ArgumentNullException(nameof(artifactsWriter)); if (statusWriter == null) throw new ArgumentNullException(nameof(statusWriter)); + if (progressWriter == null) throw new ArgumentNullException(nameof(progressWriter)); if (dispose == null) throw new ArgumentNullException(nameof(dispose)); _writeCheck = new ISubWriter[] {blockWriter, compilationWriter, testsWriter, flowWriter}; } diff --git a/TeamCity.ServiceMessages/Write/Special/Impl/Writer/TeamCityBuildStatusWriter.cs b/TeamCity.ServiceMessages/Write/Special/Impl/Writer/TeamCityBuildStatusWriter.cs index 0eb60fa..2d5dec9 100644 --- a/TeamCity.ServiceMessages/Write/Special/Impl/Writer/TeamCityBuildStatusWriter.cs +++ b/TeamCity.ServiceMessages/Write/Special/Impl/Writer/TeamCityBuildStatusWriter.cs @@ -18,6 +18,12 @@ public void WriteBuildNumber(string buildNumber) PostMessage(new ValueServiceMessage("buildNumber", buildNumber)); } + public void WriteBuildProblem(string description) + { + if (description == null) throw new ArgumentNullException(nameof(description)); + PostMessage(new ServiceMessage("buildProblem") {{"description", description}}); + } + public void WriteBuildProblem(string identity, string message) { if (identity == null) throw new ArgumentNullException(nameof(identity)); diff --git a/TeamCity.ServiceMessages/Write/Special/Impl/Writer/TeamCityFlowWriter.cs b/TeamCity.ServiceMessages/Write/Special/Impl/Writer/TeamCityFlowWriter.cs index a26120a..fc5a455 100644 --- a/TeamCity.ServiceMessages/Write/Special/Impl/Writer/TeamCityFlowWriter.cs +++ b/TeamCity.ServiceMessages/Write/Special/Impl/Writer/TeamCityFlowWriter.cs @@ -38,7 +38,7 @@ public TCloseBlock OpenFlow() processor ); - //##teamcity[flowStarted flowId='%lt;new flow id>' parent='current flow id'] + //##teamcity[flowStarted flowId='' parent='current flow id'] var flowStartedMessage = new ServiceMessage("flowStarted"); if (myTarget.FlowId != null) { @@ -69,7 +69,7 @@ private void CloseBlock([NotNull] IFlowAwareServiceMessageProcessor flowAwareSer _openChildFlowIds.Remove(flowAwareServiceMessageProcessor.FlowId); - //##teamcity[flowFinished flowId='%lt;new flow id>'] + //##teamcity[flowFinished flowId=''] flowAwareServiceMessageProcessor.AddServiceMessage(new ServiceMessage("flowFinished")); } } diff --git a/TeamCity.ServiceMessages/Write/Special/Impl/Writer/TeamCityProgressWriter.cs b/TeamCity.ServiceMessages/Write/Special/Impl/Writer/TeamCityProgressWriter.cs new file mode 100644 index 0000000..b283735 --- /dev/null +++ b/TeamCity.ServiceMessages/Write/Special/Impl/Writer/TeamCityProgressWriter.cs @@ -0,0 +1,26 @@ +namespace JetBrains.TeamCity.ServiceMessages.Write.Special.Impl.Writer +{ + using System; + + public class TeamCityProgressWriter : BaseWriter, ITeamCityProgressWriter + { + public TeamCityProgressWriter(IServiceMessageProcessor target) + : base(target) + { + if (target == null) throw new ArgumentNullException(nameof(target)); + } + + public void WriteProgress(string message) + { + if (message == null) throw new ArgumentNullException(nameof(message)); + PostMessage(new ValueServiceMessage("progressMessage", message)); + } + + public IDisposable OpenProgress(string message) + { + if (message == null) throw new ArgumentNullException(nameof(message)); + PostMessage(new ValueServiceMessage("progressStart", message)); + return new DisposableDelegate(() => PostMessage(new ValueServiceMessage("progressFinish", message))); + } + } +} \ No newline at end of file