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
89 changes: 62 additions & 27 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ on:
branches: [ main, develop ]
workflow_dispatch:

permissions:
contents: write # Required for creating GitHub releases
packages: write # Required for uploading artifacts

env:
DOTNET_VERSION: '10.0.x'
NODE_VERSION: '20.x'
Expand All @@ -20,21 +24,44 @@ jobs:
runs-on: ubuntu-latest
outputs:
is_release: ${{ steps.is_release.outputs.value }}
is_stable: ${{ steps.is_release.outputs.is_stable }}
version: ${{ steps.is_release.outputs.version }}

steps:
- name: Checkout code
uses: actions/checkout@v4

# Determine if this is a release build (main branch or version tag)
# Determine if this is a release build (v* tag)
# Sets artifact retention: 90 days for releases, 7 days for dev builds
- name: Check if main or tag
- name: Check if release tag
id: is_release
run: |
if [[ "${{ github.event_name }}" == "push" && ("${{ github.ref }}" == "refs/heads/main" || "${{ github.ref }}" == refs/tags/v*) ]]; then
echo "value=true" >> $GITHUB_OUTPUT
IS_RELEASE=false
IS_STABLE_RELEASE=false
VERSION="0.0.0" # Default version for non-release builds

if [[ "${{ github.event_name }}" == "push" && "${{ github.ref }}" == refs/tags/v* ]]; then
IS_RELEASE=true
TAG_NAME="${{ github.ref_name }}"
VERSION="${TAG_NAME#v}" # Remove 'v' prefix
echo "Release build triggered by tag $TAG_NAME"

# Check if this is a stable release (no prerelease suffix like -preview, -beta, -rc)
if [[ ! "$VERSION" =~ - ]]; then
IS_STABLE_RELEASE=true
echo "This is a stable release (no prerelease suffix)"
else
echo "This is a prerelease version"
fi
fi

echo "value=$IS_RELEASE" >> $GITHUB_OUTPUT
echo "is_stable=$IS_STABLE_RELEASE" >> $GITHUB_OUTPUT
echo "version=$VERSION" >> $GITHUB_OUTPUT

if [[ "$IS_STABLE_RELEASE" == "true" ]]; then
echo "artifact_retention_days=90" >> $GITHUB_OUTPUT
else
echo "value=false" >> $GITHUB_OUTPUT
echo "artifact_retention_days=7" >> $GITHUB_OUTPUT
fi

Expand All @@ -61,7 +88,7 @@ jobs:

# Build and test
- name: Build solution
run: dotnet build ${{ env.SOLUTION_PATH }} --configuration Release --no-restore
run: dotnet build ${{ env.SOLUTION_PATH }} --configuration Release --no-restore /p:Version=${{ steps.is_release.outputs.version }} /p:TreatWarningsAsErrors=true
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TreatWarningsAsErrors added so that we fail the build in case of warnings


- name: Run tests
run: dotnet test ${{ env.SOLUTION_PATH }} --configuration Release --no-build --verbosity normal
Expand All @@ -80,7 +107,7 @@ jobs:
- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: Docentric.EInvoice.Validator.RestServer
name: Docentric.EInvoice.Validator.RestServer-${{ steps.is_release.outputs.version }}
path: ./publish/rest-server
retention-days: ${{ steps.is_release.outputs.artifact_retention_days }}

Expand All @@ -89,7 +116,7 @@ jobs:
if: steps.is_release.outputs.value == 'true'
uses: actions/upload-artifact@v4
with:
name: Docentric.EInvoice.Validator.RestServer-Self-Contained
name: Docentric.EInvoice.Validator.RestServer-Self-Contained-${{ steps.is_release.outputs.version }}
path: ./publish/rest-server-self-contained
retention-days: ${{ steps.is_release.outputs.artifact_retention_days }}

Expand All @@ -98,7 +125,7 @@ jobs:
if: steps.is_release.outputs.value == 'true'
uses: actions/upload-artifact@v4
with:
name: Source
name: Source-${{ steps.is_release.outputs.version }}
# Includes everything except build and publish folders
path: |
.
Expand All @@ -111,6 +138,24 @@ jobs:
include-hidden-files: true # needed for the hidden files and folders (starting with ., like .github, .gitignore, etc.)
retention-days: ${{ steps.is_release.outputs.artifact_retention_days }}

