diff --git a/.github/workflows/release-internal.yml b/.github/workflows/release-beta.yml
similarity index 97%
rename from .github/workflows/release-internal.yml
rename to .github/workflows/release-beta.yml
index 1231b9e6..9cbebb05 100644
--- a/.github/workflows/release-internal.yml
+++ b/.github/workflows/release-beta.yml
@@ -1,7 +1,9 @@
name: Publish beta NuGet package
on:
workflow_dispatch:
-
+ push:
+ branches:
+ - vnext
jobs:
check:
runs-on: ubuntu-latest
diff --git a/.github/workflows/release-manual.yml b/.github/workflows/release-manual.yml
new file mode 100644
index 00000000..0eeca64b
--- /dev/null
+++ b/.github/workflows/release-manual.yml
@@ -0,0 +1,28 @@
+name: Publish custom NuGet package version
+on:
+ workflow_dispatch:
+ inputs:
+ package_version:
+ description: 'NuGet package version (e.g. 6.0.0-beta.1041)'
+ required: true
+
+jobs:
+ pre-release:
+ runs-on: ubuntu-latest
+ name: Publish NuGet packages
+ environment: AsyncAPI
+ strategy:
+ matrix:
+ package-name: [ "LEGO.AsyncAPI", "LEGO.AsyncAPI.Readers", "LEGO.AsyncAPI.Bindings" ]
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v1
+
+ - name: Setup .NET Core @ Latest
+ uses: actions/setup-dotnet@v1
+
+ - name: Build ${{ matrix.package-name }} project and pack NuGet package
+ run: dotnet pack src/${{ matrix.package-name }}/${{ matrix.package-name }}.csproj -c Release -o out-${{ matrix.package-name }} -p:PackageVersion=${{ github.event.inputs.package_version }}
+
+ - name: Push generated package to NuGet
+ run: dotnet nuget push out-${{ matrix.package-name }}/*.nupkg -s https://api.nuget.org/v3/index.json --skip-duplicate -n --api-key ${{secrets.NUGET}}
diff --git a/CODEOWNERS b/CODEOWNERS
index f1759cb1..2e87be63 100644
--- a/CODEOWNERS
+++ b/CODEOWNERS
@@ -1 +1 @@
-* @VisualBean
+* @VisualBean @UlrikSandberg
diff --git a/src/LEGO.AsyncAPI/LEGO.AsyncAPI.csproj b/src/LEGO.AsyncAPI/LEGO.AsyncAPI.csproj
index 99e69016..a321a003 100644
--- a/src/LEGO.AsyncAPI/LEGO.AsyncAPI.csproj
+++ b/src/LEGO.AsyncAPI/LEGO.AsyncAPI.csproj
@@ -19,7 +19,7 @@
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
<_Parameter1>$(MSBuildProjectName).Tests
diff --git a/src/LEGO.AsyncAPI/Models/AsyncApiDocument.cs b/src/LEGO.AsyncAPI/Models/AsyncApiDocument.cs
index 5be55202..b6488883 100644
--- a/src/LEGO.AsyncAPI/Models/AsyncApiDocument.cs
+++ b/src/LEGO.AsyncAPI/Models/AsyncApiDocument.cs
@@ -6,8 +6,8 @@ namespace LEGO.AsyncAPI.Models
using System.Collections.Generic;
using LEGO.AsyncAPI.Exceptions;
using LEGO.AsyncAPI.Models.Interfaces;
- using LEGO.AsyncAPI.Writers;
using LEGO.AsyncAPI.Services;
+ using LEGO.AsyncAPI.Writers;
///
/// This is the root document object for the API specification. It combines resource listing and API declaration together into one document.
@@ -46,7 +46,7 @@ public class AsyncApiDocument : IAsyncApiExtensible, IAsyncApiSerializable
///
/// REQUIRED. The available channels and messages for the API.
///
- public IDictionary Channels { get; set; } = new Dictionary();
+ public IDictionary Channels { get; set; }
///
/// an element to hold various schemas for the specification.
diff --git a/src/LEGO.AsyncAPI/Validation/Rules/AsyncApiDocumentRules.cs b/src/LEGO.AsyncAPI/Validation/Rules/AsyncApiDocumentRules.cs
index 27076369..264c1611 100644
--- a/src/LEGO.AsyncAPI/Validation/Rules/AsyncApiDocumentRules.cs
+++ b/src/LEGO.AsyncAPI/Validation/Rules/AsyncApiDocumentRules.cs
@@ -30,7 +30,7 @@ public static class AsyncApiDocumentRules
context.Exit();
context.Enter("channels");
- if (document.Channels == null || !document.Channels.Keys.Any())
+ if (document.Channels == null)
{
context.CreateError(
nameof(DocumentRequiredFields),
diff --git a/src/LEGO.AsyncAPI/Writers/AsyncApiWriterExtensions.cs b/src/LEGO.AsyncAPI/Writers/AsyncApiWriterExtensions.cs
index 67c4737a..25777d51 100644
--- a/src/LEGO.AsyncAPI/Writers/AsyncApiWriterExtensions.cs
+++ b/src/LEGO.AsyncAPI/Writers/AsyncApiWriterExtensions.cs
@@ -285,10 +285,7 @@ public static void WriteRequiredMap(
Action action)
where T : IAsyncApiElement
{
- if (elements != null && elements.Any())
- {
- writer.WriteMapInternal(name, elements, action);
- }
+ writer.WriteMapInternal(name, elements, action);
}
///
diff --git a/test/LEGO.AsyncAPI.Tests/AsyncApiDocumentBuilder.cs b/test/LEGO.AsyncAPI.Tests/AsyncApiDocumentBuilder.cs
index 3f2ee429..886fb7bf 100644
--- a/test/LEGO.AsyncAPI.Tests/AsyncApiDocumentBuilder.cs
+++ b/test/LEGO.AsyncAPI.Tests/AsyncApiDocumentBuilder.cs
@@ -2,9 +2,10 @@
namespace LEGO.AsyncAPI.Tests
{
+ using System;
+ using System.Collections.Generic;
using LEGO.AsyncAPI.Models;
using LEGO.AsyncAPI.Models.Interfaces;
- using System;
internal class AsyncApiDocumentBuilder
{
@@ -42,6 +43,10 @@ public AsyncApiDocumentBuilder WithDefaultContentType(string contentType = "appl
public AsyncApiDocumentBuilder WithChannel(string key, AsyncApiChannel channel)
{
+ if (this.document.Channels == null)
+ {
+ this.document.Channels = new Dictionary();
+ }
this.document.Channels.Add(key, channel);
return this;
}
diff --git a/test/LEGO.AsyncAPI.Tests/AsyncApiDocumentV2Tests.cs b/test/LEGO.AsyncAPI.Tests/AsyncApiDocumentV2Tests.cs
index 63e818b4..13ae85e5 100644
--- a/test/LEGO.AsyncAPI.Tests/AsyncApiDocumentV2Tests.cs
+++ b/test/LEGO.AsyncAPI.Tests/AsyncApiDocumentV2Tests.cs
@@ -1202,6 +1202,10 @@ public void Serialize_WithBindingReferences_SerializesDeserializes()
},
},
};
+ if (doc.Channels == null)
+ {
+ doc.Channels = new Dictionary();
+ }
doc.Channels.Add(
"testChannel",
new AsyncApiChannel
@@ -1260,6 +1264,10 @@ public void Serializev2_WithBindings_Serializes()
Protocol = "pulsar+ssl",
Url = "example.com",
});
+ if (doc.Channels == null)
+ {
+ doc.Channels = new Dictionary();
+ }
doc.Channels.Add(
"testChannel",
new AsyncApiChannel
@@ -1325,5 +1333,36 @@ public void Serializev2_WithBindings_Serializes()
Assert.AreEqual("this mah binding", httpBinding.Headers.Description);
}
+
+
+
+ [Test]
+ public void SerializeV2_EmptyChannelObject_DeserializeAndSerializePreserveChannelObject()
+ {
+ // Arrange
+ var spec = """
+ asyncapi: 2.6.0
+ info:
+ title: Spec with missing channel info
+ description: test description
+ servers:
+ production:
+ url: example.com
+ protocol: pulsar+ssl
+ description: test description
+ channels: { }
+ """;
+
+ var settings = new AsyncApiReaderSettings();
+ var reader = new AsyncApiStringReader(settings);
+
+ // Act
+ var deserialized = reader.Read(spec, out var diagnostic);
+ var actual = deserialized.Serialize(AsyncApiVersion.AsyncApi2_0, AsyncApiFormat.Yaml);
+
+ // Assert
+ actual.Should()
+ .BePlatformAgnosticEquivalentTo(spec);
+ }
}
}
\ No newline at end of file