Catalog/.gitlab-ci.yml

154 lines
7.9 KiB
YAML

stages:
- build
- publish
# Only create pipelines automatically when a Git tag is pushed.
# Otherwise the pipeline must be started manually (pipeline "Run" / dispatch equivalent).
# workflow:
# rules:
# - if: '$CI_COMMIT_TAG'
# when: always
# - if: '$CI_PIPELINE_SOURCE == "web"'
# when: always
# - when: never
variables:
DOTNET_CLI_TELEMETRY_OPTOUT: "1"
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: "1"
BUILD_CONFIG: "Release"
# NOTE: This project uses repository variables for NuGet auth because secrets
# (masked/protected variables) may not be available on your GitLab plan.
# Replace the placeholders below with values in the repository, or override
# them in your project CI/CD variables when available.
# - NUGET_USERNAME : username (can be any value when using a PAT)
# - NUGET_PASSWORD : personal access token or project deploy token
NUGET_USERNAME: "REPLACE_WITH_USERNAME"
NUGET_PASSWORD: "REPLACE_WITH_TOKEN"
# Build job for Windows runner (shell executor). Remove 'image' so the runner uses the host environment.
build_windows:
stage: build
tags:
- saas-windows-medium-amd64
script:
- |
powershell -NoProfile -Command {
$needsInstall = -not (dotnet --list-sdks 2>$null | Select-String '^10\.')
if ($needsInstall) {
Write-Host 'Installing .NET 10 SDK using dotnet-install.ps1'
Invoke-WebRequest 'https://dot.net/v1/dotnet-install.ps1' -OutFile dotnet-install.ps1 -UseBasicParsing
.\dotnet-install.ps1 -Channel 10.0 -InstallDir $env:USERPROFILE\.dotnet
$dotnetExe = Join-Path $env:USERPROFILE '.dotnet\dotnet.exe'
} else {
Write-Host '.NET 10 SDK already present on PATH'
$dotnetExe = 'dotnet'
}
# Configure private NuGet source from GitLab Packages using CI_JOB_TOKEN
# Fallback to repository variables NUGET_USERNAME/NUGET_PASSWORD for shared runners
$nugetUrl = 'https://gitlab.com/api/v4/projects/79509532/packages/nuget/index.json'
$authMode = $null
if ($env:CI_JOB_TOKEN) {
Write-Host 'Configuring private NuGet source Nuget-GitLab-AIFotoONLUS using CI_JOB_TOKEN...'
try { & $dotnetExe nuget remove source Nuget-GitLab-AIFotoONLUS } catch {}
& $dotnetExe nuget add source $nugetUrl --name Nuget-GitLab-AIFotoONLUS --username gitlab-ci-token --password $env:CI_JOB_TOKEN --store-password-in-clear-text
$authMode = 'JobToken'
} elseif ($env:NUGET_USERNAME -and $env:NUGET_PASSWORD) {
Write-Host 'Configuring private NuGet source Nuget-GitLab-AIFotoONLUS using NUGET_USERNAME/NUGET_PASSWORD...'
try { & $dotnetExe nuget remove source Nuget-GitLab-AIFotoONLUS } catch {}
& $dotnetExe nuget add source $nugetUrl --name Nuget-GitLab-AIFotoONLUS --username $env:NUGET_USERNAME --password $env:NUGET_PASSWORD --store-password-in-clear-text
$authMode = 'UserCreds'
} else {
Write-Host 'No credentials available; skipping private NuGet source configuration.'
}
& $dotnetExe --info
# Diagnostic: verify GitLab NuGet feed and package visibility using configured auth
if ($authMode) {
Write-Host 'Checking GitLab NuGet feed index and project packages for AIFotoONLUS.Core using auth mode:' $authMode
try {
if ($authMode -eq 'JobToken') {
$headers = @{ 'JOB-TOKEN' = $env:CI_JOB_TOKEN }
} else {
$pair = "$env:NUGET_USERNAME:$env:NUGET_PASSWORD"
$b64 = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes($pair))
$headers = @{ Authorization = "Basic $b64" }
}
Invoke-RestMethod -Uri $nugetUrl -Headers $headers -Method Get | ConvertTo-Json | Write-Host
} catch { Write-Host "Failed to fetch feed index: $_" }
try {
$pkgApi = "https://gitlab.com/api/v4/projects/79509532/packages?package_name=AIFotoONLUS.Core"
Invoke-RestMethod -Uri $pkgApi -Headers $headers -Method Get | ConvertTo-Json | Write-Host
} catch { Write-Host "Failed to query project packages API: $_" }
} else {
Write-Host 'Skipping feed diagnostics because no auth configured.'
}
& $dotnetExe restore
& $dotnetExe build "imagecatalog\ImageCatalog 2.csproj" -c $env:BUILD_CONFIG -v minimal
# Write a minversion file into the build output so downstream jobs can read the computed version.
try {
$outRoot = Join-Path -Path "imagecatalog\bin\$env:BUILD_CONFIG" -ChildPath '*'
# search under the build output for a file starting with ImageCatalog.
$built = Get-ChildItem -Path (Join-Path "imagecatalog\bin\$env:BUILD_CONFIG" '.') -Recurse -File -ErrorAction SilentlyContinue | Where-Object { $_.Name -like 'ImageCatalog.*' } | Select-Object -First 1
if ($built) {
$base = [System.IO.Path]::GetFileNameWithoutExtension($built.Name)
$version = $base -replace '^ImageCatalog\.', ''
$minPath = Join-Path $built.DirectoryName 'minversion'
Write-Host "Writing minversion '$version' to $minPath"
Set-Content -Path $minPath -Value $version -Encoding UTF8
} else {
Write-Host 'No ImageCatalog build artifact found to derive minversion from.'
}
} catch {
Write-Host "Failed to write minversion: $_"
}
}
artifacts:
paths:
- "imagecatalog/bin/$BUILD_CONFIG/net10.0-windows/**"
expire_in: 1 hour
# Publish and create GitLab Release when building a tag.
publish_release:
stage: publish
image: mcr.microsoft.com/dotnet/sdk:10.0
needs:
- job: build_windows
artifacts: true
script: |
set -euo pipefail
dotnet --info
echo "Reading MinVer version from build artifacts"
# locate a minversion file produced by the build artifacts
minfile=$(find imagecatalog -type f -iname 'minversion' -print | head -n1 || true)
if [ -z "$minfile" ]; then minfile=$(find . -type f -iname 'minversion' -print | head -n1 || true); fi
if [ -z "$minfile" ]; then echo "No minversion file found in artifacts"; exit 1; fi
echo "Found minversion file: $minfile"
version=$(cat "$minfile" | tr -d '\r\n')
if [ -z "$version" ]; then echo "minversion was empty"; exit 1; fi
echo "Using version: $version"
# find the primary artifact to upload (prefer the executable or first file under the build output)
file=$(find imagecatalog/bin -type f \! -iname 'minversion' -print | head -n1 || true)
if [ -z "$file" ]; then file=$(find . -type f -name 'ImageCatalog.*' -print | head -n1 || true); fi
if [ -z "$file" ]; then echo "No artifact file found to attach"; exit 1; fi
echo "Uploading artifact: $file"
uploadResp=$(curl --silent --show-error --header "JOB-TOKEN:$CI_JOB_TOKEN" --form "file=@$file" "$CI_API_V4_URL/projects/$CI_PROJECT_ID/uploads")
assetPath=$(echo "$uploadResp" | sed -n 's/.*"url":"\([^\"]*\)".*/\1/p')
if [ -z "$assetPath" ]; then echo "Upload failed: $uploadResp"; exit 1; fi
assetUrl="$CI_SERVER_URL$assetPath"
echo "Uploaded asset url: $assetUrl"
basename=$(basename "$file")
# create release JSON using the exact minversion value as tag_name
cat > release.json <<EOF
{"name":"$version","tag_name":"$version","ref":"$CI_COMMIT_SHA","description":"Automated release from CI (version $version)","assets":{"links":[{"name":"$basename","url":"$assetUrl"}]}}
EOF
echo "Creating release for tag: $version"
curl --silent --show-error --header "JOB-TOKEN:$CI_JOB_TOKEN" -X POST -H "Content-Type: application/json" --data @release.json "$CI_API_V4_URL/projects/$CI_PROJECT_ID/releases"
artifacts:
expire_in: 1 day
# only:
# - tags
# Notes for runner setup: The job now runs on the public .NET SDK image and downloads artifacts from the
# `build_windows` job via `needs`. It reads the `minversion` file produced by the build artifacts and
# uses that value as the release tag.