# Create ZIP archives for stable release builds only
- name: Create ZIP archives
if: steps.is_release.outputs.is_stable == 'true'
run: |
cd publish
zip -r Docentric.EInvoice.Validator.RestServer-${{ steps.is_release.outputs.version }}.zip rest-server
zip -r Docentric.EInvoice.Validator.RestServer-Self-Contained-${{ steps.is_release.outputs.version }}.zip rest-server-self-contained

# Create GitHub Release with ZIP artifacts (only for stable releases)
- name: Create GitHub Release
if: steps.is_release.outputs.is_stable == 'true'
uses: softprops/action-gh-release@v1
with:
files: |
publish/Docentric.EInvoice.Validator.RestServer-${{ steps.is_release.outputs.version }}.zip
publish/Docentric.EInvoice.Validator.RestServer-Self-Contained-${{ steps.is_release.outputs.version }}.zip
generate_release_notes: true
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is how the automatically created release would look like:
https://github.com/Docentric/docentric-e-invoice-validator/releases/tag/v2016.1.0


docker:
name: Build & Push Docker Image
runs-on: ubuntu-latest
Expand All @@ -124,14 +169,6 @@ jobs:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

# Read version from Directory.Build.props to tag the image
- name: Extract version from Directory.Build.props
id: version
run: |
VERSION=$(grep -oP '<Version>\K[^<]+' src/Directory.Build.props)
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "Extracted version: $VERSION"

# Login only for release builds (avoids unnecessary auth for dev builds)
- name: Log in to Docker Hub
if: needs.build.outputs.is_release == 'true'
Expand All @@ -140,22 +177,20 @@ jobs:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}

# Generate Docker tags based on version and branch
# Generate Docker tags for release builds (v* tags)
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.DOCKER_IMAGE }}
tags: |
# Tag with version from Directory.Build.props (e.g., "2026.1.0")
type=raw,value=${{ steps.version.outputs.version }}
# Tag with branch name (e.g., "main", "develop")
type=ref,event=branch
# Tag "latest" only for main branch
type=raw,value=latest,enable={{is_default_branch}}

# Build image for all branches, but only push to Docker Hub for main/tags
- name: Build Docker image
# Tag with version from Git tag (e.g., "v1.2.3" -> "1.2.3", "v1.2.3-preview.0" -> "1.2.3-preview.0")
type=semver,pattern={{version}}
# Tag "latest" only for stable releases (no prerelease suffix)
type=raw,value=latest,enable=${{ needs.build.outputs.is_stable == 'true' }}
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The latest tag will be set only for the "stable" releases. We don't want a preview version to be marked as latest.


# Build and push Docker image only for v* tags
- name: Build and push Docker image
uses: docker/build-push-action@v6
with:
context: ./src
Expand Down
14 changes: 4 additions & 10 deletions src/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,12 @@
<Company>Docentric</Company>
<Copyright>© 2015–2026 Docentric d.o.o. All rights reserved.</Copyright>

<!-- NuGet package version -->
<!-- The value here is also driving the Docker image version in the build pipelines -->
<Version>2016.1.0</Version>

<!-- Runtime binding identity (stable, rarely changed - only change the major and minor version) -->
<AssemblyVersion>$(Version).0</AssemblyVersion>

<!-- File version: updated per release / build -->
<FileVersion>$(Version).0</FileVersion>
<!-- NuGet package version (supports semantic versioning with prerelease tags) -->
<!-- Default placeholder version. For release builds, this is overridden by the Git tag version passed via /p:Version parameter in the build pipeline -->
<Version>0.0.0</Version>

<!-- Informational version: for About, logs, diagnostics -->
<Revision>$([System.DateTime]::UtcNow.ToString('yyyyMMddHHmmss'))</Revision>
<InformationalVersion>$(Version).$(Revision)</InformationalVersion>
<InformationalVersion>$(Version)+$(Revision)</InformationalVersion>
</PropertyGroup>
</Project>
1 change: 1 addition & 0 deletions src/Server/Endpoints/PdfEndpoints.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ public static IEndpointRouteBuilder MapPdfEndpoints(this IEndpointRouteBuilder e
/// <param name="mustangCliService">The Mustang CLI service for executing commands.</param>
/// <param name="uploadedFile">The file upload request with the PDF file to validate.</param>
/// <param name="loggerFactory">The logger factory for creating loggers.</param>
/// <param name="cancellationToken">The cancellation token for managing task cancellation.</param>
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

param name was missing which caused a build warning.

/// <returns>
/// An <see cref="IResult"/> containing a <see cref="PdfFileValidationResponse"/> with validation results,
/// including whether the file is valid, signature status, and a detailed validation report.
Expand Down
Loading