diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7c053ea..3233e6c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -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' @@ -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 @@ -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 - name: Run tests run: dotnet test ${{ env.SOLUTION_PATH }} --configuration Release --no-build --verbosity normal @@ -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 }} @@ -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 }} @@ -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: | . @@ -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 + docker: name: Build & Push Docker Image runs-on: ubuntu-latest @@ -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 '\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' @@ -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' }} + + # Build and push Docker image only for v* tags + - name: Build and push Docker image uses: docker/build-push-action@v6 with: context: ./src diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 93e3230..eee326f 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -8,18 +8,12 @@ Docentric © 2015–2026 Docentric d.o.o. All rights reserved. - - - 2016.1.0 - - - $(Version).0 - - - $(Version).0 + + + 0.0.0 $([System.DateTime]::UtcNow.ToString('yyyyMMddHHmmss')) - $(Version).$(Revision) + $(Version)+$(Revision) diff --git a/src/Server/Endpoints/PdfEndpoints.cs b/src/Server/Endpoints/PdfEndpoints.cs index 1e47de4..18414aa 100644 --- a/src/Server/Endpoints/PdfEndpoints.cs +++ b/src/Server/Endpoints/PdfEndpoints.cs @@ -52,6 +52,7 @@ public static IEndpointRouteBuilder MapPdfEndpoints(this IEndpointRouteBuilder e /// The Mustang CLI service for executing commands. /// The file upload request with the PDF file to validate. /// The logger factory for creating loggers. + /// The cancellation token for managing task cancellation. /// /// An containing a with validation results, /// including whether the file is valid, signature status, and a detailed validation report.