From 4b99c8e56c1707efcbf243bf59c593475efa33c8 Mon Sep 17 00:00:00 2001 From: Artifizer Date: Sat, 26 Sep 2026 02:59:41 +0300 Subject: [PATCH 1/3] ci: add GitHub Actions CI workflow Add a CI workflow mirroring the sibling implementations (gts-go, gts-rust, gts-ts): a cross-platform test job (ubuntu/windows/macos) running format, analyzer, build, and unit-test gates, plus Ubuntu-only security (vulnerable NuGet scan), coverage (Cobertura -> Codecov), and gts-spec conformance jobs. All jobs drive the existing Makefile targets so local `make check` and CI stay in lockstep. global.json intentionally stays permissive ("8.0.0" + rollForward=latestMajor, i.e. "min .NET 8, use whatever newer SDK is present"). Since that pin is not a downloadable build, setup-dotnet installs the 8.0.x SDK band explicitly rather than resolving from global.json. A minimal .editorconfig pins the baseline whitespace conventions the fmt/lint gates enforce. Signed-off-by: Artifizer --- .editorconfig | 20 ++++++ .github/workflows/ci.yml | 142 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 162 insertions(+) create mode 100644 .editorconfig create mode 100644 .github/workflows/ci.yml diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..aac61eb --- /dev/null +++ b/.editorconfig @@ -0,0 +1,20 @@ +root = true + +# Baseline whitespace conventions enforced by `make fmt` (dotnet format). +# Kept intentionally minimal so the formatter's built-in C# defaults apply +# without imposing heavy style opinions. +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true +indent_style = space + +[*.cs] +indent_size = 4 + +[*.{csproj,props,targets}] +indent_size = 2 + +[*.{json,yml,yaml}] +indent_size = 2 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..751024a --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,142 @@ +name: CI + +on: + push: + branches: [ main, develop ] + paths-ignore: + - '**/*.md' + - 'docs/**' + pull_request: + branches: [ main, develop ] + paths-ignore: + - '**/*.md' + - 'docs/**' + +# Cancel previous runs for the same ref to save CI minutes. +concurrency: + group: ci-${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +permissions: + contents: read + +env: + DOTNET_NOLOGO: 'true' + DOTNET_CLI_TELEMETRY_OPTOUT: 'true' + DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 'true' + +jobs: + test: + name: Test Suite (${{ matrix.os }}) + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ ubuntu-latest, windows-latest, macos-latest ] + + steps: + - name: Force LF in working tree (w/a for Windows) + if: runner.os == 'Windows' + shell: bash + run: | + git config --global core.autocrlf false + git config --global core.eol lf + + - name: Checkout + uses: actions/checkout@v4 + with: + clean: 'true' + + # Install the .NET 8 SDK for the net8.0 target. global.json intentionally + # stays permissive ("8.0.0" + rollForward=latestMajor, i.e. "min .NET 8, + # use whatever newer SDK is present"); that pin is not a downloadable + # build, so we install an 8.0 SDK explicitly rather than via global.json. + - name: Set up .NET + uses: actions/setup-dotnet@v4 + with: + dotnet-version: '8.0.x' + + - name: Show .NET version + run: dotnet --info + + - name: Restore + run: dotnet restore gts-dotnet.sln + + # Formatting check (fast fail for style issues) + - name: dotnet format (check) + run: make fmt + + # Analyzers (linter) + - name: dotnet format analyzers (check) + run: make lint + + # Build + - name: build + run: dotnet build gts-dotnet.sln -c Release --no-restore + + # Unit tests + - name: test + run: dotnet test gts-dotnet.sln -c Release --no-build + + security: + name: Security (dotnet list package --vulnerable on Ubuntu) + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up .NET + uses: actions/setup-dotnet@v4 + with: + dotnet-version: '8.0.x' + + - name: Restore + run: dotnet restore gts-dotnet.sln + + # Report vulnerable NuGet dependencies but do not fail CI. + - name: dotnet list package --vulnerable + run: make security + continue-on-error: true + + coverage: + name: Code Coverage + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up .NET + uses: actions/setup-dotnet@v4 + with: + dotnet-version: '8.0.x' + + # Generate a Cobertura coverage report. + - name: Run tests with coverage + run: dotnet test gts-dotnet.sln -c Release --collect:"XPlat Code Coverage" + + # Upload to Codecov; do not fail CI if Codecov is down/misconfigured. + - name: Upload to Codecov + uses: codecov/codecov-action@v4 + with: + files: '**/coverage.cobertura.xml' + fail_ci_if_error: false + # token: ${{ secrets.CODECOV_TOKEN }} # Uncomment if required for private repos + + gts-spec-tests: + name: GTS Spec Tests + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up .NET + uses: actions/setup-dotnet@v4 + with: + dotnet-version: '8.0.x' + + # Builds the gts CLI binary, pulls the gts-spec test-runner image from + # GHCR (tag from .gts-spec-version), starts the server natively, waits + # for readiness, then runs pytest inside the container against + # host.docker.internal:$PORT. See Makefile. + - name: Run gts-spec tests via docker + run: make gts-spec-tests From ed1dd89320830ba9774a9e6e33212a5acd1bfe85 Mon Sep 17 00:00:00 2001 From: Artifizer Date: Thu, 1 Oct 2026 01:39:18 +0300 Subject: [PATCH 2/3] style: format solution with dotnet format Apply the .editorconfig-driven whitespace/style conventions the new CI fmt/lint gates enforce (final newlines, BOM removal) across files that were not yet normalized on main. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- Gts.Application/GtsHttpApiHelpers.cs | 2 +- Gts.Application/GtsHttpContracts.cs | 2 +- Gts.Application/GtsOperationEndpoints.cs | 2 +- Gts.Store/GtsCastService.cs | 2 +- Gts.Store/GtsInstanceValidationService.cs | 2 +- Gts.Store/GtsRefConstraint.cs | 2 +- Gts.Store/GtsSchemaCompatibilityService.cs | 2 +- Gts.Store/GtsSchemaDependencyGraph.cs | 2 +- Gts.Store/GtsSchemaValidationService.cs | 2 +- Gts.Store/GtsTraitComposer.cs | 2 +- Gts.Store/Validation/GtsFormatRegistry.cs | 2 +- Gts.Store/Validation/GtsJson.cs | 2 +- Gts.Store/Validation/GtsJsonPointer.cs | 2 +- Gts.Store/Validation/GtsJsonSchemaEngine.cs | 2 +- Gts.Store/Validation/GtsJsonSchemaEvaluator.cs | 2 +- Gts.Store/Validation/IGtsJsonSchemaEngine.cs | 2 +- Gts.Tests/Extraction/ExtractBasicTests.cs | 2 +- Gts.Tests/Extraction/ExtractEntityTests.cs | 4 ++-- Gts.Tests/Extraction/ExtractSchemaTests.cs | 2 +- Gts.Tests/GtsIdTests.cs | 2 +- Gts.Tests/Parsing/IdentifierParserTests.cs | 2 +- Gts.Tests/Parsing/InstanceParserTests.cs | 4 ++-- Gts.Tests/Parsing/PatternParserTests.cs | 4 ++-- Gts.Tests/Parsing/SectionParserTests.cs | 4 ++-- Gts.Tests/Parsing/SegmentParserTests.cs | 2 +- Gts.Tests/Parsing/TypeParserTests.cs | 4 ++-- Gts.Tests/Parsing/VersionParserTests.cs | 2 +- Gts.Tests/Validation/JsonInfrastructureTests.cs | 2 +- Gts/Parsing/GtsIdParser.cs | 2 +- Gts/Parsing/ParseException.cs | 2 +- Gts/Properties/AssemblyInfo.cs | 2 +- 31 files changed, 36 insertions(+), 36 deletions(-) diff --git a/Gts.Application/GtsHttpApiHelpers.cs b/Gts.Application/GtsHttpApiHelpers.cs index f5d8b4c..d8439b6 100644 --- a/Gts.Application/GtsHttpApiHelpers.cs +++ b/Gts.Application/GtsHttpApiHelpers.cs @@ -75,4 +75,4 @@ internal static JsonObject ResolveSchemaRefs(JsonObject schema, IReadOnlyDiction if (result.Errors is { Count: > 0 }) return string.Join("; ", result.Errors); return result.FailureReason == GtsValidationFailure.PrecedentIncompatible ? "Parent GTS Type Schema not found" : result.FailureReason?.ToWire() ?? "JSON Schema validation failed"; } -} \ No newline at end of file +} diff --git a/Gts.Application/GtsHttpContracts.cs b/Gts.Application/GtsHttpContracts.cs index df9c210..963be8c 100644 --- a/Gts.Application/GtsHttpContracts.cs +++ b/Gts.Application/GtsHttpContracts.cs @@ -17,4 +17,4 @@ internal static class GtsHttpJson { PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower }; -} \ No newline at end of file +} diff --git a/Gts.Application/GtsOperationEndpoints.cs b/Gts.Application/GtsOperationEndpoints.cs index 935a8ba..855ac93 100644 --- a/Gts.Application/GtsOperationEndpoints.cs +++ b/Gts.Application/GtsOperationEndpoints.cs @@ -128,4 +128,4 @@ JsonValue value when value.TryGetValue(out var decimalNumber) => Result _ => Results.Json(new { resolved = true, value = result.Value?.DeepClone() }) }; } -} \ No newline at end of file +} diff --git a/Gts.Store/GtsCastService.cs b/Gts.Store/GtsCastService.cs index b22a8d5..b8818dc 100644 --- a/Gts.Store/GtsCastService.cs +++ b/Gts.Store/GtsCastService.cs @@ -80,4 +80,4 @@ private static JsonObject CanonicalSchema(JsonObject schema) => : schema; private static GtsInstanceCastResult Failure(string? id, GtsId target, GtsValidationFailure reason) => new() { Ok = false, InstanceId = id, ToSchemaId = target, FailureReason = reason }; -} \ No newline at end of file +} diff --git a/Gts.Store/GtsInstanceValidationService.cs b/Gts.Store/GtsInstanceValidationService.cs index 3f4e5bc..a4d3886 100644 --- a/Gts.Store/GtsInstanceValidationService.cs +++ b/Gts.Store/GtsInstanceValidationService.cs @@ -139,4 +139,4 @@ private static bool HasMixedDialectReferences(JsonNode? node, string dialect, IR } return node is JsonArray array && array.Any(child => HasMixedDialectReferences(child, dialect, schemas, visited)); } -} \ No newline at end of file +} diff --git a/Gts.Store/GtsRefConstraint.cs b/Gts.Store/GtsRefConstraint.cs index 2775dc9..8e91a45 100644 --- a/Gts.Store/GtsRefConstraint.cs +++ b/Gts.Store/GtsRefConstraint.cs @@ -30,4 +30,4 @@ internal bool Matches(string value) // requires a full match or a '~' segment boundary immediately after the pattern. return value.Length == Pattern.Length || Pattern.EndsWith('~') || value[Pattern.Length] == '~'; } -} \ No newline at end of file +} diff --git a/Gts.Store/GtsSchemaCompatibilityService.cs b/Gts.Store/GtsSchemaCompatibilityService.cs index c693319..8727048 100644 --- a/Gts.Store/GtsSchemaCompatibilityService.cs +++ b/Gts.Store/GtsSchemaCompatibilityService.cs @@ -17,4 +17,4 @@ public static (bool Backward, IReadOnlyList BackwardErrors, bool Forward var (forward, forwardErrors) = GtsJsonSchemaEvolutionCompatibility.CheckForward(oldSchema, newSchema); return (backward, backwardErrors, forward, forwardErrors); } -} \ No newline at end of file +} diff --git a/Gts.Store/GtsSchemaDependencyGraph.cs b/Gts.Store/GtsSchemaDependencyGraph.cs index 480c7f5..dd59bc8 100644 --- a/Gts.Store/GtsSchemaDependencyGraph.cs +++ b/Gts.Store/GtsSchemaDependencyGraph.cs @@ -134,4 +134,4 @@ private static JsonObject Resolve(JsonObject schema, Func lo }; return clone; } -} \ No newline at end of file +} diff --git a/Gts.Store/GtsSchemaValidationService.cs b/Gts.Store/GtsSchemaValidationService.cs index 818c81e..25a3133 100644 --- a/Gts.Store/GtsSchemaValidationService.cs +++ b/Gts.Store/GtsSchemaValidationService.cs @@ -105,4 +105,4 @@ internal async ValueTask ValidateAsync(GtsId schemaId } private static GtsSchemaValidationResult Failure(string? id, GtsValidationFailure reason) => new() { Ok = false, SchemaId = id, FailureReason = reason }; -} \ No newline at end of file +} diff --git a/Gts.Store/GtsTraitComposer.cs b/Gts.Store/GtsTraitComposer.cs index 07f311c..e117a47 100644 --- a/Gts.Store/GtsTraitComposer.cs +++ b/Gts.Store/GtsTraitComposer.cs @@ -70,4 +70,4 @@ private static void CollectValues(JsonObject schema, JsonObject values) CollectValues(branch, values); } } -} \ No newline at end of file +} diff --git a/Gts.Store/Validation/GtsFormatRegistry.cs b/Gts.Store/Validation/GtsFormatRegistry.cs index 61ec856..cc390d4 100644 --- a/Gts.Store/Validation/GtsFormatRegistry.cs +++ b/Gts.Store/Validation/GtsFormatRegistry.cs @@ -73,4 +73,4 @@ public override bool Validate(JsonElement value, out string? errorMessage) return valid; } } -} \ No newline at end of file +} diff --git a/Gts.Store/Validation/GtsJson.cs b/Gts.Store/Validation/GtsJson.cs index e8b8a2b..a93ea28 100644 --- a/Gts.Store/Validation/GtsJson.cs +++ b/Gts.Store/Validation/GtsJson.cs @@ -8,4 +8,4 @@ internal static class GtsJson internal static JsonElement ToElement(JsonNode? node) => JsonSerializer.SerializeToElement(node); internal static JsonObject CloneObject(JsonObject source) => (JsonObject)source.DeepClone(); -} \ No newline at end of file +} diff --git a/Gts.Store/Validation/GtsJsonPointer.cs b/Gts.Store/Validation/GtsJsonPointer.cs index cfebb13..8468413 100644 --- a/Gts.Store/Validation/GtsJsonPointer.cs +++ b/Gts.Store/Validation/GtsJsonPointer.cs @@ -17,4 +17,4 @@ internal static bool TryEvaluate(JsonNode? root, string reference, out JsonNode? var pointerText = reference.StartsWith('#') ? reference[1..] : reference; return JsonPointer.TryParse(pointerText, out var pointer) && pointer.TryEvaluate(root, out result); } -} \ No newline at end of file +} diff --git a/Gts.Store/Validation/GtsJsonSchemaEngine.cs b/Gts.Store/Validation/GtsJsonSchemaEngine.cs index fa60cd7..c75d305 100644 --- a/Gts.Store/Validation/GtsJsonSchemaEngine.cs +++ b/Gts.Store/Validation/GtsJsonSchemaEngine.cs @@ -199,4 +199,4 @@ private static void Walk(EvaluationResults node, List errors) foreach (var detail in node.Details ?? []) Walk(detail, errors); } -} \ No newline at end of file +} diff --git a/Gts.Store/Validation/GtsJsonSchemaEvaluator.cs b/Gts.Store/Validation/GtsJsonSchemaEvaluator.cs index 40fd1fb..497bbf0 100644 --- a/Gts.Store/Validation/GtsJsonSchemaEvaluator.cs +++ b/Gts.Store/Validation/GtsJsonSchemaEvaluator.cs @@ -20,4 +20,4 @@ internal static void ValidateSchema(JsonObject normalizedSchemaDocument) => Engine.ValidateSchema(normalizedSchemaDocument); internal static IReadOnlyList FlattenErrors(EvaluationResults results) => Engine.FlattenErrors(results); -} \ No newline at end of file +} diff --git a/Gts.Store/Validation/IGtsJsonSchemaEngine.cs b/Gts.Store/Validation/IGtsJsonSchemaEngine.cs index 908e888..2eb2f62 100644 --- a/Gts.Store/Validation/IGtsJsonSchemaEngine.cs +++ b/Gts.Store/Validation/IGtsJsonSchemaEngine.cs @@ -12,4 +12,4 @@ internal interface IGtsJsonSchemaEngine void ValidateSchema(JsonObject normalizedSchemaDocument); IReadOnlyList FlattenErrors(EvaluationResults results); -} \ No newline at end of file +} diff --git a/Gts.Tests/Extraction/ExtractBasicTests.cs b/Gts.Tests/Extraction/ExtractBasicTests.cs index f6f8172..9ffc00c 100644 --- a/Gts.Tests/Extraction/ExtractBasicTests.cs +++ b/Gts.Tests/Extraction/ExtractBasicTests.cs @@ -120,4 +120,4 @@ public void ExtractingIdReturnsNullWhenValidIdDoesNotExist() Assert.Null(result.Id); Assert.Null(result.SelectedEntityField); } -} \ No newline at end of file +} diff --git a/Gts.Tests/Extraction/ExtractEntityTests.cs b/Gts.Tests/Extraction/ExtractEntityTests.cs index 9970fb5..b91594d 100644 --- a/Gts.Tests/Extraction/ExtractEntityTests.cs +++ b/Gts.Tests/Extraction/ExtractEntityTests.cs @@ -1,4 +1,4 @@ -using System.Text.Json.Nodes; +using System.Text.Json.Nodes; using Gts.Extraction; namespace Gts.Tests.Extraction; @@ -85,4 +85,4 @@ public void ExtractingPopulatesRefsFromDoubleDollarRefInAllOf() Assert.Contains(entity.GtsRefs, r => r.Id == "gts.x.test6.events.type.v1~"); } -} \ No newline at end of file +} diff --git a/Gts.Tests/Extraction/ExtractSchemaTests.cs b/Gts.Tests/Extraction/ExtractSchemaTests.cs index 8918b16..7f02859 100644 --- a/Gts.Tests/Extraction/ExtractSchemaTests.cs +++ b/Gts.Tests/Extraction/ExtractSchemaTests.cs @@ -1,4 +1,4 @@ -using System.Text.Json.Nodes; +using System.Text.Json.Nodes; using Gts.Extraction; namespace Gts.Tests.Extraction; diff --git a/Gts.Tests/GtsIdTests.cs b/Gts.Tests/GtsIdTests.cs index 3e9bf8e..54b1472 100644 --- a/Gts.Tests/GtsIdTests.cs +++ b/Gts.Tests/GtsIdTests.cs @@ -129,4 +129,4 @@ public void EqualsIsTheSameAsEqualsForString() Assert.Equal(id1, id12); Assert.NotEqual(id1, id2); } -} \ No newline at end of file +} diff --git a/Gts.Tests/Parsing/IdentifierParserTests.cs b/Gts.Tests/Parsing/IdentifierParserTests.cs index 90c1424..6873f74 100644 --- a/Gts.Tests/Parsing/IdentifierParserTests.cs +++ b/Gts.Tests/Parsing/IdentifierParserTests.cs @@ -1,4 +1,4 @@ -using Gts.Parsing; +using Gts.Parsing; namespace Gts.Tests.Parsing; diff --git a/Gts.Tests/Parsing/InstanceParserTests.cs b/Gts.Tests/Parsing/InstanceParserTests.cs index 99374f8..f3fd30d 100644 --- a/Gts.Tests/Parsing/InstanceParserTests.cs +++ b/Gts.Tests/Parsing/InstanceParserTests.cs @@ -1,4 +1,4 @@ -using Gts.Parsing; +using Gts.Parsing; using Pidgin; namespace Gts.Tests.Parsing; @@ -30,4 +30,4 @@ public void InstanceParsesTripleSegment() var segments = id.ToArray(); Assert.Equal(3, segments.Length); } -} \ No newline at end of file +} diff --git a/Gts.Tests/Parsing/PatternParserTests.cs b/Gts.Tests/Parsing/PatternParserTests.cs index e1c79f4..97faf8e 100644 --- a/Gts.Tests/Parsing/PatternParserTests.cs +++ b/Gts.Tests/Parsing/PatternParserTests.cs @@ -1,4 +1,4 @@ -using Gts.Parsing; +using Gts.Parsing; using Pidgin; namespace Gts.Tests.Parsing; @@ -148,4 +148,4 @@ public void GtsPatternParsesMultipleWithTildeAtTheEnd() var segments = id.ToArray(); Assert.Single(segments); } -} \ No newline at end of file +} diff --git a/Gts.Tests/Parsing/SectionParserTests.cs b/Gts.Tests/Parsing/SectionParserTests.cs index f3ecc7b..306674f 100644 --- a/Gts.Tests/Parsing/SectionParserTests.cs +++ b/Gts.Tests/Parsing/SectionParserTests.cs @@ -1,4 +1,4 @@ -using Gts.Parsing; +using Gts.Parsing; using Pidgin; namespace Gts.Tests.Parsing; @@ -18,4 +18,4 @@ public void GtsDoesNotParseUppercaseLiteral() Assert.Throws>( () => Parsers.GtsPrefix.ParseOrThrow("GTS")); } -} \ No newline at end of file +} diff --git a/Gts.Tests/Parsing/SegmentParserTests.cs b/Gts.Tests/Parsing/SegmentParserTests.cs index 4bc953f..9bc77b1 100644 --- a/Gts.Tests/Parsing/SegmentParserTests.cs +++ b/Gts.Tests/Parsing/SegmentParserTests.cs @@ -1,4 +1,4 @@ -using Gts.Parsing; +using Gts.Parsing; using Pidgin; namespace Gts.Tests.Parsing; diff --git a/Gts.Tests/Parsing/TypeParserTests.cs b/Gts.Tests/Parsing/TypeParserTests.cs index 254527d..6978626 100644 --- a/Gts.Tests/Parsing/TypeParserTests.cs +++ b/Gts.Tests/Parsing/TypeParserTests.cs @@ -1,4 +1,4 @@ -using Gts.Parsing; +using Gts.Parsing; using Pidgin; namespace Gts.Tests.Parsing; @@ -30,4 +30,4 @@ public void TypeParsesDoubleSegment() var segments = id.ToArray(); Assert.Equal(2, segments.Length); } -} \ No newline at end of file +} diff --git a/Gts.Tests/Parsing/VersionParserTests.cs b/Gts.Tests/Parsing/VersionParserTests.cs index e040ef8..38e3781 100644 --- a/Gts.Tests/Parsing/VersionParserTests.cs +++ b/Gts.Tests/Parsing/VersionParserTests.cs @@ -46,4 +46,4 @@ public void VersionFullParsesPartialVersionString() Assert.Equal(123, major); Assert.Null(minor); } -} \ No newline at end of file +} diff --git a/Gts.Tests/Validation/JsonInfrastructureTests.cs b/Gts.Tests/Validation/JsonInfrastructureTests.cs index ddc59a7..0a86c75 100644 --- a/Gts.Tests/Validation/JsonInfrastructureTests.cs +++ b/Gts.Tests/Validation/JsonInfrastructureTests.cs @@ -152,4 +152,4 @@ public void Shared_id_parser_rejects_negative_versions(string id) { Assert.False(GtsId.TryParse(id, out _)); } -} \ No newline at end of file +} diff --git a/Gts/Parsing/GtsIdParser.cs b/Gts/Parsing/GtsIdParser.cs index 61c633c..9c35182 100644 --- a/Gts/Parsing/GtsIdParser.cs +++ b/Gts/Parsing/GtsIdParser.cs @@ -63,4 +63,4 @@ private static bool HasCanonicalVersion(string source, Parsers.VersionInfo? vers return false; return tokens.Length == 5 || tokens[5] == version.Value.Minor?.ToString(); } -} \ No newline at end of file +} diff --git a/Gts/Parsing/ParseException.cs b/Gts/Parsing/ParseException.cs index 05e5986..670af98 100644 --- a/Gts/Parsing/ParseException.cs +++ b/Gts/Parsing/ParseException.cs @@ -11,4 +11,4 @@ public ParseException(ParseResult parseResult) { ParseResult = parseResult; } -} \ No newline at end of file +} diff --git a/Gts/Properties/AssemblyInfo.cs b/Gts/Properties/AssemblyInfo.cs index 4aac24a..a89e18b 100644 --- a/Gts/Properties/AssemblyInfo.cs +++ b/Gts/Properties/AssemblyInfo.cs @@ -1,3 +1,3 @@ -using System.Runtime.CompilerServices; +using System.Runtime.CompilerServices; [assembly: InternalsVisibleTo("Gts.Tests")] From acb242d01be020254364118917e4c8685daddf49 Mon Sep 17 00:00:00 2001 From: Artifizer Date: Thu, 1 Oct 2026 01:42:49 +0300 Subject: [PATCH 3/3] ci: harden workflow per CodeRabbit review Address the two CodeRabbit security findings on the CI workflow: - Pin third-party actions (actions/checkout, actions/setup-dotnet, codecov/codecov-action) to full 40-char commit SHAs with the version retained in a trailing comment (CWE-829), matching gts-rust. - Set persist-credentials: false on all checkout steps so the GITHUB_TOKEN is not persisted into .git/config for subsequent steps (artipacked). Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 751024a..5d6dfdf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -43,16 +43,17 @@ jobs: git config --global core.eol lf - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0 with: clean: 'true' + persist-credentials: false # Install the .NET 8 SDK for the net8.0 target. global.json intentionally # stays permissive ("8.0.0" + rollForward=latestMajor, i.e. "min .NET 8, # use whatever newer SDK is present"); that pin is not a downloadable # build, so we install an 8.0 SDK explicitly rather than via global.json. - name: Set up .NET - uses: actions/setup-dotnet@v4 + uses: actions/setup-dotnet@67a3573c9a986a3f9c594539f4ab511d57bb3ce9 # v4.3.1 with: dotnet-version: '8.0.x' @@ -83,10 +84,12 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0 + with: + persist-credentials: false - name: Set up .NET - uses: actions/setup-dotnet@v4 + uses: actions/setup-dotnet@67a3573c9a986a3f9c594539f4ab511d57bb3ce9 # v4.3.1 with: dotnet-version: '8.0.x' @@ -103,10 +106,12 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0 + with: + persist-credentials: false - name: Set up .NET - uses: actions/setup-dotnet@v4 + uses: actions/setup-dotnet@67a3573c9a986a3f9c594539f4ab511d57bb3ce9 # v4.3.1 with: dotnet-version: '8.0.x' @@ -116,7 +121,7 @@ jobs: # Upload to Codecov; do not fail CI if Codecov is down/misconfigured. - name: Upload to Codecov - uses: codecov/codecov-action@v4 + uses: codecov/codecov-action@0f8570b1a125f4937846a11fcfa3bcd548bd8c97 # v4.6.0 with: files: '**/coverage.cobertura.xml' fail_ci_if_error: false @@ -127,10 +132,12 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0 + with: + persist-credentials: false - name: Set up .NET - uses: actions/setup-dotnet@v4 + uses: actions/setup-dotnet@67a3573c9a986a3f9c594539f4ab511d57bb3ce9 # v4.3.1 with: dotnet-version: '8.0.x'