From eef77b18646bd16d9070b7dab0d33034792e1698 Mon Sep 17 00:00:00 2001 From: pomianowski <13592821+pomianowski@users.noreply.github.com> Date: Tue, 19 Mar 2024 22:26:55 +0100 Subject: [PATCH] Update workflows --- .github/labeler.yml | 33 +++++++++++++++++ .../workflows/openapi-client-cd-nuget.yaml | 35 +++++++++++++++++++ .github/workflows/openapi-client-labeler.yaml | 15 ++++++++ .../openapi-client-pr-validator.yaml | 31 ++++++++++++++++ .../Generation/ClientGenerator.Class.cs | 15 ++++---- .../Generation/ClientGenerator.Interface.cs | 7 ++-- .../Generation/ClientGenerator.Result.cs | 21 ++++++----- .../Generation/ClientGenerator.Types.cs | 1 + .../Generation/ClientGenerator.cs | 11 +++--- .../OpenApiClientGenerationHelper.cs | 22 ++++-------- 10 files changed, 152 insertions(+), 39 deletions(-) create mode 100644 .github/labeler.yml create mode 100644 .github/workflows/openapi-client-cd-nuget.yaml create mode 100644 .github/workflows/openapi-client-labeler.yaml create mode 100644 .github/workflows/openapi-client-pr-validator.yaml diff --git a/.github/labeler.yml b/.github/labeler.yml new file mode 100644 index 0000000..deca2c5 --- /dev/null +++ b/.github/labeler.yml @@ -0,0 +1,33 @@ +release: + - base-branch: 'main' + +PR: + - base-branch: [ 'main', 'development' ] + +github_actions: +- changed-files: + - any-glob-to-any-file: '.github/workflows/**' + +documentation: +- changed-files: + - any-glob-to-any-file: [ 'docs/**', 'documentation/**' ] + +dotnet: +- changed-files: + - any-glob-to-any-file: '**/*.cs' + +update: +- changed-files: + - any-glob-to-any-file: 'src/Directory.Build.props' + +NuGet: +- changed-files: + - any-glob-to-any-file: [ 'src/OpenApi.Client/**', 'src/Directory.Packages.props' ] + +dependencies: +- changed-files: + - any-glob-to-any-file: [ 'src/Directory.Packages.props' ] + +source-generators: +- changed-files: + - any-glob-to-any-file: [ 'src/OpenApi.Client.SourceGenerators/**' ] diff --git a/.github/workflows/openapi-client-cd-nuget.yaml b/.github/workflows/openapi-client-cd-nuget.yaml new file mode 100644 index 0000000..84c75b4 --- /dev/null +++ b/.github/workflows/openapi-client-cd-nuget.yaml @@ -0,0 +1,35 @@ +name: openapi-client-cd-nuget + +on: + push: + branches: [main] + + workflow_dispatch: + +jobs: + deploy: + runs-on: windows-latest + steps: + - uses: actions/checkout@v4 + - uses: microsoft/setup-msbuild@v1.3 + with: + msbuild-architecture: x64 + - uses: nuget/setup-nuget@v2 + with: + nuget-api-key: ${{ secrets.NUGET_API_KEY }} + - name: Setup .NET Core SDK 8.x + uses: actions/setup-dotnet@v4 + with: + dotnet-version: 8.x + + - name: Install dependencies + run: dotnet restore + + - name: Build + run: dotnet build src\OpenApi.Client\OpenApi.Client.csproj --configuration Release --no-restore + + - name: Publish the package to NuGet.org + run: nuget push **\*.nupkg -NonInteractive -SkipDuplicate -Source 'https://api.nuget.org/v3/index.json' + + - name: Publish the symbols to NuGet.org + run: nuget push **\*.snupkg -NonInteractive -SkipDuplicate -Source 'https://api.nuget.org/v3/index.json' diff --git a/.github/workflows/openapi-client-labeler.yaml b/.github/workflows/openapi-client-labeler.yaml new file mode 100644 index 0000000..346599e --- /dev/null +++ b/.github/workflows/openapi-client-labeler.yaml @@ -0,0 +1,15 @@ +name: openapi-client-labeler + +on: + - pull_request_target + +jobs: + triage: + permissions: + contents: read + pull-requests: write + runs-on: ubuntu-latest + steps: + - uses: actions/labeler@v5 + with: + repo-token: "${{ secrets.GITHUB_TOKEN }}" diff --git a/.github/workflows/openapi-client-pr-validator.yaml b/.github/workflows/openapi-client-pr-validator.yaml new file mode 100644 index 0000000..7317f9e --- /dev/null +++ b/.github/workflows/openapi-client-pr-validator.yaml @@ -0,0 +1,31 @@ +name: openapi-client-pr-validator + +on: + pull_request: + branches: [development] + push: + branches: [development] + + workflow_dispatch: + +jobs: + build: + runs-on: windows-latest + steps: + - uses: actions/checkout@v4 + - uses: microsoft/setup-msbuild@v1.3 + with: + msbuild-architecture: x64 + - uses: nuget/setup-nuget@v2 + with: + nuget-api-key: ${{ secrets.NUGET_API_KEY }} + - name: Setup .NET Core SDK 8.x + uses: actions/setup-dotnet@v4 + with: + dotnet-version: 8.x + + - name: Install dependencies + run: dotnet restore + + - name: Build + run: dotnet build src\OpenApi.Client\OpenApi.Client.csproj --configuration Release --no-restore diff --git a/src/OpenApi.Client.SourceGenerators/Generation/ClientGenerator.Class.cs b/src/OpenApi.Client.SourceGenerators/Generation/ClientGenerator.Class.cs index e5f2a70..ee4e47f 100644 --- a/src/OpenApi.Client.SourceGenerators/Generation/ClientGenerator.Class.cs +++ b/src/OpenApi.Client.SourceGenerators/Generation/ClientGenerator.Class.cs @@ -10,7 +10,8 @@ namespace OpenApi.Client.SourceGenerators.Genertion; internal sealed partial class ClientGenerator { public const string ClassHeader = """ - %A partial class %C : I%C + [global::System.CodeDom.Compiler.GeneratedCode("OpenApiClient", "%VERSION%")] + %ACCESS% partial class %CLASS% : I%CLASS% { private global::System.Net.HttpStatusCode? lastStatusCode; @@ -20,7 +21,7 @@ internal sealed partial class ClientGenerator /// Options for the serializer used to create API objects. protected readonly global::System.Text.Json.JsonSerializerOptions JsonSettings; - public %C(global::System.Net.Http.HttpClient httpClient) + public %CLASS%(global::System.Net.Http.HttpClient httpClient) : this(httpClient, new global::System.Text.Json.JsonSerializerOptions { PropertyNameCaseInsensitive = true, @@ -32,11 +33,11 @@ internal sealed partial class ClientGenerator { } - protected %C() : this(default!, default!) + protected %CLASS%() : this(default!, default!) { } - protected %C(global::System.Net.Http.HttpClient httpClient, global::System.Text.Json.JsonSerializerOptions jsonSettings) + protected %CLASS%(global::System.Net.Http.HttpClient httpClient, global::System.Text.Json.JsonSerializerOptions jsonSettings) { HttpClient = httpClient; JsonSettings = jsonSettings; @@ -160,7 +161,7 @@ public static void AppendClass(StringBuilder builder, OpenApiContract contract) } builder.Append( - " public virtual async global::System.Threading.Tasks.Task<%CResult" + " public virtual async global::System.Threading.Tasks.Task<%CLASS%Result" ); if (path.ResponseType?.Length > 0) @@ -210,10 +211,10 @@ public static void AppendClass(StringBuilder builder, OpenApiContract contract) } catch (global::System.Exception e) { - return new %CResult(new %CResultError[]{new %CResultError(e.Message)}, lastStatusCode); + return new %CLASS%Result(new %CLASS%ResultError[]{new %CLASS%ResultError(e.Message)}, lastStatusCode); } - return new %CResult(lastStatusCode); + return new %CLASS%Result(lastStatusCode); } """ ); diff --git a/src/OpenApi.Client.SourceGenerators/Generation/ClientGenerator.Interface.cs b/src/OpenApi.Client.SourceGenerators/Generation/ClientGenerator.Interface.cs index e28ef40..7754f8f 100644 --- a/src/OpenApi.Client.SourceGenerators/Generation/ClientGenerator.Interface.cs +++ b/src/OpenApi.Client.SourceGenerators/Generation/ClientGenerator.Interface.cs @@ -10,9 +10,10 @@ namespace OpenApi.Client.SourceGenerators.Genertion; internal sealed partial class ClientGenerator { public const string InterfaceHeader = """ - /// An interface for the %T Open API Client. + /// An interface for the %TITLE% Open API Client. /// Generated with Open API Client Source Generator. See: - %A interface I%C + [global::System.CodeDom.Compiler.GeneratedCode("OpenApiClient", "%VERSION%")] + %ACCESS% interface I%CLASS% { /// Gets the last status code from the HTTP request. global::System.Net.HttpStatusCode? GetLastStatusCode(); @@ -43,7 +44,7 @@ public static void AppendInterface(StringBuilder builder, OpenApiContract contra builder.AppendLine(""); } - builder.Append(" global::System.Threading.Tasks.Task<%CResult"); + builder.Append(" global::System.Threading.Tasks.Task<%CLASS%Result"); if (path.ResponseType?.Length > 0) { diff --git a/src/OpenApi.Client.SourceGenerators/Generation/ClientGenerator.Result.cs b/src/OpenApi.Client.SourceGenerators/Generation/ClientGenerator.Result.cs index 585da88..6224bee 100644 --- a/src/OpenApi.Client.SourceGenerators/Generation/ClientGenerator.Result.cs +++ b/src/OpenApi.Client.SourceGenerators/Generation/ClientGenerator.Result.cs @@ -9,10 +9,11 @@ internal sealed partial class ClientGenerator { public const string ResultTemplate = """ /// Represents a result of the API call. - %A struct %CResultError + [global::System.CodeDom.Compiler.GeneratedCode("OpenApiClient", "%VERSION%")] + %ACCESS% struct %CLASS%ResultError { /// Initializes a new instance of the error struct. - public %CResultError(string message) + public %CLASS%ResultError(string message) { Message = message; } @@ -22,12 +23,13 @@ internal sealed partial class ClientGenerator } /// Represents a result of the API call. - %A class %CResult + [global::System.CodeDom.Compiler.GeneratedCode("OpenApiClient", "%VERSION%")] + %ACCESS% class %CLASS%Result { /// Initializes a new instance of the class. /// The errors of the API call. /// The status code of the API call. - public %CResult(%CResultError[] errors, global::System.Net.HttpStatusCode? statusCode) + public %CLASS%Result(%CLASS%ResultError[] errors, global::System.Net.HttpStatusCode? statusCode) { Errors = errors; StatusCode = statusCode; @@ -35,7 +37,7 @@ internal sealed partial class ClientGenerator /// Initializes a new instance of the result class. /// The status code of the API call. - public %CResult(global::System.Net.HttpStatusCode? statusCode) : this(new %CResultError[0], statusCode) + public %CLASS%Result(global::System.Net.HttpStatusCode? statusCode) : this(new %CLASS%ResultError[0], statusCode) { } @@ -43,7 +45,7 @@ internal sealed partial class ClientGenerator public global::System.Net.HttpStatusCode? StatusCode { get; } /// Gets the errors of the API call. - public %CResultError[] Errors { get; } + public %CLASS%ResultError[] Errors { get; } /// Gets a value indicating whether the API call has errors. public bool HasErrors @@ -56,14 +58,15 @@ public bool HasErrors } /// Represents a result from the API. - %A sealed class %CResult : %CResult where TResult : class + [global::System.CodeDom.Compiler.GeneratedCode("OpenApiClient", "%VERSION%")] + %ACCESS% sealed class %CLASS%Result : %CLASS%Result where TResult : class { private readonly TResult? _result; /// Initializes a new instance of the result class. /// Result of the API call. /// The status code of the API call. - public %CResult(TResult result, global::System.Net.HttpStatusCode? statusCode) : base(statusCode) + public %CLASS%Result(TResult result, global::System.Net.HttpStatusCode? statusCode) : base(statusCode) { if (result == null) { @@ -76,7 +79,7 @@ public bool HasErrors /// Initializes a new instance of the result class. /// The errors of the API call. /// The errors of the API call. - public %CResult(%CResultError[] errors, global::System.Net.HttpStatusCode? statusCode) : base(errors, statusCode) + public %CLASS%Result(%CLASS%ResultError[] errors, global::System.Net.HttpStatusCode? statusCode) : base(errors, statusCode) { } diff --git a/src/OpenApi.Client.SourceGenerators/Generation/ClientGenerator.Types.cs b/src/OpenApi.Client.SourceGenerators/Generation/ClientGenerator.Types.cs index 8c1818d..5469680 100644 --- a/src/OpenApi.Client.SourceGenerators/Generation/ClientGenerator.Types.cs +++ b/src/OpenApi.Client.SourceGenerators/Generation/ClientGenerator.Types.cs @@ -32,6 +32,7 @@ public static void AppendTypes(StringBuilder builder, OpenApiContract contract) builder.AppendLine(""); } + builder.AppendLine(" [global::System.CodeDom.Compiler.GeneratedCode(\"OpenApiClient\", \"%VERSION%\")]"); builder.Append(" public sealed class "); builder.AppendLine(type.Name); builder.AppendLine(" {"); diff --git a/src/OpenApi.Client.SourceGenerators/Generation/ClientGenerator.cs b/src/OpenApi.Client.SourceGenerators/Generation/ClientGenerator.cs index ca50bea..9fd9189 100644 --- a/src/OpenApi.Client.SourceGenerators/Generation/ClientGenerator.cs +++ b/src/OpenApi.Client.SourceGenerators/Generation/ClientGenerator.cs @@ -9,7 +9,9 @@ namespace OpenApi.Client.SourceGenerators.Genertion; internal sealed partial class ClientGenerator(OpenApiContract contract) { - public static readonly string[] Placeholders = ["%C", "%T", "%A"]; + public const string GeneratorVersion = "1.0.0"; + + public static readonly string[] Placeholders = ["%CLASS%", "%TITLE%", "%ACCESS%", "%VERSION%"]; public const string DocumentPrefix = """ // @@ -43,9 +45,10 @@ public GenerationResult Generate() builder.AppendLine("}"); - builder.Replace("%C", contract.ClassName); - builder.Replace("%T", RemoveUnsafeWords(contract.Title)); - builder.Replace("%A", contract.Access); + builder.Replace("%CLASS%", contract.ClassName); + builder.Replace("%TITLE%", RemoveUnsafeWords(contract.Title)); + builder.Replace("%ACCESS%", contract.Access); + builder.Replace("%VERSION%", GeneratorVersion); return builder.ToString(); } diff --git a/src/OpenApi.Client.SourceGenerators/OpenApiClientGenerationHelper.cs b/src/OpenApi.Client.SourceGenerators/OpenApiClientGenerationHelper.cs index 5fa0987..6d9a6a1 100644 --- a/src/OpenApi.Client.SourceGenerators/OpenApiClientGenerationHelper.cs +++ b/src/OpenApi.Client.SourceGenerators/OpenApiClientGenerationHelper.cs @@ -14,41 +14,31 @@ internal static class OpenApiClientGenerationHelper #nullable enable namespace OpenApi.Client { - /// - /// Library which API should use at runtime. - /// + /// Library which API client should use at runtime. internal enum OpenApiClientSerialization { SystemTextJson, NewtonsoftJson } - /// An attribute that indicates that a given class should have an Open API Client generated for it. + /// Indicates that a given class should have an Open API Client generated for it. /// Generated with Open API Client Source Generator. See: [global::System.AttributeUsage(global::System.AttributeTargets.Class, AllowMultiple = false, Inherited = false)] internal sealed class OpenApiClientAttribute : global::System.Attribute { - /// - /// Initializes a new instance of the class. - /// + /// Initializes a new instance of the class. /// The specification resource name for the Open API Client. - /// - /// The specification is the name of the resource which is a yaml or json open api code. - /// + /// The specification is the name of the resource which is a yaml or json open api code. public OpenApiClientAttribute(string specification) { Specification = specification; Serialization = OpenApiClientSerialization.SystemTextJson; } - /// - /// Initializes a new instance of the class. - /// + /// Initializes a new instance of the class. /// The specification resource name for the Open API Client. /// A flag indicating whether to use the Service Collection for the Open API Client. - /// - /// The specification is the name of the resource which is a yaml or json open api code. - /// + /// The specification is the name of the resource which is a yaml or json open api code. public OpenApiClientAttribute(string specification, OpenApiClientSerialization serializationTool) { Specification = specification;