diff --git a/.github/workflows/chocolatey-publish-cfl.yml b/.github/workflows/chocolatey-publish-cfl.yml
index aa44e669..9c9e8c1d 100644
--- a/.github/workflows/chocolatey-publish-cfl.yml
+++ b/.github/workflows/chocolatey-publish-cfl.yml
@@ -11,20 +11,29 @@ on:
jobs:
publish:
runs-on: windows-latest
+ env:
+ VERSION: ${{ inputs.version }}
steps:
- uses: actions/checkout@v4
+ - name: Validate version
+ shell: pwsh
+ run: |
+ if ($env:VERSION -notmatch '^[0-9]+\.[0-9]+\.[0-9]+$') {
+ throw "Version must be numeric SemVer (major.minor.patch): $env:VERSION"
+ }
+
- name: Download release assets
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
- $version = "${{ inputs.version }}"
+ $version = $env:VERSION
$tag = "cfl-v$version"
gh release download $tag --pattern "cfl_${version}_windows_*.zip" --pattern "checksums.txt" --dir artifacts
- name: Extract checksums
run: |
- $version = "${{ inputs.version }}"
+ $version = $env:VERSION
$checksums = Get-Content artifacts/checksums.txt
$amd64 = ($checksums | Select-String "cfl_${version}_windows_amd64.zip").ToString().Split(" ")[0]
$arm64 = ($checksums | Select-String "cfl_${version}_windows_arm64.zip").ToString().Split(" ")[0]
@@ -33,28 +42,22 @@ jobs:
- name: Update nuspec version
run: |
- $version = "${{ inputs.version }}"
+ $version = $env:VERSION
$nuspec = Get-Content tools/cfl/packaging/chocolatey/confluence-cli.nuspec
$nuspec = $nuspec -replace '.*', "$version"
$nuspec | Set-Content tools/cfl/packaging/chocolatey/confluence-cli.nuspec
- - name: Update install script checksums
- run: |
- $script = Get-Content tools/cfl/packaging/chocolatey/tools/chocolateyInstall.ps1
- $script = $script -replace "CHECKSUM_AMD64_PLACEHOLDER", $env:CHECKSUM_AMD64
- $script = $script -replace "CHECKSUM_ARM64_PLACEHOLDER", $env:CHECKSUM_ARM64
- $script | Set-Content tools/cfl/packaging/chocolatey/tools/chocolateyInstall.ps1
-
- - name: Update install script URLs
+ - name: Render install script
run: |
- $version = "${{ inputs.version }}"
- $script = Get-Content tools/cfl/packaging/chocolatey/tools/chocolateyInstall.ps1
- $script = $script -replace 'https://github.com/open-cli-collective/confluence-cli/', 'https://github.com/open-cli-collective/atlassian-cli/'
- $script = $script -replace '/v\$\{version\}', "/cfl-v`${version}"
- $script | Set-Content tools/cfl/packaging/chocolatey/tools/chocolateyInstall.ps1
+ pwsh -File tools/cfl/scripts/render-chocolatey-install.ps1 `
+ -Version $env:VERSION `
+ -ScriptPath tools/cfl/packaging/chocolatey/tools/chocolateyInstall.ps1 `
+ -ChecksumAmd64 $env:CHECKSUM_AMD64 `
+ -ChecksumArm64 $env:CHECKSUM_ARM64
- name: Pack and push
run: |
cd tools/cfl/packaging/chocolatey
choco pack
- choco push confluence-cli.${{ inputs.version }}.nupkg --source https://push.chocolatey.org/ --api-key ${{ secrets.CHOCOLATEY_API_KEY }}
+ $package = "confluence-cli.$($env:VERSION).nupkg"
+ choco push $package --source https://push.chocolatey.org/ --api-key ${{ secrets.CHOCOLATEY_API_KEY }}
diff --git a/.github/workflows/test-chocolatey.yml b/.github/workflows/test-chocolatey.yml
index 7c9ff03c..8379bd45 100644
--- a/.github/workflows/test-chocolatey.yml
+++ b/.github/workflows/test-chocolatey.yml
@@ -5,6 +5,15 @@ on:
branches: [main]
paths:
- 'tools/*/packaging/chocolatey/**'
+ - 'tools/cfl/scripts/**'
+ - '.github/workflows/chocolatey-publish-cfl.yml'
+ - '.github/workflows/test-chocolatey.yml'
+ pull_request:
+ paths:
+ - 'tools/*/packaging/chocolatey/**'
+ - 'tools/cfl/scripts/**'
+ - '.github/workflows/chocolatey-publish-cfl.yml'
+ - '.github/workflows/test-chocolatey.yml'
jobs:
test-cfl:
@@ -34,14 +43,85 @@ jobs:
}
Write-Host "Install script syntax is valid"
- - name: Test pack (dry run)
+ - name: Test rendered package
+ shell: pwsh
run: |
- cd tools/cfl/packaging/chocolatey
- # Update version for test
- $nuspec = Get-Content confluence-cli.nuspec
- $nuspec = $nuspec -replace '.*', '0.0.1-test'
- $nuspec | Set-Content confluence-cli.nuspec
- choco pack --verbose
+ $version = '0.0.1'
+ $packageDir = 'tools/cfl/packaging/chocolatey'
+ $nuspecPath = Join-Path $packageDir 'confluence-cli.nuspec'
+ $nuspec = (Get-Content $nuspecPath -Raw).Replace('0.0.0', "$version")
+ Set-Content $nuspecPath $nuspec
+
+ $scriptPath = Join-Path $packageDir 'tools/chocolateyInstall.ps1'
+ $checksumAmd64 = '0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef'
+ $checksumArm64 = 'fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210'
+ pwsh -File tools/cfl/scripts/render-chocolatey-install.ps1 `
+ -Version $version `
+ -ScriptPath $scriptPath `
+ -ChecksumAmd64 $checksumAmd64 `
+ -ChecksumArm64 $checksumArm64
+
+ Push-Location $packageDir
+ try {
+ choco pack --verbose
+ } finally {
+ Pop-Location
+ }
+
+ $packagePath = Join-Path $packageDir "confluence-cli.$version.nupkg"
+ if (-not (Test-Path $packagePath)) { throw "Expected package was not created: $packagePath" }
+ $extractDir = Join-Path $env:RUNNER_TEMP "cfl-choco-$([guid]::NewGuid())"
+ [IO.Compression.ZipFile]::ExtractToDirectory($packagePath, $extractDir)
+ $renderedPath = Join-Path $extractDir 'tools/chocolateyInstall.ps1'
+ $rendered = Get-Content $renderedPath -Raw
+ if ($rendered -match 'URL_AMD64_PLACEHOLDER|URL_ARM64_PLACEHOLDER|CHECKSUM_AMD64_PLACEHOLDER|CHECKSUM_ARM64_PLACEHOLDER|ChocolateyPackageVersion|\$\{version\}') {
+ throw 'Rendered cfl package still contains a URL/checksum placeholder or runtime package-version expression'
+ }
+ $expectedAmd64 = "https://github.com/open-cli-collective/atlassian-cli/releases/download/cfl-v$version/cfl_${version}_windows_amd64.zip"
+ $expectedArm64 = "https://github.com/open-cli-collective/atlassian-cli/releases/download/cfl-v$version/cfl_${version}_windows_arm64.zip"
+ if (-not $rendered.Contains($expectedAmd64)) { throw "Rendered package is missing $expectedAmd64" }
+ if (-not $rendered.Contains($expectedArm64)) { throw "Rendered package is missing $expectedArm64" }
+
+ function Install-ChocolateyZipPackage {
+ param(
+ [string]$PackageName,
+ [string]$Url,
+ [string]$UnzipLocation,
+ [string]$Checksum,
+ [string]$ChecksumType
+ )
+ $global:capturedPackageName = $PackageName
+ $global:capturedUrl = $Url
+ $global:capturedChecksum = $Checksum
+ $global:capturedChecksumType = $ChecksumType
+ }
+
+ $env:ChocolateyPackageName = 'confluence-cli'
+ $architectures = @(
+ @{ Name = 'AMD64'; Environment = 'AMD64'; Url = $expectedAmd64; Checksum = $checksumAmd64 },
+ @{ Name = 'ARM64'; Environment = 'ARM64'; Url = $expectedArm64; Checksum = $checksumArm64 }
+ )
+ foreach ($architecture in $architectures) {
+ $previousArchitecture = $env:PROCESSOR_ARCHITECTURE
+ try {
+ $env:PROCESSOR_ARCHITECTURE = $architecture.Environment
+ $global:capturedUrl = $null
+ $global:capturedChecksum = $null
+ $global:capturedChecksumType = $null
+ & $renderedPath
+ } finally {
+ $env:PROCESSOR_ARCHITECTURE = $previousArchitecture
+ }
+ if ($global:capturedUrl -ne $architecture.Url) {
+ throw "$($architecture.Name) selected URL '$global:capturedUrl', expected '$($architecture.Url)'"
+ }
+ if ($global:capturedChecksum -ne $architecture.Checksum) {
+ throw "$($architecture.Name) selected checksum '$global:capturedChecksum', expected '$($architecture.Checksum)'"
+ }
+ if ($global:capturedChecksumType -ne 'sha256') {
+ throw "$($architecture.Name) selected checksum type '$global:capturedChecksumType', expected 'sha256'"
+ }
+ }
test-jtk:
runs-on: windows-latest
diff --git a/tools/cfl/packaging/chocolatey/tools/chocolateyInstall.ps1 b/tools/cfl/packaging/chocolatey/tools/chocolateyInstall.ps1
index 13b5e4e6..ab5f85b2 100644
--- a/tools/cfl/packaging/chocolatey/tools/chocolateyInstall.ps1
+++ b/tools/cfl/packaging/chocolatey/tools/chocolateyInstall.ps1
@@ -1,28 +1,27 @@
$ErrorActionPreference = 'Stop'
-$version = $env:ChocolateyPackageVersion
$toolsDir = Split-Path -Parent $MyInvocation.MyCommand.Definition
-# Checksums injected by release workflow - DO NOT EDIT MANUALLY
+# URLs and checksums injected by release workflow - DO NOT EDIT MANUALLY
+$urlAmd64 = 'URL_AMD64_PLACEHOLDER'
+$urlArm64 = 'URL_ARM64_PLACEHOLDER'
$checksumAmd64 = 'CHECKSUM_AMD64_PLACEHOLDER'
$checksumArm64 = 'CHECKSUM_ARM64_PLACEHOLDER'
# Architecture detection with ARM64 support
if ($env:PROCESSOR_ARCHITECTURE -eq 'ARM64') {
$arch = 'arm64'
+ $url = $urlArm64
$checksum = $checksumArm64
} elseif ([Environment]::Is64BitOperatingSystem) {
$arch = 'amd64'
+ $url = $urlAmd64
$checksum = $checksumAmd64
} else {
throw "32-bit Windows is not supported. confluence-cli requires 64-bit Windows."
}
-$baseUrl = "https://github.com/open-cli-collective/atlassian-cli/releases/download/cfl-v${version}"
-$zipFile = "cfl_${version}_windows_${arch}.zip"
-$url = "${baseUrl}/${zipFile}"
-
-Write-Host "Installing confluence-cli ${version} for Windows ${arch}..."
+Write-Host "Installing confluence-cli for Windows ${arch}..."
Write-Host "URL: ${url}"
Write-Host "Checksum (SHA256): ${checksum}"
diff --git a/tools/cfl/scripts/render-chocolatey-install.ps1 b/tools/cfl/scripts/render-chocolatey-install.ps1
new file mode 100644
index 00000000..53edbb2f
--- /dev/null
+++ b/tools/cfl/scripts/render-chocolatey-install.ps1
@@ -0,0 +1,42 @@
+[CmdletBinding()]
+param(
+ [Parameter(Mandatory)]
+ [ValidatePattern('^[0-9]+\.[0-9]+\.[0-9]+$')]
+ [string]$Version,
+
+ [Parameter(Mandatory)]
+ [string]$ScriptPath,
+
+ [Parameter(Mandatory)]
+ [ValidatePattern('^[0-9a-fA-F]{64}$')]
+ [string]$ChecksumAmd64,
+
+ [Parameter(Mandatory)]
+ [ValidatePattern('^[0-9a-fA-F]{64}$')]
+ [string]$ChecksumArm64
+)
+
+$ErrorActionPreference = 'Stop'
+
+$amd64Url = "https://github.com/open-cli-collective/atlassian-cli/releases/download/cfl-v$Version/cfl_${Version}_windows_amd64.zip"
+$arm64Url = "https://github.com/open-cli-collective/atlassian-cli/releases/download/cfl-v$Version/cfl_${Version}_windows_arm64.zip"
+$script = Get-Content $ScriptPath -Raw
+
+foreach ($placeholder in 'URL_AMD64_PLACEHOLDER', 'URL_ARM64_PLACEHOLDER', 'CHECKSUM_AMD64_PLACEHOLDER', 'CHECKSUM_ARM64_PLACEHOLDER') {
+ if (-not $script.Contains($placeholder)) { throw "Missing $placeholder in $ScriptPath" }
+}
+
+$script = $script.Replace('URL_AMD64_PLACEHOLDER', $amd64Url)
+$script = $script.Replace('URL_ARM64_PLACEHOLDER', $arm64Url)
+$script = $script.Replace('CHECKSUM_AMD64_PLACEHOLDER', $ChecksumAmd64)
+$script = $script.Replace('CHECKSUM_ARM64_PLACEHOLDER', $ChecksumArm64)
+
+if ($script -match 'URL_AMD64_PLACEHOLDER|URL_ARM64_PLACEHOLDER|CHECKSUM_AMD64_PLACEHOLDER|CHECKSUM_ARM64_PLACEHOLDER|ChocolateyPackageVersion|\$\{version\}') {
+ throw "Rendered $ScriptPath still contains a URL/checksum placeholder or runtime package-version expression"
+}
+if (-not $script.Contains($amd64Url)) { throw "Rendered script is missing $amd64Url" }
+if (-not $script.Contains($arm64Url)) { throw "Rendered script is missing $arm64Url" }
+if (-not $script.Contains($ChecksumAmd64)) { throw "Rendered script is missing the AMD64 checksum" }
+if (-not $script.Contains($ChecksumArm64)) { throw "Rendered script is missing the ARM64 checksum" }
+
+Set-Content $ScriptPath $script