Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
279 changes: 279 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,279 @@
name: CI

on:
push:
branches: [master]
pull_request:
branches: [master]

env:
MAJOR_MINOR: '1.15'

permissions:
contents: write
pull-requests: write
security-events: write

jobs:
build:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: |
8.0.x
9.0.x
10.0.x

- name: Restore
run: dotnet restore

- name: Build
run: dotnet build -c Release --no-restore 2>&1 | tee build.log

- name: Check warnings
run: |
WARNING_COUNT=$(grep -c " warning " build.log || true)
echo "Build warnings: $WARNING_COUNT"
if [ "$WARNING_COUNT" -gt 15 ]; then
echo "::error::Build has $WARNING_COUNT warnings (threshold: 15)"
exit 1
fi

- name: Test with coverage
run: dotnet test -c Release --no-build --verbosity normal --collect:"XPlat Code Coverage" --results-directory ./coverage

- name: Upload coverage to Codecov
uses: codecov/codecov-action@v5
with:
directory: ./coverage
fail_ci_if_error: false
token: ${{ secrets.CODECOV_TOKEN }}

- name: Compute version
id: version
run: |
LATEST_TAG=$(git tag -l "${MAJOR_MINOR}.*" --sort=-v:refname \
| grep -E "^${MAJOR_MINOR}\.[0-9]+$" \
| head -1)

if [ -z "$LATEST_TAG" ]; then
PATCH=0
else
PATCH=$(echo "$LATEST_TAG" | sed "s/${MAJOR_MINOR}\.\([0-9]*\)/\1/")
PATCH=$((PATCH + 1))
fi

VERSION="${MAJOR_MINOR}.${PATCH}"
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
echo "previous_tag=$LATEST_TAG" >> "$GITHUB_OUTPUT"
echo "Computed version: $VERSION (previous: $LATEST_TAG)"

- name: Compute pre-release version
id: preversion
if: github.ref != 'refs/heads/master'
run: |
VERSION="${{ steps.version.outputs.version }}"
PRE_BASE="${VERSION}-pre"

LATEST_PRE=$(git tag -l "${PRE_BASE}.*" --sort=-v:refname | head -1)

if [ -z "$LATEST_PRE" ]; then
COUNTER=1
else
COUNTER=$(echo "$LATEST_PRE" | sed "s/.*-pre\.\([0-9]*\)/\1/")
COUNTER=$((COUNTER + 1))
fi

PRE_VERSION="${PRE_BASE}.${COUNTER}"
echo "version=$PRE_VERSION" >> "$GITHUB_OUTPUT"
echo "Computed pre-release version: $PRE_VERSION"

- name: Pack (stable — push to master)
if: github.ref == 'refs/heads/master' && github.event_name == 'push'
run: |
dotnet pack Tharga.Toolkit.Standard/Tharga.Toolkit.Standard.csproj -c Release --no-build -o ./artifacts -p:PackageVersion=${{ steps.version.outputs.version }}
dotnet pack Tharga.Toolkit/Tharga.Toolkit.csproj -c Release --no-build -o ./artifacts -p:PackageVersion=${{ steps.version.outputs.version }}

- name: Pack (pre-release — pull request)
if: github.event_name == 'pull_request'
run: |
dotnet pack Tharga.Toolkit.Standard/Tharga.Toolkit.Standard.csproj -c Release --no-build -o ./artifacts -p:PackageVersion=${{ steps.preversion.outputs.version }}
dotnet pack Tharga.Toolkit/Tharga.Toolkit.csproj -c Release --no-build -o ./artifacts -p:PackageVersion=${{ steps.preversion.outputs.version }}

- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: nuget-packages
path: ./artifacts/

security:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: csharp

- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: |
8.0.x
9.0.x
10.0.x

- name: Build for CodeQL
run: dotnet build -c Release

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3

release:
needs: [build, security]
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/master' && github.event_name == 'push'
environment: release

steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: 10.0.x

- name: Download artifacts
uses: actions/download-artifact@v4
with:
name: nuget-packages
path: ./artifacts/

- name: Compute version
id: version
run: |
LATEST_TAG=$(git tag -l "${MAJOR_MINOR}.*" --sort=-v:refname \
| grep -E "^${MAJOR_MINOR}\.[0-9]+$" \
| head -1)

if [ -z "$LATEST_TAG" ]; then
PATCH=0
else
PATCH=$(echo "$LATEST_TAG" | sed "s/${MAJOR_MINOR}\.\([0-9]*\)/\1/")
PATCH=$((PATCH + 1))
fi

