name: Publish to PowerShell Gallery on: pull_request: types: [closed] branches: [main] jobs: build: if: github.event.pull_request.merged == true runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 with: fetch-depth: 0 - name: Set up .NET SDK uses: actions/setup-dotnet@v4 with: dotnet-version: '8.0.x' - name: Install PowerShell 7 (if not present) shell: bash run: | set -euo pipefail if command -v pwsh >/dev/null 2>&1; then echo "pwsh already installed: $(pwsh --version)" exit 0 fi sudo apt-get update sudo apt-get install -y --no-install-recommends wget ca-certificates apt-transport-https gnupg source /etc/os-release wget -q "https://packages.microsoft.com/config/ubuntu/${VERSION_ID}/packages-microsoft-prod.deb" -O /tmp/ms-prod.deb sudo dpkg -i /tmp/ms-prod.deb rm -f /tmp/ms-prod.deb sudo apt-get update sudo apt-get install -y powershell pwsh --version - name: Build and test module shell: pwsh run: ./build.ps1 -RunTests - name: Validate module manifest shell: pwsh run: | $ErrorActionPreference = 'Stop' $manifestPath = Join-Path $PWD 'Module/PSInfisicalAPI/PSInfisicalAPI.psd1' $manifest = Test-ModuleManifest -Path $manifestPath Write-Host "Manifest OK: $($manifest.Name) $($manifest.Version)" - name: Upload module artifact uses: actions/upload-artifact@v4 with: name: PSInfisicalAPI-module path: Module/PSInfisicalAPI if-no-files-found: error retention-days: 7 release: needs: build if: ${{ success() && github.event.pull_request.merged == true }} runs-on: ubuntu-latest outputs: version: ${{ steps.meta.outputs.version }} tag: ${{ steps.meta.outputs.tag }} steps: - name: Checkout uses: actions/checkout@v4 with: fetch-depth: 0 - name: Install PowerShell 7 (if not present) shell: bash run: | set -euo pipefail if command -v pwsh >/dev/null 2>&1; then echo "pwsh already installed: $(pwsh --version)" exit 0 fi sudo apt-get update sudo apt-get install -y --no-install-recommends wget ca-certificates apt-transport-https gnupg source /etc/os-release wget -q "https://packages.microsoft.com/config/ubuntu/${VERSION_ID}/packages-microsoft-prod.deb" -O /tmp/ms-prod.deb sudo dpkg -i /tmp/ms-prod.deb rm -f /tmp/ms-prod.deb sudo apt-get update sudo apt-get install -y powershell pwsh --version - name: Download module artifact uses: actions/download-artifact@v4 with: name: PSInfisicalAPI-module path: Module/PSInfisicalAPI - name: Resolve module version and tag id: meta shell: pwsh run: | $ErrorActionPreference = 'Stop' $manifestPath = Join-Path $PWD 'Module/PSInfisicalAPI/PSInfisicalAPI.psd1' $manifest = Test-ModuleManifest -Path $manifestPath $version = $manifest.Version.ToString() $tag = $version Write-Host "Module version: $version" Write-Host "Release tag: $tag" "version=$version" | Out-File -FilePath $env:GITHUB_OUTPUT -Append -Encoding utf8 "tag=$tag" | Out-File -FilePath $env:GITHUB_OUTPUT -Append -Encoding utf8 - name: Package module as release asset shell: pwsh env: VERSION: ${{ steps.meta.outputs.version }} run: | $ErrorActionPreference = 'Stop' $zipPath = Join-Path $PWD "PSInfisicalAPI-$($env:VERSION).zip" if (Test-Path $zipPath) { Remove-Item $zipPath -Force } Compress-Archive -Path 'Module/PSInfisicalAPI/*' -DestinationPath $zipPath -Force Write-Host "Created: $zipPath ($([math]::Round((Get-Item $zipPath).Length / 1KB, 1)) KB)" - name: Create Gitea release shell: pwsh env: GITEA_TOKEN: ${{ github.token }} API_URL: ${{ github.api_url }} REPO: ${{ github.repository }} TAG: ${{ steps.meta.outputs.tag }} VERSION: ${{ steps.meta.outputs.version }} COMMIT_SHA: ${{ github.sha }} PR_NUMBER: ${{ github.event.pull_request.number }} PR_TITLE: ${{ github.event.pull_request.title }} PR_AUTHOR: ${{ github.event.pull_request.user.login }} SERVER_URL: ${{ github.server_url }} RUN_ID: ${{ github.run_id }} run: | $ErrorActionPreference = 'Stop' if ([string]::IsNullOrWhiteSpace($env:GITEA_TOKEN)) { throw "github.token is not available; cannot call the Gitea release API." } $shortSha = $env:COMMIT_SHA.Substring(0, [Math]::Min(12, $env:COMMIT_SHA.Length)) $buildUtc = (Get-Date).ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ssZ') $runUrl = "$($env:SERVER_URL)/$($env:REPO)/actions/runs/$($env:RUN_ID)" $prUrl = "$($env:SERVER_URL)/$($env:REPO)/pulls/$($env:PR_NUMBER)" $changelogSection = '' if (Test-Path 'CHANGELOG.md') { $lines = [System.IO.File]::ReadAllLines('CHANGELOG.md') $start = -1; $end = $lines.Length for ($i = 0; $i -lt $lines.Length; $i++) { if ($lines[$i] -match "^##\s+$([regex]::Escape($env:VERSION))\s*$") { $start = $i + 1; continue } if ($start -ge 0 -and $lines[$i] -match '^##\s+') { $end = $i; break } } if ($start -ge 0) { $changelogSection = ($lines[$start..($end - 1)] -join "`n").Trim() } } $body = @" **PSInfisicalAPI $($env:VERSION)** | Field | Value | | --- | --- | | Version | ``$($env:VERSION)`` | | Tag | ``$($env:TAG)`` | | Commit | [``$shortSha``]($($env:SERVER_URL)/$($env:REPO)/commit/$($env:COMMIT_SHA)) | | Built (UTC) | $buildUtc | | Merged PR | [#$($env:PR_NUMBER) $($env:PR_TITLE)]($prUrl) by @$($env:PR_AUTHOR) | | Workflow run | [$($env:RUN_ID)]($runUrl) | ## Changes $(if ($changelogSection) { $changelogSection } else { '_No CHANGELOG section found for this version._' }) ## Install ``````powershell Install-Module -Name PSInfisicalAPI -RequiredVersion $($env:VERSION) -Scope CurrentUser `````` "@ $headers = @{ Authorization = "token $($env:GITEA_TOKEN)" Accept = 'application/json' } $createUri = "$($env:API_URL)/repos/$($env:REPO)/releases" $existing = $null try { $existing = Invoke-RestMethod -Method Get -Headers $headers ` -Uri "$createUri/tags/$($env:TAG)" -ErrorAction Stop } catch { if ($_.Exception.Response.StatusCode.value__ -ne 404) { throw } } if ($existing) { Write-Host "Release tag '$($env:TAG)' already exists (id=$($existing.id)); skipping release creation." return } $payload = @{ tag_name = $env:TAG target_commitish = $env:COMMIT_SHA name = "PSInfisicalAPI $($env:VERSION)" body = $body draft = $false prerelease = $false } | ConvertTo-Json -Depth 4 $release = Invoke-RestMethod -Method Post -Uri $createUri -Headers $headers ` -ContentType 'application/json' -Body $payload Write-Host "Created release id=$($release.id) at $($release.html_url)" $assetPath = Join-Path $PWD "PSInfisicalAPI-$($env:VERSION).zip" $uploadUri = "$createUri/$($release.id)/assets?name=PSInfisicalAPI-$($env:VERSION).zip" $fileBytes = [System.IO.File]::ReadAllBytes($assetPath) Invoke-RestMethod -Method Post -Uri $uploadUri -Headers $headers ` -ContentType 'application/zip' -Body $fileBytes | Out-Null Write-Host "Uploaded asset: PSInfisicalAPI-$($env:VERSION).zip" publish: needs: release if: ${{ success() && github.event.pull_request.merged == true }} runs-on: ubuntu-latest steps: - name: Install PowerShell 7 (if not present) shell: bash run: | set -euo pipefail if command -v pwsh >/dev/null 2>&1; then echo "pwsh already installed: $(pwsh --version)" exit 0 fi sudo apt-get update sudo apt-get install -y --no-install-recommends wget ca-certificates apt-transport-https gnupg source /etc/os-release wget -q "https://packages.microsoft.com/config/ubuntu/${VERSION_ID}/packages-microsoft-prod.deb" -O /tmp/ms-prod.deb sudo dpkg -i /tmp/ms-prod.deb rm -f /tmp/ms-prod.deb sudo apt-get update sudo apt-get install -y powershell pwsh --version - name: Download module artifact uses: actions/download-artifact@v4 with: name: PSInfisicalAPI-module path: Module/PSInfisicalAPI - name: Bootstrap PowerShellGet / NuGet provider shell: pwsh run: | $ErrorActionPreference = 'Stop' Set-PSRepository -Name PSGallery -InstallationPolicy Trusted if (-not (Get-PackageProvider -Name NuGet -ListAvailable -ErrorAction SilentlyContinue)) { Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force -Scope CurrentUser | Out-Null } Get-PackageProvider -Name NuGet | Format-Table Name,Version - name: Verify PowerShell Gallery API key is configured shell: pwsh env: PSGALLERY_API_KEY: ${{ secrets.PSGALLERY_API_KEY }} run: | if ([string]::IsNullOrWhiteSpace($env:PSGALLERY_API_KEY)) { throw "Repository secret 'PSGALLERY_API_KEY' is not configured." } - name: Re-validate downloaded module manifest shell: pwsh run: | $ErrorActionPreference = 'Stop' $manifestPath = Join-Path $PWD 'Module/PSInfisicalAPI/PSInfisicalAPI.psd1' $manifest = Test-ModuleManifest -Path $manifestPath Write-Host "Manifest OK: $($manifest.Name) $($manifest.Version)" - name: Publish to PowerShell Gallery shell: pwsh env: PSGALLERY_API_KEY: ${{ secrets.PSGALLERY_API_KEY }} run: | $ErrorActionPreference = 'Stop' $moduleDir = Join-Path $PWD 'Module/PSInfisicalAPI' Write-Host "Publishing module from: $moduleDir" Publish-Module ` -Path $moduleDir ` -NuGetApiKey $env:PSGALLERY_API_KEY ` -Verbose