diff --git a/scripts/pack-clients.ps1 b/scripts/pack-clients.ps1 new file mode 100644 index 0000000..12aa220 --- /dev/null +++ b/scripts/pack-clients.ps1 @@ -0,0 +1,312 @@ +#Requires -Version 7 + +<# +.SYNOPSIS + Packs all MxAccessGateway clients into a single dist/ directory. + +.DESCRIPTION + Runs each language client's native packaging command: + .NET -> dotnet pack (NuGet) + Python -> python -m build (sdist + wheel) + Rust -> cargo package (.crate) + Java -> gradle assemble + jars (jar + sources + javadoc + pom) + Go -> skipped; use scripts/tag-go-module.ps1 + + All artifacts land in -OutputDir (default: dist/). + + With -Publish, each language pushes its package to the internal Gitea + feed. Requires GITEA_USERNAME and GITEA_TOKEN env vars. + +.PARAMETER OutputDir + Where to drop the packed artifacts. Default: ./dist + +.PARAMETER Languages + Subset of languages to pack. Default: all five. + Values: dotnet, python, rust, java, go + +.PARAMETER Publish + After packing, upload to Gitea feeds. Requires: + GITEA_USERNAME + GITEA_TOKEN + Will refuse to publish if either is missing. + +.PARAMETER SkipTests + Skip per-language regression tests before packing. Default: false. + +.EXAMPLE + pwsh scripts/pack-clients.ps1 + pwsh scripts/pack-clients.ps1 -Languages dotnet,python + pwsh scripts/pack-clients.ps1 -Publish +#> + +[CmdletBinding()] +param( + [string]$OutputDir = (Join-Path $PSScriptRoot '..' 'dist'), + [string[]]$Languages = @('dotnet', 'python', 'rust', 'java', 'go'), + [switch]$Publish, + [switch]$SkipTests +) + +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' + +# Normalize comma-separated strings that shells may pass as a single element. +$validLanguages = @('dotnet', 'python', 'rust', 'java', 'go') +$Languages = @($Languages | ForEach-Object { $_ -split ',' } | ForEach-Object { + $_.Trim().ToLowerInvariant() +} | Where-Object { -not [string]::IsNullOrWhiteSpace($_) }) + +foreach ($lang in $Languages) { + if ($validLanguages -notcontains $lang) { + throw "Unsupported language '$lang'. Supported values: $($validLanguages -join ', ')." + } +} + +if ($Languages.Count -eq 0) { + throw "At least one language is required. Supported values: $($validLanguages -join ', ')." +} + +# Resolve absolute output dir +$OutputDir = [System.IO.Path]::GetFullPath($OutputDir) +$RepoRoot = [System.IO.Path]::GetFullPath((Join-Path $PSScriptRoot '..')) + +if (-not (Test-Path $OutputDir)) { + New-Item -ItemType Directory -Path $OutputDir | Out-Null +} + +if ($Publish) { + if ([string]::IsNullOrEmpty($env:GITEA_USERNAME)) { + throw 'Publish requires GITEA_USERNAME env var.' + } + if ([string]::IsNullOrEmpty($env:GITEA_TOKEN)) { + throw 'Publish requires GITEA_TOKEN env var.' + } +} + +$GiteaNugetFeed = 'https://gitea.dohertylan.com/api/packages/dohertj2/nuget/index.json' +$GiteaPypiFeed = 'https://gitea.dohertylan.com/api/packages/dohertj2/pypi' +$JavaHome = '/Users/dohertj2/.local/jdks/jdk-21.0.11+10/Contents/Home' + +function Write-Header { + param([string]$Text) + Write-Host '' + Write-Host '=== ' -NoNewline -ForegroundColor Cyan + Write-Host $Text -ForegroundColor Cyan +} + +# -------- .NET -------- + +function Invoke-PackDotnet { + Write-Header '.NET' + + if (-not $SkipTests) { + Write-Host 'Running .NET client tests...' + $testProject = Join-Path $RepoRoot 'clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/ZB.MOM.WW.MxGateway.Client.Tests.csproj' + & dotnet test $testProject --no-restore + if ($LASTEXITCODE -ne 0) { throw '.NET tests failed.' } + } + + Write-Host 'Packing ZB.MOM.WW.MxGateway.Contracts...' + & dotnet pack (Join-Path $RepoRoot 'src/ZB.MOM.WW.MxGateway.Contracts/ZB.MOM.WW.MxGateway.Contracts.csproj') ` + -c Release -o $OutputDir + if ($LASTEXITCODE -ne 0) { throw '.NET Contracts pack failed.' } + + Write-Host 'Packing ZB.MOM.WW.MxGateway.Client...' + & dotnet pack (Join-Path $RepoRoot 'clients/dotnet/ZB.MOM.WW.MxGateway.Client/ZB.MOM.WW.MxGateway.Client.csproj') ` + -c Release -o $OutputDir + if ($LASTEXITCODE -ne 0) { throw '.NET Client pack failed.' } + + Write-Host "Packed .NET artifacts -> $OutputDir" -ForegroundColor Green + + if ($Publish) { + Write-Host 'Publishing .NET packages to Gitea...' -ForegroundColor Yellow + Get-ChildItem $OutputDir -Filter 'ZB.MOM.WW.MxGateway.*.nupkg' | ForEach-Object { + & dotnet nuget push $_.FullName --source $GiteaNugetFeed --api-key $env:GITEA_TOKEN + if ($LASTEXITCODE -ne 0) { throw "dotnet nuget push failed for '$($_.Name)'." } + } + } +} + +# -------- Python -------- + +function Invoke-PackPython { + Write-Header 'Python' + + # Use a persistent venv in /tmp so repeated runs skip reinstall. + $Venv = '/tmp/mxgw-py' + if (-not (Test-Path "$Venv/bin/python")) { + Write-Host "Creating Python venv at $Venv..." + & python3 -m venv $Venv + if ($LASTEXITCODE -ne 0) { throw 'python3 -m venv failed.' } + & "$Venv/bin/pip" install --quiet --upgrade pip + & "$Venv/bin/pip" install --quiet build twine + & "$Venv/bin/pip" install --quiet -e (Join-Path $RepoRoot 'clients/python[dev]') + } + + if (-not $SkipTests) { + Write-Host 'Running Python tests...' + Push-Location (Join-Path $RepoRoot 'clients/python') + try { + & "$Venv/bin/python" -m pytest -q + if ($LASTEXITCODE -ne 0) { throw 'Python tests failed.' } + } finally { Pop-Location } + } + + Write-Host 'Building Python sdist + wheel...' + & "$Venv/bin/python" -m build (Join-Path $RepoRoot 'clients/python') --outdir $OutputDir + if ($LASTEXITCODE -ne 0) { throw 'Python build failed.' } + + Write-Host "Packed Python artifacts -> $OutputDir" -ForegroundColor Green + + if ($Publish) { + Write-Host 'Publishing Python distribution to Gitea...' -ForegroundColor Yellow + $wheels = @(Get-ChildItem $OutputDir -Filter 'zb_mom_ww_mxaccess_gateway_client-*.whl') + $sdists = @(Get-ChildItem $OutputDir -Filter 'zb_mom_ww_mxaccess_gateway_client-*.tar.gz') + $files = ($wheels + $sdists) | ForEach-Object { $_.FullName } + & "$Venv/bin/python" -m twine upload ` + --repository-url $GiteaPypiFeed ` + -u $env:GITEA_USERNAME ` + -p $env:GITEA_TOKEN ` + @files + if ($LASTEXITCODE -ne 0) { throw 'twine upload failed.' } + } +} + +# -------- Rust -------- + +function Invoke-PackRust { + Write-Header 'Rust' + + $rustDir = Join-Path $RepoRoot 'clients/rust' + Push-Location $rustDir + try { + if (-not $SkipTests) { + Write-Host 'Running Rust tests...' + & cargo test --workspace + if ($LASTEXITCODE -ne 0) { throw 'Rust tests failed.' } + } + + Write-Host 'Running cargo package...' + & cargo package --no-verify + if ($LASTEXITCODE -ne 0) { throw 'cargo package failed.' } + + $packageDir = Join-Path $rustDir 'target/package' + $crates = @(Get-ChildItem $packageDir -Filter '*.crate') + if ($crates.Count -eq 0) { + throw 'cargo package produced no .crate files.' + } + foreach ($crate in $crates) { + Copy-Item $crate.FullName -Destination $OutputDir -Force + Write-Host " Copied $($crate.Name)" + } + } finally { Pop-Location } + + Write-Host "Packed Rust artifacts -> $OutputDir" -ForegroundColor Green + + if ($Publish) { + Write-Host 'Publishing Rust crate to Gitea...' -ForegroundColor Yellow + Push-Location (Join-Path $RepoRoot 'clients/rust') + try { + & cargo publish --no-verify --registry dohertj2-gitea + if ($LASTEXITCODE -ne 0) { throw 'cargo publish failed.' } + } finally { Pop-Location } + } +} + +# -------- Java -------- + +function Invoke-PackJava { + Write-Header 'Java' + + $env:JAVA_HOME = $JavaHome + $javaDir = Join-Path $RepoRoot 'clients/java' + Push-Location $javaDir + try { + if (-not $SkipTests) { + Write-Host 'Running Java tests...' + & gradle ':zb-mom-ww-mxgateway-client:test' --no-daemon + if ($LASTEXITCODE -ne 0) { throw 'Java tests failed.' } + } + + Write-Host 'Assembling Java jars + pom...' + & gradle ` + ':zb-mom-ww-mxgateway-client:assemble' ` + ':zb-mom-ww-mxgateway-client:sourcesJar' ` + ':zb-mom-ww-mxgateway-client:javadocJar' ` + ':zb-mom-ww-mxgateway-client:generatePomFileForMavenPublication' ` + --no-daemon + if ($LASTEXITCODE -ne 0) { throw 'Java assemble failed.' } + + $libsDir = Join-Path $javaDir 'zb-mom-ww-mxgateway-client/build/libs' + $jars = @(Get-ChildItem $libsDir -Filter 'zb-mom-ww-mxgateway-client-*.jar') + if ($jars.Count -eq 0) { + throw "No jars found under '$libsDir'." + } + foreach ($jar in $jars) { + Copy-Item $jar.FullName -Destination $OutputDir -Force + Write-Host " Copied $($jar.Name)" + } + + $pomSrc = Join-Path $javaDir 'zb-mom-ww-mxgateway-client/build/publications/maven/pom-default.xml' + if (Test-Path $pomSrc) { + # Derive the version from the jar filename (e.g. zb-mom-ww-mxgateway-client-0.1.0.jar). + $versionJar = $jars | Where-Object { $_.Name -notmatch '-(sources|javadoc)\.jar$' } | Select-Object -First 1 + $version = if ($versionJar) { + [System.IO.Path]::GetFileNameWithoutExtension($versionJar.Name) -replace '^zb-mom-ww-mxgateway-client-', '' + } else { + '0.1.0' + } + $pomDest = Join-Path $OutputDir "zb-mom-ww-mxgateway-client-$version.pom" + Copy-Item $pomSrc -Destination $pomDest -Force + Write-Host " Copied pom -> $([System.IO.Path]::GetFileName($pomDest))" + } else { + Write-Warning "POM not found at '$pomSrc'; skipping." + } + } finally { Pop-Location } + + Write-Host "Packed Java artifacts -> $OutputDir" -ForegroundColor Green + + if ($Publish) { + Write-Host 'Publishing Java artifacts to Gitea Maven feed...' -ForegroundColor Yellow + Push-Location $javaDir + try { + & gradle ':zb-mom-ww-mxgateway-client:publish' --no-daemon + if ($LASTEXITCODE -ne 0) { throw 'gradle publish failed.' } + } finally { Pop-Location } + } +} + +# -------- Go -------- + +function Invoke-PackGo { + Write-Header 'Go' + Write-Host 'Go modules are released by git-tagging — no artifact to pack.' -ForegroundColor Yellow + Write-Host 'To publish a Go release, run:' -ForegroundColor Yellow + Write-Host ' pwsh scripts/tag-go-module.ps1 -Version v0.1.0 -Push' -ForegroundColor Yellow + Write-Host '(skipping)' -ForegroundColor DarkGray +} + +# -------- Dispatch -------- + +$wanted = @{} +foreach ($lang in $Languages) { $wanted[$lang.ToLower()] = $true } + +if ($wanted.ContainsKey('dotnet')) { Invoke-PackDotnet } +if ($wanted.ContainsKey('python')) { Invoke-PackPython } +if ($wanted.ContainsKey('rust')) { Invoke-PackRust } +if ($wanted.ContainsKey('java')) { Invoke-PackJava } +if ($wanted.ContainsKey('go')) { Invoke-PackGo } + +# -------- Summary -------- + +Write-Header 'Summary' +$artifacts = @(Get-ChildItem $OutputDir) +if ($artifacts.Count -eq 0) { + Write-Host ' (no artifacts)' -ForegroundColor DarkGray +} else { + foreach ($a in $artifacts) { + Write-Host (' {0,10} {1}' -f $a.Length, $a.Name) + } +} +Write-Host '' +Write-Host "All artifacts in: $OutputDir" -ForegroundColor Green