VERSION="${MAJOR_MINOR}.${PATCH}"
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
echo "previous_tag=$LATEST_TAG" >> "$GITHUB_OUTPUT"

- name: Push to NuGet
run: |
for pkg in ./artifacts/*.nupkg; do
echo "Pushing $pkg..."
dotnet nuget push "$pkg" --api-key ${{ secrets.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json --skip-duplicate || true
done

- name: Create GitHub Release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
NOTES_FLAG=""
if [ -n "${{ steps.version.outputs.previous_tag }}" ]; then
NOTES_FLAG="--notes-start-tag ${{ steps.version.outputs.previous_tag }}"
fi
gh release create "${{ steps.version.outputs.version }}" \
--title "v${{ steps.version.outputs.version }}" \
--generate-notes \
$NOTES_FLAG \
./artifacts/*.nupkg

- name: Comment released version on merged PR
if: always()
continue-on-error: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
PR_NUMBER=$(echo "${{ github.event.head_commit.message }}" | grep -oP 'Merge pull request #\K\d+' | head -1)
if [ -n "$PR_NUMBER" ]; then
gh pr comment "$PR_NUMBER" --body "Released as **v${{ steps.version.outputs.version }}** — https://github.com/${{ github.repository }}/releases/tag/${{ steps.version.outputs.version }}"
else
echo "No PR number found in commit message — skipping PR comment."
fi

prerelease:
needs: [build, security]
runs-on: ubuntu-latest
if: github.ref != 'refs/heads/master' && github.event_name == 'pull_request'
environment: prerelease

steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: 10.0.x

- name: Download artifacts
uses: actions/download-artifact@v4
with:
name: nuget-packages
path: ./artifacts/

- name: Compute pre-release version
id: version
run: |
LATEST_TAG=$(git tag -l "${MAJOR_MINOR}.*" --sort=-v:refname \
| grep -E "^${MAJOR_MINOR}\.[0-9]+$" \
| head -1)

if [ -z "$LATEST_TAG" ]; then
PATCH=0
else
PATCH=$(echo "$LATEST_TAG" | sed "s/${MAJOR_MINOR}\.\([0-9]*\)/\1/")
PATCH=$((PATCH + 1))
fi

PRE_BASE="${MAJOR_MINOR}.${PATCH}-pre"
LATEST_PRE=$(git tag -l "${PRE_BASE}.*" --sort=-v:refname | head -1)

if [ -z "$LATEST_PRE" ]; then
COUNTER=1
else
COUNTER=$(echo "$LATEST_PRE" | sed "s/.*-pre\.\([0-9]*\)/\1/")
COUNTER=$((COUNTER + 1))
fi

VERSION="${PRE_BASE}.${COUNTER}"
echo "version=$VERSION" >> "$GITHUB_OUTPUT"

- name: Push to NuGet
run: |
for pkg in ./artifacts/*.nupkg; do
echo "Pushing $pkg..."
dotnet nuget push "$pkg" --api-key ${{ secrets.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json --skip-duplicate || true
done

- name: Create GitHub Pre-release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh release create "${{ steps.version.outputs.version }}" \
--title "v${{ steps.version.outputs.version }} (pre-release)" \
--notes "Pre-release from \`${{ github.head_ref }}\` branch." \
--prerelease \
./artifacts/*.nupkg
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<IsPackable>false</IsPackable>
<NoWarn>$(NoWarn);xUnit1051</NoWarn>
</PropertyGroup>

<ItemGroup>
Expand Down
1 change: 1 addition & 0 deletions Tharga.Toolkit.Tests/DependencyTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ public void Has_no_accidental_dependency()
//act
var dps = GetDependencies()
.Where(x => x.Name != "Microsoft.Extensions.DependencyInjection.Abstractions")
.Where(x => !x.Name.StartsWith("System."))
.ToArray();

//Assert
Expand Down
1 change: 1 addition & 0 deletions Tharga.Toolkit.Tests/Tharga.Toolkit.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<IsPackable>false</IsPackable>
<NoWarn>$(NoWarn);xUnit1051</NoWarn>
</PropertyGroup>

<ItemGroup>
Expand Down
2 changes: 1 addition & 1 deletion Tharga.Toolkit/HashString.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public HashString(string value, HashFormat format)
}

/// <summary>Gets the formatted hash string.</summary>
public string Value { get; }
public new string Value { get; }

/// <summary>Gets the format used to encode this hash string.</summary>
public HashFormat Format { get; }
Expand Down
Loading