diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml
index 0003b3d..55634bb 100644
--- a/.github/workflows/build-test.yml
+++ b/.github/workflows/build-test.yml
@@ -20,7 +20,11 @@ jobs:
name: Build and test
permissions:
contents: read
- runs-on: ubuntu-latest
+ strategy:
+ fail-fast: false # don't fail if one of the matrix jobs fails. Example: try to run the windows matrix even if the ubuntu matrix fails.
+ matrix:
+ os: [ubuntu-latest, windows-latest]
+ runs-on: ${{ matrix.os }}
env:
SLN_DIR: GitHubIssueFormsParser
SLN_FILENAME: GitHubIssueFormsParser.sln
@@ -93,7 +97,7 @@ jobs:
}
- name: Set run even if tests fail condition
id: even-if-tests-fail
- if: always()
+ if: matrix.os == 'ubuntu-latest' && always()
run: |
# Some of the steps below provide feedback on the test run and I want to run them even if
# some of the previous steps failed. For that I need:
@@ -109,7 +113,7 @@ jobs:
Write-Output "condition is set to $condition"
- name: Generate code coverage report
id: code-coverage-report-generator
- if: (steps.dotnet-test.conclusion == 'success' || steps.dotnet-test.conclusion == 'failure') && always()
+ if: matrix.os == 'ubuntu-latest' && steps.even-if-tests-fail.outputs.condition == 'true' && always()
run: |
$testCoverageReportDir = $(Join-Path -Path ${{ steps.dotnet-test.outputs.test-coverage-dir }} -ChildPath "report")
Write-Output "test-coverage-report-dir=$testCoverageReportDir" >> $env:GITHUB_OUTPUT
@@ -118,24 +122,26 @@ jobs:
"-targetdir:$testCoverageReportDir" `
-reportTypes:htmlInline
- name: Upload code coverage report to artifacts
- if: steps.even-if-tests-fail.outputs.condition == 'true' && always()
+ if: matrix.os == 'ubuntu-latest' && steps.even-if-tests-fail.outputs.condition == 'true' && always()
uses: actions/upload-artifact@v3
with:
name: ${{ env.CODE_COVERAGE_ARTIFACT_NAME }}
path: ${{ steps.code-coverage-report-generator.outputs.test-coverage-report-dir }}
- name: Upload test results to artifacts
- if: steps.even-if-tests-fail.outputs.condition == 'true' && always()
+ if: matrix.os == 'ubuntu-latest' && steps.even-if-tests-fail.outputs.condition == 'true' && always()
uses: actions/upload-artifact@v3
with:
name: ${{ env.TEST_RESULTS_ARTIFACT_NAME }}
path: ${{ steps.dotnet-test.outputs.test-results-dir }}
- name: Upload test coverage to Codecov
+ if: matrix.os == 'ubuntu-latest'
uses: codecov/codecov-action@v3
with:
token: ${{ secrets.CODECOV_TOKEN }} # even though it's not required for public repos it helps with intermittent failures caused by https://community.codecov.com/t/upload-issues-unable-to-locate-build-via-github-actions-api/3954, https://github.com/codecov/codecov-action/issues/598
files: ${{ steps.dotnet-test.outputs.test-coverage-file }}
fail_ci_if_error: true
- name: Log Codecov info
+ if: matrix.os == 'ubuntu-latest'
run: |
$codeCoveUrl = "https://app.codecov.io/gh/${{ github.repository }}/"
Write-Output "::notice title=Code coverage (${{ runner.os }})::Code coverage has been uploaded to Codecov at $codeCoveUrl. You can download the code coverage report from the workflow artifact named: ${{ env.CODE_COVERAGE_ARTIFACT_NAME }}."
diff --git a/Dockerfile b/Dockerfile
index c770885..a1b1bfb 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,8 +1,10 @@
-#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging.
+# See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging.
+# See https://hub.docker.com/_/microsoft-dotnet-runtime/ for list of tags for dotnet runtime
+# See https://hub.docker.com/_/microsoft-dotnet-sdk for list of tags for dotnet sdk
-FROM mcr.microsoft.com/dotnet/runtime:7.0-alpine AS base
+FROM mcr.microsoft.com/dotnet/runtime:8.0-alpine AS base
# install powershell as per https://docs.microsoft.com/en-us/powershell/scripting/install/install-alpine
-ARG PWSH_VERSION=7.3.6
+ARG PWSH_VERSION=7.4.0
RUN apk add --no-cache \
ca-certificates \
less \
@@ -18,14 +20,14 @@ RUN apk add --no-cache \
icu-libs \
curl
RUN apk -X https://dl-cdn.alpinelinux.org/alpine/edge/main add --no-cache lttng-ust
-RUN curl -L https://github.com/PowerShell/PowerShell/releases/download/v${PWSH_VERSION}/powershell-${PWSH_VERSION}-linux-alpine-x64.tar.gz -o /tmp/powershell.tar.gz
+RUN curl -L https://github.com/PowerShell/PowerShell/releases/download/v${PWSH_VERSION}/powershell-${PWSH_VERSION}-linux-musl-x64.tar.gz -o /tmp/powershell.tar.gz
RUN mkdir -p /opt/microsoft/powershell/7
RUN tar zxf /tmp/powershell.tar.gz -C /opt/microsoft/powershell/7
RUN chmod +x /opt/microsoft/powershell/7/pwsh
RUN ln -s /opt/microsoft/powershell/7/pwsh /usr/bin/pwsh
# end of install powershell
-FROM mcr.microsoft.com/dotnet/sdk:7.0-alpine AS build
+FROM mcr.microsoft.com/dotnet/sdk:8.0-alpine AS build
WORKDIR /github-issue-forms-parser
COPY ["GitHubIssueFormsParser/NuGet.Config", "GitHubIssueFormsParser/"]
COPY ["GitHubIssueFormsParser/src/GitHubIssuesParserCli/GitHubIssuesParserCli.csproj", "GitHubIssueFormsParser/src/GitHubIssuesParserCli/"]
diff --git a/GitHubIssueFormsParser/global.json b/GitHubIssueFormsParser/global.json
index 90e17e6..1a11256 100644
--- a/GitHubIssueFormsParser/global.json
+++ b/GitHubIssueFormsParser/global.json
@@ -1,6 +1,6 @@
{
"sdk": {
- "version": "7.0.x",
+ "version": "8.0.x",
"rollForward": "disable",
"allowPrerelease": false
}
diff --git a/GitHubIssueFormsParser/src/GitHubIssuesParserCli/GitHubIssuesParserCli.csproj b/GitHubIssueFormsParser/src/GitHubIssuesParserCli/GitHubIssuesParserCli.csproj
index 3eddfe9..abd2785 100644
--- a/GitHubIssueFormsParser/src/GitHubIssuesParserCli/GitHubIssuesParserCli.csproj
+++ b/GitHubIssueFormsParser/src/GitHubIssuesParserCli/GitHubIssuesParserCli.csproj
@@ -2,7 +2,7 @@
Exe
- net7.0
+ net8.0
diff --git a/GitHubIssueFormsParser/src/GitHubIssuesParserCli/IssueFormBodies/IssueFormBody.cs b/GitHubIssueFormsParser/src/GitHubIssuesParserCli/IssueFormBodies/IssueFormBody.cs
index 3c886a6..09ad4e0 100644
--- a/GitHubIssueFormsParser/src/GitHubIssuesParserCli/IssueFormBodies/IssueFormBody.cs
+++ b/GitHubIssueFormsParser/src/GitHubIssuesParserCli/IssueFormBodies/IssueFormBody.cs
@@ -2,6 +2,12 @@ namespace GitHubIssuesParserCli.IssueFormBodies;
internal sealed class IssueFormBody
{
+ private static readonly JsonSerializerOptions _serializeOptions = new JsonSerializerOptions
+ {
+ WriteIndented = false,
+ Converters = { new IssueFormBodyJsonConverter() },
+ };
+
public IssueFormBody(List items)
{
Items = items.NotNull();
@@ -11,15 +17,7 @@ public IssueFormBody(List items)
public string ToJson()
{
- var serializeOptions = new JsonSerializerOptions
- {
- WriteIndented = false,
- Converters =
- {
- new IssueFormBodyJsonConverter(),
- },
- };
- return JsonSerializer.Serialize(this, serializeOptions);
+ return JsonSerializer.Serialize(this, _serializeOptions);
}
public void WriteAsJson(Utf8JsonWriter writer)
diff --git a/GitHubIssueFormsParser/tests/GitHubIssuesParserCli.Tests/Auxiliary/LineEndings.cs b/GitHubIssueFormsParser/tests/GitHubIssuesParserCli.Tests/Auxiliary/LineEndings.cs
index 37b5fce..d7c0166 100644
--- a/GitHubIssueFormsParser/tests/GitHubIssuesParserCli.Tests/Auxiliary/LineEndings.cs
+++ b/GitHubIssueFormsParser/tests/GitHubIssuesParserCli.Tests/Auxiliary/LineEndings.cs
@@ -1,7 +1,17 @@
namespace GitHubIssuesParserCli.Tests.Auxiliary;
-internal static class LineEndings
+internal static partial class LineEndings
{
+ // matchTimeoutMilliseconds used to prevent denial of service attacks. See MA0009 https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0009.md
+ // Adding 5 secs which for this scenario means: a random high enough value. It will probably work with much lower values but
+ // for this code this doesn't matter much as long as it's compliant with MA0009.
+ [GeneratedRegex(@"\r\n", RegexOptions.IgnoreCase, matchTimeoutMilliseconds: 5000)]
+ private static partial Regex WindowsNewLinesRegex();
+
+ // This pattern uses a negative lookbehind to ensure that the LF character is not preceded by a CR character.
+ [GeneratedRegex(@"(?
/// Updates a string so that the line endings match the OS expected line endings.
///
@@ -9,24 +19,18 @@ internal static class LineEndings
/// A string containing line endings matching the OS expected line endings.
public static string NormalizeLineEndings(this string original)
{
- if (Environment.OSVersion.Platform == PlatformID.Win32NT && original.Contains(CR + LF, StringComparison.Ordinal))
- {
- // if it's a Windows OS and contains Windows line endings then do nothing
- return original;
- }
-
- if (Environment.OSVersion.Platform == PlatformID.Win32NT && original.Contains(LF, StringComparison.Ordinal))
+ if (Environment.OSVersion.Platform == PlatformID.Win32NT && LinuxNewLinesRegex().IsMatch(original))
{
// if it's a Windows OS and doesn't contain Windows line endings then replace
// new lines with Windows line endings
- return original.Replace(LF, Environment.NewLine, StringComparison.Ordinal);
+ return LinuxNewLinesRegex().Replace(original, CR + LF);
}
- if (Environment.OSVersion.Platform == PlatformID.Unix && original.Contains(CR + LF, StringComparison.Ordinal))
+ if (Environment.OSVersion.Platform == PlatformID.Unix && WindowsNewLinesRegex().IsMatch(original))
{
// if it's a Linux OS and contains Windows line endings then replace
// new lines with Linux line endings
- return original.Replace(CR + LF, Environment.NewLine, StringComparison.Ordinal);
+ return WindowsNewLinesRegex().Replace(original, LF);
}
return original;
diff --git a/GitHubIssueFormsParser/tests/GitHubIssuesParserCli.Tests/GitHubIssuesParserCli.Tests.csproj b/GitHubIssueFormsParser/tests/GitHubIssuesParserCli.Tests/GitHubIssuesParserCli.Tests.csproj
index 989f272..1e94cb9 100644
--- a/GitHubIssueFormsParser/tests/GitHubIssuesParserCli.Tests/GitHubIssuesParserCli.Tests.csproj
+++ b/GitHubIssueFormsParser/tests/GitHubIssuesParserCli.Tests/GitHubIssuesParserCli.Tests.csproj
@@ -1,7 +1,7 @@
- net7.0
+ net8.0
false
true
diff --git a/GitHubIssueFormsParser/tests/GitHubIssuesParserCli.Tests/Usings.cs b/GitHubIssueFormsParser/tests/GitHubIssuesParserCli.Tests/Usings.cs
index 7c55555..6de08cb 100644
--- a/GitHubIssueFormsParser/tests/GitHubIssuesParserCli.Tests/Usings.cs
+++ b/GitHubIssueFormsParser/tests/GitHubIssuesParserCli.Tests/Usings.cs
@@ -1,5 +1,6 @@
global using System.Text.Json;
global using System.Text.Json.Serialization;
+global using System.Text.RegularExpressions;
global using CliFx.Exceptions;
global using CliFx.Extensibility;
global using CliFx.Infrastructure;