diff --git a/.github/workflows/publish-nuget.yml b/.github/workflows/publish-nuget.yml
new file mode 100644
index 0000000..844a4c7
--- /dev/null
+++ b/.github/workflows/publish-nuget.yml
@@ -0,0 +1,35 @@
+name: Publish to NuGet
+
+on:
+ push:
+ tags:
+ - 'v*'
+
+jobs:
+ publish:
+ runs-on: ubuntu-latest
+ permissions:
+ id-token: write
+ contents: read
+
+ steps:
+ - uses: actions/checkout@v5
+
+ - name: Setup .NET
+ uses: actions/setup-dotnet@v5
+ with:
+ dotnet-version: '10.0.x'
+
+ - name: Pack
+ run: |
+ dotnet pack src/MaksIT.Core.Desktop/MaksIT.Core.Desktop.csproj -c Release -o artifacts
+ dotnet pack src/MaksIT.Core.UI/MaksIT.Core.UI.csproj -c Release -o artifacts
+
+ - name: NuGet login (OIDC)
+ id: login
+ uses: NuGet/login@v1
+ with:
+ user: maks-it
+
+ - name: Push to NuGet
+ run: dotnet nuget push artifacts/*.nupkg --api-key ${{ steps.login.outputs.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json --skip-duplicate
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 29eef12..163f90c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
+## [0.1.1] - 2026-10-27
+
+### Changed
+
+- **MaksIT.Core.UI:** Avalonia and Avalonia.Desktop 12.1.2 → 12.1.4.
+- Release packs both libraries for the GitHub release; nuget.org publish uses GitHub Actions Trusted Publishing instead of local `DotNetNuGet`.
+
+### Fixed
+
+- Sync RepoUtils release engine (`-InstallOnly` / Helm install helpers) and bump test packages (xunit.v3, coverlet.MTP).
+
## [0.1.0] - 2026-10-10
### Added
diff --git a/README.md b/README.md
index be8e54b..7b7fd73 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
# MaksIT.Core desktop UI

-
+

Shared .NET 10 libraries for MaksIT desktop apps. Install from NuGet. Do not reference this folder from another repository.
diff --git a/src/MaksIT.Core.Desktop.Tests/MaksIT.Core.Desktop.Tests.csproj b/src/MaksIT.Core.Desktop.Tests/MaksIT.Core.Desktop.Tests.csproj
index 170e2e9..a84d07e 100644
--- a/src/MaksIT.Core.Desktop.Tests/MaksIT.Core.Desktop.Tests.csproj
+++ b/src/MaksIT.Core.Desktop.Tests/MaksIT.Core.Desktop.Tests.csproj
@@ -11,8 +11,8 @@
-
-
+
+
diff --git a/src/MaksIT.Core.Desktop/MaksIT.Core.Desktop.csproj b/src/MaksIT.Core.Desktop/MaksIT.Core.Desktop.csproj
index 2deebc8..dae5aeb 100644
--- a/src/MaksIT.Core.Desktop/MaksIT.Core.Desktop.csproj
+++ b/src/MaksIT.Core.Desktop/MaksIT.Core.Desktop.csproj
@@ -10,7 +10,7 @@
$(NoWarn);CS1591
MaksIT.Core.Desktop
- 0.1.0
+ 0.1.1
Maksym Sadovnychyy
MAKS-IT
MaksIT.Core.Desktop
diff --git a/src/MaksIT.Core.UI.Tests/MaksIT.Core.UI.Tests.csproj b/src/MaksIT.Core.UI.Tests/MaksIT.Core.UI.Tests.csproj
index a16ee84..f946318 100644
--- a/src/MaksIT.Core.UI.Tests/MaksIT.Core.UI.Tests.csproj
+++ b/src/MaksIT.Core.UI.Tests/MaksIT.Core.UI.Tests.csproj
@@ -11,8 +11,8 @@
-
-
+
+
diff --git a/src/MaksIT.Core.UI/MaksIT.Core.UI.csproj b/src/MaksIT.Core.UI/MaksIT.Core.UI.csproj
index c4f35e7..7aa867e 100644
--- a/src/MaksIT.Core.UI/MaksIT.Core.UI.csproj
+++ b/src/MaksIT.Core.UI/MaksIT.Core.UI.csproj
@@ -11,7 +11,7 @@
$(NoWarn);CS1591
MaksIT.Core.UI
- 0.1.0
+ 0.1.1
Maksym Sadovnychyy
MAKS-IT
MaksIT.Core.UI
@@ -43,8 +43,8 @@
-
-
+
+
diff --git a/utils/engines/release/Invoke-ReleasePackage.ps1 b/utils/engines/release/Invoke-ReleasePackage.ps1
index 887e7a7..f8d45f5 100644
--- a/utils/engines/release/Invoke-ReleasePackage.ps1
+++ b/utils/engines/release/Invoke-ReleasePackage.ps1
@@ -8,6 +8,10 @@
.NOTES
Per-plugin dryRun on mutatesRemote plugins validates without remote mutation.
There is no engine-wide dryRun switch — set dryRun on each plugin as needed.
+
+ -InstallOnly (Install-Helm-*.bat) keeps the version plugin and HelmSelfDeploy.
+ Compile, test, image build, image push, and HelmPush are skipped. The chart
+ must already be in OCI at the version the version plugin reports.
#>
# Keep a plain param block so unbound launcher arguments remain in $args for
@@ -17,6 +21,17 @@ param()
$ErrorActionPreference = 'Stop'
Set-Location $PSScriptRoot
+$installOnly = $false
+$extensionArgs = [System.Collections.Generic.List[object]]::new()
+foreach ($argument in @($args)) {
+ if ([string]$argument -eq '-InstallOnly') {
+ $installOnly = $true
+ continue
+ }
+
+ $extensionArgs.Add($argument)
+}
+
$srcDir = (Resolve-Path (Join-Path $PSScriptRoot '..\..')).Path
. (Join-Path $srcDir 'modules/Engine/Import-EngineModules.ps1')
@@ -24,7 +39,7 @@ Import-EngineModules -Engine Release
$releaseExtension = $null
if (Get-Command Initialize-ReleaseExtension -ErrorAction SilentlyContinue) {
- $releaseExtension = Initialize-ReleaseExtension -ScriptDir $PSScriptRoot -ArgumentList $args
+ $releaseExtension = Initialize-ReleaseExtension -ScriptDir $PSScriptRoot -ArgumentList @($extensionArgs)
}
$settings = if ($null -ne $releaseExtension) {
@@ -35,9 +50,29 @@ else {
}
$configuredPlugins = Get-ConfiguredPlugins -Settings $settings
+if ($installOnly) {
+ $enabledBefore = @($configuredPlugins | Where-Object { $_.enabled } | ForEach-Object { [string]$_.name })
+ $configuredPlugins = @(Select-HelmInstallPlugins -Plugins $configuredPlugins -ScriptDir $PSScriptRoot)
+ $kept = @($configuredPlugins | ForEach-Object { [string]$_.name })
+ $skipped = @($enabledBefore | Where-Object { $_ -notin $kept })
+ if ($skipped.Count -gt 0) {
+ Write-Log -Level 'INFO' -Message "Install-only: skipping $($skipped -join ', '). Chart and images are taken from OCI."
+ }
+
+ Write-Log -Level 'INFO' -Message "Install-only: running $($kept -join ', ')."
+}
+
Initialize-RepoUtilsVaultSecrets -Settings $settings -Plugins $configuredPlugins
-$releaseBanner = if ($null -ne $releaseExtension) {
+$releaseBanner = if ($installOnly) {
+ $modeLabel = 'ha'
+ if ($null -ne $releaseExtension -and $releaseExtension.ContextData.PSObject.Properties.Name -contains 'deployMode') {
+ $modeLabel = [string]$releaseExtension.ContextData.deployMode
+ }
+
+ "HELM INSTALL (deploy mode: $modeLabel; OCI chart, no build or push)"
+}
+elseif ($null -ne $releaseExtension) {
$releaseExtension.StepBanner
}
else {
@@ -97,7 +132,11 @@ if (-not $releaseStageInitialized) {
Write-Log -Level 'OK' -Message '=================================================='
if ($releaseHadPluginFailures) {
- Write-Log -Level 'ERROR' -Message 'RELEASE FAILED'
+ $failureLabel = if ($installOnly) { 'HELM INSTALL FAILED' } else { 'RELEASE FAILED' }
+ Write-Log -Level 'ERROR' -Message $failureLabel
+}
+elseif ($installOnly) {
+ Write-Log -Level 'OK' -Message 'HELM INSTALL COMPLETE'
}
elseif ($engineContext.PSObject.Properties.Name -contains 'skipPublishPlugins' -and $engineContext.skipPublishPlugins) {
Write-Log -Level 'OK' -Message 'RUN COMPLETE (publish skipped by ReleasePublishGuard)'
@@ -110,7 +149,7 @@ else {
}
Write-Log -Level 'OK' -Message '=================================================='
-if ($engineContext.isNonReleaseBranch -and -not ($engineContext.PSObject.Properties.Name -contains 'skipPublishPlugins' -and $engineContext.skipPublishPlugins)) {
+if (-not $installOnly -and $engineContext.isNonReleaseBranch -and -not ($engineContext.PSObject.Properties.Name -contains 'skipPublishPlugins' -and $engineContext.skipPublishPlugins)) {
$preferredReleaseBranch = Get-PreferredReleaseBranch -EngineContext $engineContext
Write-Log -Level 'INFO' -Message "For publish, use an allowed branch (see ReleasePublishGuard.branches), e.g. '$preferredReleaseBranch', and satisfy the guard requirements."
}
diff --git a/utils/engines/release/scriptSettings.json b/utils/engines/release/scriptSettings.json
index edb2505..5d48d2b 100644
--- a/utils/engines/release/scriptSettings.json
+++ b/utils/engines/release/scriptSettings.json
@@ -1,7 +1,7 @@
{
"$schema": "https://json-schema.org/draft-07/schema",
"title": "Release Package Script Settings",
- "description": "Invoke-ReleasePackage.ps1 plugin settings. Place ReleasePublishGuard before GitHub/DotNetNuGet. Publish plugins omit per-plugin branches. Semver comes from DotNetReleaseVersion (projectFiles). DotNetPack packs the first projectFiles entry only, so each library is packed and pushed as its own pair.",
+ "description": "Invoke-ReleasePackage.ps1 plugin settings. Place ReleasePublishGuard before GitHub. Publish plugins omit per-plugin branches. Semver comes from DotNetReleaseVersion (projectFiles). DotNetPack packs the first projectFiles entry only, so each library is packed for GitHub assets; nuget.org publish is GHA Trusted Publishing.",
"repoUtilsSecretsShared": "RepoUtilsSecretsShared",
"repoUtilsSecrets": "RepoUtilsSecrets",
"plugins": [
@@ -47,13 +47,6 @@
],
"artifactsDir": "..\\..\\..\\releases"
},
- {
- "name": "DotNetNuGet",
- "stageLabel": "release",
- "enabled": true,
- "nugetSecret": "NuGet",
- "source": "https://api.nuget.org/v3/index.json"
- },
{
"name": "DotNetPack",
"stageLabel": "build",
@@ -63,13 +56,6 @@
],
"artifactsDir": "..\\..\\..\\releases"
},
- {
- "name": "DotNetNuGet",
- "stageLabel": "release",
- "enabled": true,
- "nugetSecret": "NuGet",
- "source": "https://api.nuget.org/v3/index.json"
- },
{
"name": "AttachNuGetPackages",
"stageLabel": "release",
diff --git a/utils/modules/Engine/ReleaseSupport.psm1 b/utils/modules/Engine/ReleaseSupport.psm1
index 6dc2ffb..055a9cb 100644
--- a/utils/modules/Engine/ReleaseSupport.psm1
+++ b/utils/modules/Engine/ReleaseSupport.psm1
@@ -266,4 +266,61 @@ function Get-PreferredReleaseBranch {
return "main"
}
-Export-ModuleMember -Function Assert-WorkingTreeClean, Initialize-ReleaseStageContext, New-EngineContext, Get-PreferredReleaseBranch
+function Select-HelmInstallPlugins {
+ <#
+ .SYNOPSIS
+ Keeps the release version plugin and HelmSelfDeploy for an OCI install without build or push.
+
+ .DESCRIPTION
+ Install-Helm-*.bat passes -InstallOnly. The chart and images are already in OCI, so compile,
+ test, image build, image push, and HelmPush are not run. The version plugin still supplies
+ the chart tag (shared.version). HelmSelfDeploy dryRun is rejected: that path needs the local
+ package HelmPush keeps in the same run.
+ #>
+ param(
+ [Parameter(Mandatory = $true)]
+ [AllowEmptyCollection()]
+ [object[]]$Plugins,
+
+ [Parameter(Mandatory = $true)]
+ [string]$ScriptDir
+ )
+
+ $versionPlugins = @(Get-EnabledVersionPlugins -Plugins $Plugins -ScriptDir $ScriptDir)
+ if ($versionPlugins.Count -eq 0) {
+ throw "Install-only Helm requires exactly one enabled release version plugin (providesVersion) so the OCI chart tag can be resolved. Build and push plugins are not run."
+ }
+
+ if ($versionPlugins.Count -gt 1) {
+ $names = ($versionPlugins | ForEach-Object { [string]$_.name }) -join ', '
+ throw "Install-only Helm requires exactly one enabled release version plugin. Found: $names."
+ }
+
+ $deployPlugins = @($Plugins | Where-Object {
+ $null -ne $_ -and
+ $_.enabled -and
+ [string]$_.name -eq 'HelmSelfDeploy'
+ })
+
+ if ($deployPlugins.Count -eq 0) {
+ throw "Install-only Helm requires an enabled HelmSelfDeploy plugin. The chart is installed from OCI; image build, image push, and HelmPush are not run."
+ }
+
+ if ($deployPlugins.Count -gt 1) {
+ throw "Install-only Helm found multiple enabled HelmSelfDeploy plugins."
+ }
+
+ $deployPlugin = $deployPlugins[0]
+ if ($deployPlugin.PSObject.Properties.Name -contains 'dryRun' -and $null -ne $deployPlugin.dryRun -and [bool]$deployPlugin.dryRun) {
+ throw "Install-only Helm cannot use HelmSelfDeploy dryRun. That path needs the local package from HelmPush in the same run. Omit dryRun to install the chart already published to OCI."
+ }
+
+ $versionName = [string]$versionPlugins[0].name
+ return @($Plugins | Where-Object {
+ $null -ne $_ -and
+ $_.enabled -and
+ ([string]$_.name -eq $versionName -or [string]$_.name -eq 'HelmSelfDeploy')
+ })
+}
+
+Export-ModuleMember -Function Assert-WorkingTreeClean, Initialize-ReleaseStageContext, New-EngineContext, Get-PreferredReleaseBranch, Select-HelmInstallPlugins