From 1d9aa1f04bfccca04623290db39dd6d51d52935d Mon Sep 17 00:00:00 2001 From: Rian Stockbower Date: Thu, 29 Jan 2026 06:58:24 -0500 Subject: [PATCH 1/3] feat: implement complete CI/CD pipeline for monorepo Workflows: - ci.yml: Path-filtered build/test/lint for each tool - auto-release-{cfl,jtk}.yml: Auto-create tags on feat:/fix: commits - release-{cfl,jtk}.yml: GoReleaser builds triggered by tags - chocolatey-publish-{cfl,jtk}.yml: Manual Chocolatey publishing - winget-publish-{cfl,jtk}.yml: Manual Winget publishing - test-chocolatey.yml: Validate Chocolatey packaging - test-winget.yml: Validate Winget manifests GoReleaser: - .goreleaser-cfl.yml / .goreleaser-jtk.yml at repo root - Builds for darwin/linux/windows on amd64/arm64 - Generates .deb, .rpm packages - Updates Homebrew tap automatically Packaging updates: - All URLs point to atlassian-cli repo - Tag format: {tool}-v{version} (e.g., cfl-v0.9.150) --- .github/workflows/auto-release-cfl.yml | 35 +++++ .github/workflows/auto-release-jtk.yml | 35 +++++ .github/workflows/chocolatey-publish-cfl.yml | 60 ++++++++ .github/workflows/chocolatey-publish-jtk.yml | 60 ++++++++ .github/workflows/ci.yml | 80 +++++++---- .github/workflows/release-cfl.yml | 128 ++++++++++++++++++ .github/workflows/release-jtk.yml | 128 ++++++++++++++++++ .github/workflows/test-chocolatey.yml | 99 ++++++++++++++ .github/workflows/test-winget.yml | 45 ++++++ .github/workflows/winget-publish-cfl.yml | 47 +++++++ .github/workflows/winget-publish-jtk.yml | 47 +++++++ .goreleaser-cfl.yml | 103 ++++++++++++++ .goreleaser-jtk.yml | 108 +++++++++++++++ CLAUDE.md | 42 +++++- .../chocolatey/confluence-cli.nuspec | 14 +- .../chocolatey/tools/chocolateyInstall.ps1 | 2 +- .../OpenCLICollective.cfl.installer.yaml | 4 +- .../OpenCLICollective.cfl.locale.en-US.yaml | 6 +- .../chocolatey/jira-ticket-cli.nuspec | 12 +- .../chocolatey/tools/chocolateyInstall.ps1 | 2 +- ...ICollective.jira-ticket-cli.installer.yaml | 4 +- ...llective.jira-ticket-cli.locale.en-US.yaml | 6 +- 22 files changed, 1010 insertions(+), 57 deletions(-) create mode 100644 .github/workflows/auto-release-cfl.yml create mode 100644 .github/workflows/auto-release-jtk.yml create mode 100644 .github/workflows/chocolatey-publish-cfl.yml create mode 100644 .github/workflows/chocolatey-publish-jtk.yml create mode 100644 .github/workflows/release-cfl.yml create mode 100644 .github/workflows/release-jtk.yml create mode 100644 .github/workflows/test-chocolatey.yml create mode 100644 .github/workflows/test-winget.yml create mode 100644 .github/workflows/winget-publish-cfl.yml create mode 100644 .github/workflows/winget-publish-jtk.yml create mode 100644 .goreleaser-cfl.yml create mode 100644 .goreleaser-jtk.yml diff --git a/.github/workflows/auto-release-cfl.yml b/.github/workflows/auto-release-cfl.yml new file mode 100644 index 00000000..3d1724f6 --- /dev/null +++ b/.github/workflows/auto-release-cfl.yml @@ -0,0 +1,35 @@ +name: Auto Release cfl + +on: + push: + branches: [main] + paths: + - 'tools/cfl/**/*.go' + - 'tools/cfl/go.mod' + - 'tools/cfl/go.sum' + +jobs: + create-tag: + runs-on: ubuntu-latest + # Only create release for feat: or fix: commits + if: startsWith(github.event.head_commit.message, 'feat:') || startsWith(github.event.head_commit.message, 'fix:') + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + token: ${{ secrets.TAP_GITHUB_TOKEN }} + + - name: Read version + id: version + run: | + BASE_VERSION=$(cat tools/cfl/version.txt | tr -d '\n') + VERSION="${BASE_VERSION}.${{ github.run_number }}" + echo "version=$VERSION" >> $GITHUB_OUTPUT + echo "Version: $VERSION" + + - name: Create and push tag + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + git tag -a "cfl-v${{ steps.version.outputs.version }}" -m "Release cfl v${{ steps.version.outputs.version }}" + git push origin "cfl-v${{ steps.version.outputs.version }}" diff --git a/.github/workflows/auto-release-jtk.yml b/.github/workflows/auto-release-jtk.yml new file mode 100644 index 00000000..445b96dd --- /dev/null +++ b/.github/workflows/auto-release-jtk.yml @@ -0,0 +1,35 @@ +name: Auto Release jtk + +on: + push: + branches: [main] + paths: + - 'tools/jtk/**/*.go' + - 'tools/jtk/go.mod' + - 'tools/jtk/go.sum' + +jobs: + create-tag: + runs-on: ubuntu-latest + # Only create release for feat: or fix: commits + if: startsWith(github.event.head_commit.message, 'feat:') || startsWith(github.event.head_commit.message, 'fix:') + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + token: ${{ secrets.TAP_GITHUB_TOKEN }} + + - name: Read version + id: version + run: | + BASE_VERSION=$(cat tools/jtk/version.txt | tr -d '\n') + VERSION="${BASE_VERSION}.${{ github.run_number }}" + echo "version=$VERSION" >> $GITHUB_OUTPUT + echo "Version: $VERSION" + + - name: Create and push tag + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + git tag -a "jtk-v${{ steps.version.outputs.version }}" -m "Release jtk v${{ steps.version.outputs.version }}" + git push origin "jtk-v${{ steps.version.outputs.version }}" diff --git a/.github/workflows/chocolatey-publish-cfl.yml b/.github/workflows/chocolatey-publish-cfl.yml new file mode 100644 index 00000000..aa44e669 --- /dev/null +++ b/.github/workflows/chocolatey-publish-cfl.yml @@ -0,0 +1,60 @@ +name: Chocolatey Publish cfl + +on: + workflow_dispatch: + inputs: + version: + description: 'Version to publish (e.g., 0.9.150)' + required: true + type: string + +jobs: + publish: + runs-on: windows-latest + steps: + - uses: actions/checkout@v4 + + - name: Download release assets + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + $version = "${{ inputs.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 }}" + $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] + echo "CHECKSUM_AMD64=$amd64" >> $env:GITHUB_ENV + echo "CHECKSUM_ARM64=$arm64" >> $env:GITHUB_ENV + + - name: Update nuspec version + run: | + $version = "${{ inputs.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 + 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 + + - 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 }} diff --git a/.github/workflows/chocolatey-publish-jtk.yml b/.github/workflows/chocolatey-publish-jtk.yml new file mode 100644 index 00000000..79bae199 --- /dev/null +++ b/.github/workflows/chocolatey-publish-jtk.yml @@ -0,0 +1,60 @@ +name: Chocolatey Publish jtk + +on: + workflow_dispatch: + inputs: + version: + description: 'Version to publish (e.g., 0.1.75)' + required: true + type: string + +jobs: + publish: + runs-on: windows-latest + steps: + - uses: actions/checkout@v4 + + - name: Download release assets + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + $version = "${{ inputs.version }}" + $tag = "jtk-v$version" + gh release download $tag --pattern "jtk_${version}_windows_*.zip" --pattern "checksums.txt" --dir artifacts + + - name: Extract checksums + run: | + $version = "${{ inputs.version }}" + $checksums = Get-Content artifacts/checksums.txt + $amd64 = ($checksums | Select-String "jtk_${version}_windows_amd64.zip").ToString().Split(" ")[0] + $arm64 = ($checksums | Select-String "jtk_${version}_windows_arm64.zip").ToString().Split(" ")[0] + echo "CHECKSUM_AMD64=$amd64" >> $env:GITHUB_ENV + echo "CHECKSUM_ARM64=$arm64" >> $env:GITHUB_ENV + + - name: Update nuspec version + run: | + $version = "${{ inputs.version }}" + $nuspec = Get-Content tools/jtk/packaging/chocolatey/jira-ticket-cli.nuspec + $nuspec = $nuspec -replace '.*', "$version" + $nuspec | Set-Content tools/jtk/packaging/chocolatey/jira-ticket-cli.nuspec + + - name: Update install script checksums + run: | + $script = Get-Content tools/jtk/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/jtk/packaging/chocolatey/tools/chocolateyInstall.ps1 + + - name: Update install script URLs + run: | + $version = "${{ inputs.version }}" + $script = Get-Content tools/jtk/packaging/chocolatey/tools/chocolateyInstall.ps1 + $script = $script -replace 'https://github.com/open-cli-collective/jira-ticket-cli/', 'https://github.com/open-cli-collective/atlassian-cli/' + $script = $script -replace '/v\$\{version\}', "/jtk-v`${version}" + $script | Set-Content tools/jtk/packaging/chocolatey/tools/chocolateyInstall.ps1 + + - name: Pack and push + run: | + cd tools/jtk/packaging/chocolatey + choco pack + choco push jira-ticket-cli.${{ inputs.version }}.nupkg --source https://push.chocolatey.org/ --api-key ${{ secrets.CHOCOLATEY_API_KEY }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d6098d4f..5bbc6d2e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,53 +6,77 @@ on: pull_request: jobs: - build-and-test: + detect-changes: runs-on: ubuntu-latest - strategy: - matrix: - go-version: ['1.24'] - + outputs: + cfl: ${{ steps.filter.outputs.cfl }} + jtk: ${{ steps.filter.outputs.jtk }} + shared: ${{ steps.filter.outputs.shared }} steps: - uses: actions/checkout@v4 - - - name: Set up Go - uses: actions/setup-go@v5 + - uses: dorny/paths-filter@v3 + id: filter with: - go-version: ${{ matrix.go-version }} - - - name: Verify go.work - run: go work sync + filters: | + cfl: + - 'tools/cfl/**' + jtk: + - 'tools/jtk/**' + shared: + - 'shared/**' + build-test-cfl: + needs: detect-changes + if: needs.detect-changes.outputs.cfl == 'true' || needs.detect-changes.outputs.shared == 'true' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-go@v5 + with: + go-version: '1.24' - name: Build cfl - run: go build -v ./tools/cfl/cmd/cfl - - - name: Build jtk - run: go build -v ./tools/jtk/cmd/jtk - + run: go build -v ./tools/cfl/... - name: Test cfl - run: go test -v ./tools/cfl/... + run: go test -v -race -coverprofile=coverage-cfl.out ./tools/cfl/... + build-test-jtk: + needs: detect-changes + if: needs.detect-changes.outputs.jtk == 'true' || needs.detect-changes.outputs.shared == 'true' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-go@v5 + with: + go-version: '1.24' + - name: Build jtk + run: go build -v ./tools/jtk/... - name: Test jtk - run: go test -v ./tools/jtk/... + run: go test -v -race -coverprofile=coverage-jtk.out ./tools/jtk/... - lint: + lint-cfl: + needs: detect-changes + if: needs.detect-changes.outputs.cfl == 'true' || needs.detect-changes.outputs.shared == 'true' runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - - name: Set up Go - uses: actions/setup-go@v5 + - uses: actions/setup-go@v5 with: go-version: '1.24' - - - name: golangci-lint cfl - uses: golangci/golangci-lint-action@v6 + - uses: golangci/golangci-lint-action@v6 with: working-directory: tools/cfl version: v2.0.2 - - name: golangci-lint jtk - uses: golangci/golangci-lint-action@v6 + lint-jtk: + needs: detect-changes + if: needs.detect-changes.outputs.jtk == 'true' || needs.detect-changes.outputs.shared == 'true' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-go@v5 + with: + go-version: '1.24' + - uses: golangci/golangci-lint-action@v6 with: working-directory: tools/jtk version: v2.0.2 diff --git a/.github/workflows/release-cfl.yml b/.github/workflows/release-cfl.yml new file mode 100644 index 00000000..6908681d --- /dev/null +++ b/.github/workflows/release-cfl.yml @@ -0,0 +1,128 @@ +name: Release cfl + +on: + push: + tags: + - 'cfl-v*' + +permissions: + contents: write + +jobs: + goreleaser: + runs-on: ubuntu-latest + outputs: + version: ${{ steps.get_version.outputs.version }} + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Get version from tag + id: get_version + run: | + VERSION=${GITHUB_REF#refs/tags/cfl-v} + echo "version=$VERSION" >> $GITHUB_OUTPUT + + - uses: actions/setup-go@v5 + with: + go-version: '1.24' + + - name: Run GoReleaser + uses: goreleaser/goreleaser-action@v6 + with: + distribution: goreleaser + version: '~> v2' + args: release --clean --config .goreleaser-cfl.yml + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + TAP_GITHUB_TOKEN: ${{ secrets.TAP_GITHUB_TOKEN }} + + chocolatey: + needs: goreleaser + runs-on: windows-latest + steps: + - uses: actions/checkout@v4 + + - name: Download release assets + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + $version = "${{ needs.goreleaser.outputs.version }}" + $tag = "cfl-v$version" + gh release download $tag --pattern "cfl_${version}_windows_*.zip" --pattern "checksums.txt" --dir artifacts + + - name: Extract checksums + run: | + $version = "${{ needs.goreleaser.outputs.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] + echo "CHECKSUM_AMD64=$amd64" >> $env:GITHUB_ENV + echo "CHECKSUM_ARM64=$arm64" >> $env:GITHUB_ENV + + - name: Update nuspec version + run: | + $version = "${{ needs.goreleaser.outputs.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 + run: | + $version = "${{ needs.goreleaser.outputs.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 + + - name: Pack and push + run: | + cd tools/cfl/packaging/chocolatey + choco pack + choco push confluence-cli.${{ needs.goreleaser.outputs.version }}.nupkg --source https://push.chocolatey.org/ --api-key ${{ secrets.CHOCOLATEY_API_KEY }} + + winget: + needs: goreleaser + runs-on: windows-latest + steps: + - uses: actions/checkout@v4 + + - name: Download checksums + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + $version = "${{ needs.goreleaser.outputs.version }}" + $tag = "cfl-v$version" + gh release download $tag --pattern "checksums.txt" --dir artifacts + + - name: Extract checksums + run: | + $version = "${{ needs.goreleaser.outputs.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] + echo "CHECKSUM_AMD64=$amd64" >> $env:GITHUB_ENV + echo "CHECKSUM_ARM64=$arm64" >> $env:GITHUB_ENV + + - name: Install wingetcreate + run: | + iwr https://aka.ms/wingetcreate/latest -OutFile wingetcreate.exe + + - name: Update and submit manifest + run: | + $version = "${{ needs.goreleaser.outputs.version }}" + $baseUrl = "https://github.com/open-cli-collective/atlassian-cli/releases/download/cfl-v$version" + + ./wingetcreate.exe update OpenCLICollective.cfl ` + --version $version ` + --urls "$baseUrl/cfl_${version}_windows_amd64.zip|x64" "$baseUrl/cfl_${version}_windows_arm64.zip|arm64" ` + --submit ` + --token ${{ secrets.WINGET_GITHUB_TOKEN }} diff --git a/.github/workflows/release-jtk.yml b/.github/workflows/release-jtk.yml new file mode 100644 index 00000000..d4463f30 --- /dev/null +++ b/.github/workflows/release-jtk.yml @@ -0,0 +1,128 @@ +name: Release jtk + +on: + push: + tags: + - 'jtk-v*' + +permissions: + contents: write + +jobs: + goreleaser: + runs-on: ubuntu-latest + outputs: + version: ${{ steps.get_version.outputs.version }} + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Get version from tag + id: get_version + run: | + VERSION=${GITHUB_REF#refs/tags/jtk-v} + echo "version=$VERSION" >> $GITHUB_OUTPUT + + - uses: actions/setup-go@v5 + with: + go-version: '1.24' + + - name: Run GoReleaser + uses: goreleaser/goreleaser-action@v6 + with: + distribution: goreleaser + version: '~> v2' + args: release --clean --config .goreleaser-jtk.yml + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + TAP_GITHUB_TOKEN: ${{ secrets.TAP_GITHUB_TOKEN }} + + chocolatey: + needs: goreleaser + runs-on: windows-latest + steps: + - uses: actions/checkout@v4 + + - name: Download release assets + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + $version = "${{ needs.goreleaser.outputs.version }}" + $tag = "jtk-v$version" + gh release download $tag --pattern "jtk_${version}_windows_*.zip" --pattern "checksums.txt" --dir artifacts + + - name: Extract checksums + run: | + $version = "${{ needs.goreleaser.outputs.version }}" + $checksums = Get-Content artifacts/checksums.txt + $amd64 = ($checksums | Select-String "jtk_${version}_windows_amd64.zip").ToString().Split(" ")[0] + $arm64 = ($checksums | Select-String "jtk_${version}_windows_arm64.zip").ToString().Split(" ")[0] + echo "CHECKSUM_AMD64=$amd64" >> $env:GITHUB_ENV + echo "CHECKSUM_ARM64=$arm64" >> $env:GITHUB_ENV + + - name: Update nuspec version + run: | + $version = "${{ needs.goreleaser.outputs.version }}" + $nuspec = Get-Content tools/jtk/packaging/chocolatey/jira-ticket-cli.nuspec + $nuspec = $nuspec -replace '.*', "$version" + $nuspec | Set-Content tools/jtk/packaging/chocolatey/jira-ticket-cli.nuspec + + - name: Update install script checksums + run: | + $script = Get-Content tools/jtk/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/jtk/packaging/chocolatey/tools/chocolateyInstall.ps1 + + - name: Update install script URLs + run: | + $version = "${{ needs.goreleaser.outputs.version }}" + $script = Get-Content tools/jtk/packaging/chocolatey/tools/chocolateyInstall.ps1 + $script = $script -replace 'https://github.com/open-cli-collective/jira-ticket-cli/', 'https://github.com/open-cli-collective/atlassian-cli/' + $script = $script -replace '/v\$\{version\}', "/jtk-v`${version}" + $script | Set-Content tools/jtk/packaging/chocolatey/tools/chocolateyInstall.ps1 + + - name: Pack and push + run: | + cd tools/jtk/packaging/chocolatey + choco pack + choco push jira-ticket-cli.${{ needs.goreleaser.outputs.version }}.nupkg --source https://push.chocolatey.org/ --api-key ${{ secrets.CHOCOLATEY_API_KEY }} + + winget: + needs: goreleaser + runs-on: windows-latest + steps: + - uses: actions/checkout@v4 + + - name: Download checksums + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + $version = "${{ needs.goreleaser.outputs.version }}" + $tag = "jtk-v$version" + gh release download $tag --pattern "checksums.txt" --dir artifacts + + - name: Extract checksums + run: | + $version = "${{ needs.goreleaser.outputs.version }}" + $checksums = Get-Content artifacts/checksums.txt + $amd64 = ($checksums | Select-String "jtk_${version}_windows_amd64.zip").ToString().Split(" ")[0] + $arm64 = ($checksums | Select-String "jtk_${version}_windows_arm64.zip").ToString().Split(" ")[0] + echo "CHECKSUM_AMD64=$amd64" >> $env:GITHUB_ENV + echo "CHECKSUM_ARM64=$arm64" >> $env:GITHUB_ENV + + - name: Install wingetcreate + run: | + iwr https://aka.ms/wingetcreate/latest -OutFile wingetcreate.exe + + - name: Update and submit manifest + run: | + $version = "${{ needs.goreleaser.outputs.version }}" + $baseUrl = "https://github.com/open-cli-collective/atlassian-cli/releases/download/jtk-v$version" + + ./wingetcreate.exe update OpenCLICollective.jira-ticket-cli ` + --version $version ` + --urls "$baseUrl/jtk_${version}_windows_amd64.zip|x64" "$baseUrl/jtk_${version}_windows_arm64.zip|arm64" ` + --submit ` + --token ${{ secrets.WINGET_GITHUB_TOKEN }} diff --git a/.github/workflows/test-chocolatey.yml b/.github/workflows/test-chocolatey.yml new file mode 100644 index 00000000..aa9a2d62 --- /dev/null +++ b/.github/workflows/test-chocolatey.yml @@ -0,0 +1,99 @@ +name: Test Chocolatey Packaging + +on: + push: + branches: [main] + paths: + - 'tools/*/packaging/chocolatey/**' + pull_request: + paths: + - 'tools/*/packaging/chocolatey/**' + +jobs: + test-cfl: + runs-on: windows-latest + steps: + - uses: actions/checkout@v4 + + - name: Validate nuspec + run: | + cd tools/cfl/packaging/chocolatey + # Check nuspec is valid XML + [xml]$nuspec = Get-Content confluence-cli.nuspec + Write-Host "Package ID: $($nuspec.package.metadata.id)" + Write-Host "Title: $($nuspec.package.metadata.title)" + + - name: Validate install script syntax + run: | + $script = Get-Content tools/cfl/packaging/chocolatey/tools/chocolateyInstall.ps1 -Raw + $null = [System.Management.Automation.Language.Parser]::ParseInput($script, [ref]$null, [ref]$errors) + if ($errors.Count -gt 0) { + Write-Error "PowerShell syntax errors found:" + $errors | ForEach-Object { Write-Error $_.ToString() } + exit 1 + } + Write-Host "Install script syntax is valid" + + - name: Validate uninstall script syntax + run: | + $script = Get-Content tools/cfl/packaging/chocolatey/tools/chocolateyUninstall.ps1 -Raw + $null = [System.Management.Automation.Language.Parser]::ParseInput($script, [ref]$null, [ref]$errors) + if ($errors.Count -gt 0) { + Write-Error "PowerShell syntax errors found:" + $errors | ForEach-Object { Write-Error $_.ToString() } + exit 1 + } + Write-Host "Uninstall script syntax is valid" + + - name: Test pack (dry run) + 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 + + test-jtk: + runs-on: windows-latest + steps: + - uses: actions/checkout@v4 + + - name: Validate nuspec + run: | + cd tools/jtk/packaging/chocolatey + # Check nuspec is valid XML + [xml]$nuspec = Get-Content jira-ticket-cli.nuspec + Write-Host "Package ID: $($nuspec.package.metadata.id)" + Write-Host "Title: $($nuspec.package.metadata.title)" + + - name: Validate install script syntax + run: | + $script = Get-Content tools/jtk/packaging/chocolatey/tools/chocolateyInstall.ps1 -Raw + $null = [System.Management.Automation.Language.Parser]::ParseInput($script, [ref]$null, [ref]$errors) + if ($errors.Count -gt 0) { + Write-Error "PowerShell syntax errors found:" + $errors | ForEach-Object { Write-Error $_.ToString() } + exit 1 + } + Write-Host "Install script syntax is valid" + + - name: Validate uninstall script syntax + run: | + $script = Get-Content tools/jtk/packaging/chocolatey/tools/chocolateyUninstall.ps1 -Raw + $null = [System.Management.Automation.Language.Parser]::ParseInput($script, [ref]$null, [ref]$errors) + if ($errors.Count -gt 0) { + Write-Error "PowerShell syntax errors found:" + $errors | ForEach-Object { Write-Error $_.ToString() } + exit 1 + } + Write-Host "Uninstall script syntax is valid" + + - name: Test pack (dry run) + run: | + cd tools/jtk/packaging/chocolatey + # Update version for test + $nuspec = Get-Content jira-ticket-cli.nuspec + $nuspec = $nuspec -replace '.*', '0.0.1-test' + $nuspec | Set-Content jira-ticket-cli.nuspec + choco pack --verbose diff --git a/.github/workflows/test-winget.yml b/.github/workflows/test-winget.yml new file mode 100644 index 00000000..4a198b61 --- /dev/null +++ b/.github/workflows/test-winget.yml @@ -0,0 +1,45 @@ +name: Test Winget Manifests + +on: + push: + branches: [main] + paths: + - 'tools/*/packaging/winget/**' + pull_request: + paths: + - 'tools/*/packaging/winget/**' + +jobs: + test-cfl: + runs-on: windows-latest + steps: + - uses: actions/checkout@v4 + + - name: Install winget-cli + run: | + # Install winget from GitHub release + $release = Invoke-RestMethod -Uri "https://api.github.com/repos/microsoft/winget-cli/releases/latest" + $msixBundle = $release.assets | Where-Object { $_.name -like "*.msixbundle" } | Select-Object -First 1 + Invoke-WebRequest -Uri $msixBundle.browser_download_url -OutFile winget.msixbundle + Add-AppxPackage -Path winget.msixbundle + + - name: Validate manifests + run: | + winget validate tools/cfl/packaging/winget/ + + test-jtk: + runs-on: windows-latest + steps: + - uses: actions/checkout@v4 + + - name: Install winget-cli + run: | + # Install winget from GitHub release + $release = Invoke-RestMethod -Uri "https://api.github.com/repos/microsoft/winget-cli/releases/latest" + $msixBundle = $release.assets | Where-Object { $_.name -like "*.msixbundle" } | Select-Object -First 1 + Invoke-WebRequest -Uri $msixBundle.browser_download_url -OutFile winget.msixbundle + Add-AppxPackage -Path winget.msixbundle + + - name: Validate manifests + run: | + winget validate tools/jtk/packaging/winget/ diff --git a/.github/workflows/winget-publish-cfl.yml b/.github/workflows/winget-publish-cfl.yml new file mode 100644 index 00000000..0f967bab --- /dev/null +++ b/.github/workflows/winget-publish-cfl.yml @@ -0,0 +1,47 @@ +name: Winget Publish cfl + +on: + workflow_dispatch: + inputs: + version: + description: 'Version to publish (e.g., 0.9.150)' + required: true + type: string + +jobs: + publish: + runs-on: windows-latest + steps: + - uses: actions/checkout@v4 + + - name: Download checksums + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + $version = "${{ inputs.version }}" + $tag = "cfl-v$version" + gh release download $tag --pattern "checksums.txt" --dir artifacts + + - name: Extract checksums + run: | + $version = "${{ inputs.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] + echo "CHECKSUM_AMD64=$amd64" >> $env:GITHUB_ENV + echo "CHECKSUM_ARM64=$arm64" >> $env:GITHUB_ENV + + - name: Install wingetcreate + run: | + iwr https://aka.ms/wingetcreate/latest -OutFile wingetcreate.exe + + - name: Update and submit manifest + run: | + $version = "${{ inputs.version }}" + $baseUrl = "https://github.com/open-cli-collective/atlassian-cli/releases/download/cfl-v$version" + + ./wingetcreate.exe update OpenCLICollective.cfl ` + --version $version ` + --urls "$baseUrl/cfl_${version}_windows_amd64.zip|x64" "$baseUrl/cfl_${version}_windows_arm64.zip|arm64" ` + --submit ` + --token ${{ secrets.WINGET_GITHUB_TOKEN }} diff --git a/.github/workflows/winget-publish-jtk.yml b/.github/workflows/winget-publish-jtk.yml new file mode 100644 index 00000000..8e626d4f --- /dev/null +++ b/.github/workflows/winget-publish-jtk.yml @@ -0,0 +1,47 @@ +name: Winget Publish jtk + +on: + workflow_dispatch: + inputs: + version: + description: 'Version to publish (e.g., 0.1.75)' + required: true + type: string + +jobs: + publish: + runs-on: windows-latest + steps: + - uses: actions/checkout@v4 + + - name: Download checksums + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + $version = "${{ inputs.version }}" + $tag = "jtk-v$version" + gh release download $tag --pattern "checksums.txt" --dir artifacts + + - name: Extract checksums + run: | + $version = "${{ inputs.version }}" + $checksums = Get-Content artifacts/checksums.txt + $amd64 = ($checksums | Select-String "jtk_${version}_windows_amd64.zip").ToString().Split(" ")[0] + $arm64 = ($checksums | Select-String "jtk_${version}_windows_arm64.zip").ToString().Split(" ")[0] + echo "CHECKSUM_AMD64=$amd64" >> $env:GITHUB_ENV + echo "CHECKSUM_ARM64=$arm64" >> $env:GITHUB_ENV + + - name: Install wingetcreate + run: | + iwr https://aka.ms/wingetcreate/latest -OutFile wingetcreate.exe + + - name: Update and submit manifest + run: | + $version = "${{ inputs.version }}" + $baseUrl = "https://github.com/open-cli-collective/atlassian-cli/releases/download/jtk-v$version" + + ./wingetcreate.exe update OpenCLICollective.jira-ticket-cli ` + --version $version ` + --urls "$baseUrl/jtk_${version}_windows_amd64.zip|x64" "$baseUrl/jtk_${version}_windows_arm64.zip|arm64" ` + --submit ` + --token ${{ secrets.WINGET_GITHUB_TOKEN }} diff --git a/.goreleaser-cfl.yml b/.goreleaser-cfl.yml new file mode 100644 index 00000000..b4c6e5a8 --- /dev/null +++ b/.goreleaser-cfl.yml @@ -0,0 +1,103 @@ +version: 2 + +project_name: cfl + +before: + hooks: + - go mod tidy + - go test ./tools/cfl/... + +builds: + - id: cfl + dir: tools/cfl + main: ./cmd/cfl + binary: cfl + env: + - CGO_ENABLED=0 + goos: + - darwin + - linux + - windows + goarch: + - amd64 + - arm64 + ldflags: + - -s -w + - -X github.com/open-cli-collective/confluence-cli/internal/version.Version={{.Version}} + - -X github.com/open-cli-collective/confluence-cli/internal/version.Commit={{.Commit}} + - -X github.com/open-cli-collective/confluence-cli/internal/version.Date={{.Date}} + +archives: + - id: default + formats: + - tar.gz + format_overrides: + - goos: windows + formats: + - zip + name_template: "{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}" + files: + - tools/cfl/LICENSE + - tools/cfl/README.md + +# Linux packages (.deb and .rpm) +nfpms: + - id: cfl + package_name: cfl + vendor: Open CLI Collective + homepage: https://github.com/open-cli-collective/atlassian-cli + maintainer: Open CLI Collective + description: Command-line interface for Atlassian Confluence Cloud + license: MIT + formats: + - deb + - rpm + bindir: /usr/bin + contents: + - src: tools/cfl/LICENSE + dst: /usr/share/licenses/cfl/LICENSE + +# Homebrew cask with auto-quarantine removal for unsigned binaries +homebrew_casks: + - name: cfl + repository: + owner: open-cli-collective + name: homebrew-tap + token: "{{ .Env.TAP_GITHUB_TOKEN }}" + homepage: https://github.com/open-cli-collective/atlassian-cli + description: "Command-line interface for Atlassian Confluence" + binary: cfl + hooks: + post: + install: | + system_command "/usr/bin/xattr", args: ["-dr", "com.apple.quarantine", "#{staged_path}/cfl"] + caveats: | + cfl has been installed. Run 'cfl init' to configure. + +checksum: + name_template: 'checksums.txt' + +changelog: + sort: asc + use: github + filters: + exclude: + - '^docs:' + - '^test:' + - '^ci:' + - '^chore:' + - '^Merge pull request' + groups: + - title: 'Features' + regexp: '^feat:' + order: 0 + - title: 'Bug Fixes' + regexp: '^fix:' + order: 1 + - title: 'Other' + order: 999 + +release: + github: + owner: open-cli-collective + name: atlassian-cli diff --git a/.goreleaser-jtk.yml b/.goreleaser-jtk.yml new file mode 100644 index 00000000..ee0cac5b --- /dev/null +++ b/.goreleaser-jtk.yml @@ -0,0 +1,108 @@ +version: 2 + +project_name: jtk + +before: + hooks: + - go mod tidy + - go test ./tools/jtk/... + +builds: + - id: jtk + dir: tools/jtk + main: ./cmd/jtk + binary: jtk + env: + - CGO_ENABLED=0 + goos: + - darwin + - linux + - windows + goarch: + - amd64 + - arm64 + ldflags: + - -s -w + - -X github.com/open-cli-collective/jira-ticket-cli/internal/version.Version={{.Version}} + - -X github.com/open-cli-collective/jira-ticket-cli/internal/version.Commit={{.Commit}} + - -X github.com/open-cli-collective/jira-ticket-cli/internal/version.BuildDate={{.Date}} + +archives: + - id: default + formats: + - tar.gz + format_overrides: + - goos: windows + formats: + - zip + name_template: "{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}" + files: + - tools/jtk/LICENSE + - tools/jtk/README.md + +# Linux packages (.deb and .rpm) +nfpms: + - id: jtk + package_name: jtk + vendor: Open CLI Collective + homepage: https://github.com/open-cli-collective/atlassian-cli + maintainer: Open CLI Collective + description: Command-line interface for Jira Cloud + license: MIT + formats: + - deb + - rpm + bindir: /usr/bin + contents: + - src: tools/jtk/LICENSE + dst: /usr/share/licenses/jtk/LICENSE + +# Homebrew cask with auto-quarantine removal for unsigned binaries +homebrew_casks: + - name: jira-ticket-cli + repository: + owner: open-cli-collective + name: homebrew-tap + token: "{{ .Env.TAP_GITHUB_TOKEN }}" + homepage: https://github.com/open-cli-collective/atlassian-cli + description: "Command-line interface for Jira Cloud" + binary: jtk + hooks: + post: + install: | + system_command "/usr/bin/xattr", args: ["-dr", "com.apple.quarantine", "#{staged_path}/jtk"] + caveats: | + jira-ticket-cli has been installed. + + To configure, run: + jtk config set --domain DOMAIN --email EMAIL --token TOKEN + + Get your API token from: https://id.atlassian.com/manage-profile/security/api-tokens + +checksum: + name_template: 'checksums.txt' + +changelog: + sort: asc + use: github + filters: + exclude: + - '^docs:' + - '^test:' + - '^ci:' + - '^chore:' + - '^Merge pull request' + groups: + - title: 'Features' + regexp: '^feat:' + order: 0 + - title: 'Bug Fixes' + regexp: '^fix:' + order: 1 + - title: 'Other' + order: 999 + +release: + github: + owner: open-cli-collective + name: atlassian-cli diff --git a/CLAUDE.md b/CLAUDE.md index c565cc68..7e61f6ae 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -56,11 +56,45 @@ go test ./tools/jtk/... go work sync ``` -## CI +## CI/CD -GitHub Actions CI runs on all PRs and pushes to main: -- **build-and-test**: Verifies `go.work`, builds both binaries, runs all tests -- **lint**: Runs golangci-lint v2 for both tools +### CI Workflows + +GitHub Actions CI runs on all PRs and pushes to main with **path filtering**: +- Changes to `tools/cfl/**` trigger cfl build/test/lint only +- Changes to `tools/jtk/**` trigger jtk build/test/lint only +- Changes to `shared/**` trigger both (future shared code) + +### Release Workflow + +Releases are automated with a dual-gate system: + +1. **Path gate**: Only Go code changes (`**/*.go`, `go.mod`, `go.sum`) can trigger releases +2. **Commit gate**: Only `feat:` and `fix:` commits create releases + +**Tag format**: `{tool}-v{base}.{run}` (e.g., `cfl-v0.9.150`, `jtk-v0.1.75`) + +When a release-triggering commit is merged to main: +1. `auto-release-{tool}.yml` creates a tag +2. Tag push triggers `release-{tool}.yml` +3. GoReleaser builds binaries for all platforms +4. Homebrew tap is updated automatically +5. Chocolatey and Winget workflows publish packages + +### Required Secrets + +| Secret | Purpose | +|--------|---------| +| `TAP_GITHUB_TOKEN` | Push tags + update Homebrew tap | +| `CHOCOLATEY_API_KEY` | Publish to Chocolatey | +| `WINGET_GITHUB_TOKEN` | Submit to microsoft/winget-pkgs | + +### Build Matrix + +Each tool builds 6 binaries: +- darwin/amd64, darwin/arm64 (.tar.gz) +- linux/amd64, linux/arm64 (.tar.gz + .deb + .rpm) +- windows/amd64, windows/arm64 (.zip) ## Environment Variables diff --git a/tools/cfl/packaging/chocolatey/confluence-cli.nuspec b/tools/cfl/packaging/chocolatey/confluence-cli.nuspec index 43a296b6..1ab7a0f1 100644 --- a/tools/cfl/packaging/chocolatey/confluence-cli.nuspec +++ b/tools/cfl/packaging/chocolatey/confluence-cli.nuspec @@ -6,12 +6,12 @@ Confluence CLI Open CLI Collective rianjs - https://github.com/open-cli-collective/confluence-cli/blob/main/LICENSE - https://github.com/open-cli-collective/confluence-cli#readme - https://github.com/open-cli-collective/confluence-cli - https://github.com/open-cli-collective/confluence-cli/tree/main/packaging/chocolatey - https://github.com/open-cli-collective/confluence-cli/issues - https://cdn.jsdelivr.net/gh/open-cli-collective/confluence-cli@main/assets/logo/cfl-256.png + https://github.com/open-cli-collective/atlassian-cli/blob/main/tools/cfl/LICENSE + https://github.com/open-cli-collective/atlassian-cli/tree/main/tools/cfl#readme + https://github.com/open-cli-collective/atlassian-cli + https://github.com/open-cli-collective/atlassian-cli/tree/main/tools/cfl/packaging/chocolatey + https://github.com/open-cli-collective/atlassian-cli/issues + https://cdn.jsdelivr.net/gh/open-cli-collective/atlassian-cli@main/tools/cfl/assets/logo/cfl-256.png Copyright (c) 2025 Open CLI Collective false A command-line interface for Atlassian Confluence Cloud. Provides markdown-first page management with automatic conversion between Markdown and Confluence's storage format. @@ -25,7 +25,7 @@ Features: Binary: cfl.exe Command-line interface for Atlassian Confluence Cloud - https://github.com/open-cli-collective/confluence-cli/releases + https://github.com/open-cli-collective/atlassian-cli/releases confluence atlassian cli markdown wiki documentation diff --git a/tools/cfl/packaging/chocolatey/tools/chocolateyInstall.ps1 b/tools/cfl/packaging/chocolatey/tools/chocolateyInstall.ps1 index ca17e62f..f107123f 100644 --- a/tools/cfl/packaging/chocolatey/tools/chocolateyInstall.ps1 +++ b/tools/cfl/packaging/chocolatey/tools/chocolateyInstall.ps1 @@ -18,7 +18,7 @@ if ($env:PROCESSOR_ARCHITECTURE -eq 'ARM64') { throw "32-bit Windows is not supported. confluence-cli requires 64-bit Windows." } -$baseUrl = "https://github.com/open-cli-collective/confluence-cli/releases/download/v${version}" +$baseUrl = "https://github.com/open-cli-collective/atlassian-cli/releases/download/cfl-v${version}" $zipFile = "cfl_${version}_windows_${arch}.zip" $url = "${baseUrl}/${zipFile}" diff --git a/tools/cfl/packaging/winget/OpenCLICollective.cfl.installer.yaml b/tools/cfl/packaging/winget/OpenCLICollective.cfl.installer.yaml index 2a5ca623..5d05ec03 100644 --- a/tools/cfl/packaging/winget/OpenCLICollective.cfl.installer.yaml +++ b/tools/cfl/packaging/winget/OpenCLICollective.cfl.installer.yaml @@ -9,10 +9,10 @@ NestedInstallerFiles: PortableCommandAlias: cfl Installers: - Architecture: x64 - InstallerUrl: https://github.com/open-cli-collective/confluence-cli/releases/download/v0.0.0/cfl_0.0.0_windows_amd64.zip + InstallerUrl: https://github.com/open-cli-collective/atlassian-cli/releases/download/cfl-v0.0.0/cfl_0.0.0_windows_amd64.zip InstallerSha256: 0000000000000000000000000000000000000000000000000000000000000000 - Architecture: arm64 - InstallerUrl: https://github.com/open-cli-collective/confluence-cli/releases/download/v0.0.0/cfl_0.0.0_windows_arm64.zip + InstallerUrl: https://github.com/open-cli-collective/atlassian-cli/releases/download/cfl-v0.0.0/cfl_0.0.0_windows_arm64.zip InstallerSha256: 0000000000000000000000000000000000000000000000000000000000000000 ManifestType: installer ManifestVersion: 1.10.0 diff --git a/tools/cfl/packaging/winget/OpenCLICollective.cfl.locale.en-US.yaml b/tools/cfl/packaging/winget/OpenCLICollective.cfl.locale.en-US.yaml index 3467b740..ed589764 100644 --- a/tools/cfl/packaging/winget/OpenCLICollective.cfl.locale.en-US.yaml +++ b/tools/cfl/packaging/winget/OpenCLICollective.cfl.locale.en-US.yaml @@ -6,9 +6,9 @@ PackageLocale: en-US Publisher: Open CLI Collective PublisherUrl: https://github.com/open-cli-collective PackageName: Confluence CLI -PackageUrl: https://github.com/open-cli-collective/confluence-cli +PackageUrl: https://github.com/open-cli-collective/atlassian-cli/tree/main/tools/cfl License: MIT -LicenseUrl: https://github.com/open-cli-collective/confluence-cli/blob/main/LICENSE +LicenseUrl: https://github.com/open-cli-collective/atlassian-cli/blob/main/tools/cfl/LICENSE ShortDescription: Command-line interface for Atlassian Confluence Cloud Description: |- A CLI tool for managing Confluence pages with a markdown-first workflow. @@ -22,6 +22,6 @@ Tags: - markdown - wiki - documentation -ReleaseNotesUrl: https://github.com/open-cli-collective/confluence-cli/releases +ReleaseNotesUrl: https://github.com/open-cli-collective/atlassian-cli/releases ManifestType: defaultLocale ManifestVersion: 1.10.0 diff --git a/tools/jtk/packaging/chocolatey/jira-ticket-cli.nuspec b/tools/jtk/packaging/chocolatey/jira-ticket-cli.nuspec index aa2dae9c..2ab5791e 100644 --- a/tools/jtk/packaging/chocolatey/jira-ticket-cli.nuspec +++ b/tools/jtk/packaging/chocolatey/jira-ticket-cli.nuspec @@ -6,11 +6,11 @@ Jira Ticket CLI Open CLI Collective rianjs - https://github.com/open-cli-collective/jira-ticket-cli/blob/main/LICENSE - https://github.com/open-cli-collective/jira-ticket-cli#readme - https://github.com/open-cli-collective/jira-ticket-cli - https://github.com/open-cli-collective/jira-ticket-cli/tree/main/packaging/chocolatey - https://github.com/open-cli-collective/jira-ticket-cli/issues + https://github.com/open-cli-collective/atlassian-cli/blob/main/tools/jtk/LICENSE + https://github.com/open-cli-collective/atlassian-cli/tree/main/tools/jtk#readme + https://github.com/open-cli-collective/atlassian-cli + https://github.com/open-cli-collective/atlassian-cli/tree/main/tools/jtk/packaging/chocolatey + https://github.com/open-cli-collective/atlassian-cli/issues Copyright (c) 2025 Open CLI Collective false A command-line interface for Jira Cloud. Manage issues, sprints, and workflows directly from your terminal. @@ -24,7 +24,7 @@ Features: Binary: jtk.exe Command-line interface for Jira Cloud - https://github.com/open-cli-collective/jira-ticket-cli/releases + https://github.com/open-cli-collective/atlassian-cli/releases jira atlassian cli ticket issue-tracking agile diff --git a/tools/jtk/packaging/chocolatey/tools/chocolateyInstall.ps1 b/tools/jtk/packaging/chocolatey/tools/chocolateyInstall.ps1 index 7b88b618..a8d73fbd 100644 --- a/tools/jtk/packaging/chocolatey/tools/chocolateyInstall.ps1 +++ b/tools/jtk/packaging/chocolatey/tools/chocolateyInstall.ps1 @@ -18,7 +18,7 @@ if ($env:PROCESSOR_ARCHITECTURE -eq 'ARM64') { throw "32-bit Windows is not supported. jtk requires 64-bit Windows." } -$baseUrl = "https://github.com/open-cli-collective/jira-ticket-cli/releases/download/v${version}" +$baseUrl = "https://github.com/open-cli-collective/atlassian-cli/releases/download/jtk-v${version}" $zipFile = "jtk_${version}_windows_${arch}.zip" $url = "${baseUrl}/${zipFile}" diff --git a/tools/jtk/packaging/winget/OpenCLICollective.jira-ticket-cli.installer.yaml b/tools/jtk/packaging/winget/OpenCLICollective.jira-ticket-cli.installer.yaml index bda0414d..36b63de9 100644 --- a/tools/jtk/packaging/winget/OpenCLICollective.jira-ticket-cli.installer.yaml +++ b/tools/jtk/packaging/winget/OpenCLICollective.jira-ticket-cli.installer.yaml @@ -9,10 +9,10 @@ NestedInstallerFiles: PortableCommandAlias: jtk Installers: - Architecture: x64 - InstallerUrl: https://github.com/open-cli-collective/jira-ticket-cli/releases/download/v0.0.0/jtk_0.0.0_windows_amd64.zip + InstallerUrl: https://github.com/open-cli-collective/atlassian-cli/releases/download/jtk-v0.0.0/jtk_0.0.0_windows_amd64.zip InstallerSha256: 0000000000000000000000000000000000000000000000000000000000000000 - Architecture: arm64 - InstallerUrl: https://github.com/open-cli-collective/jira-ticket-cli/releases/download/v0.0.0/jtk_0.0.0_windows_arm64.zip + InstallerUrl: https://github.com/open-cli-collective/atlassian-cli/releases/download/jtk-v0.0.0/jtk_0.0.0_windows_arm64.zip InstallerSha256: 0000000000000000000000000000000000000000000000000000000000000000 ManifestType: installer ManifestVersion: 1.10.0 diff --git a/tools/jtk/packaging/winget/OpenCLICollective.jira-ticket-cli.locale.en-US.yaml b/tools/jtk/packaging/winget/OpenCLICollective.jira-ticket-cli.locale.en-US.yaml index 760a7dc9..6756d4e4 100644 --- a/tools/jtk/packaging/winget/OpenCLICollective.jira-ticket-cli.locale.en-US.yaml +++ b/tools/jtk/packaging/winget/OpenCLICollective.jira-ticket-cli.locale.en-US.yaml @@ -6,9 +6,9 @@ PackageLocale: en-US Publisher: Open CLI Collective PublisherUrl: https://github.com/open-cli-collective PackageName: Jira Ticket CLI -PackageUrl: https://github.com/open-cli-collective/jira-ticket-cli +PackageUrl: https://github.com/open-cli-collective/atlassian-cli/tree/main/tools/jtk License: MIT -LicenseUrl: https://github.com/open-cli-collective/jira-ticket-cli/blob/main/LICENSE +LicenseUrl: https://github.com/open-cli-collective/atlassian-cli/blob/main/tools/jtk/LICENSE ShortDescription: Command-line interface for Jira Cloud Description: |- A CLI tool for managing Jira issues directly from your terminal. @@ -21,6 +21,6 @@ Tags: - ticket - issue-tracking - agile -ReleaseNotesUrl: https://github.com/open-cli-collective/jira-ticket-cli/releases +ReleaseNotesUrl: https://github.com/open-cli-collective/atlassian-cli/releases ManifestType: defaultLocale ManifestVersion: 1.10.0 From b911e2e19020914c019b40c315f2d4fa22b91611 Mon Sep 17 00:00:00 2001 From: Rian Stockbower Date: Thu, 29 Jan 2026 07:02:49 -0500 Subject: [PATCH 2/3] fix: update workflows for CI compatibility - Use golangci-lint-action@v7 for golangci-lint v2 support - Fix PowerShell variable initialization in chocolatey tests - Use pre-installed winget on windows-latest runners --- .github/workflows/ci.yml | 4 +-- .github/workflows/test-chocolatey.yml | 36 ++++++++++++++++++--------- .github/workflows/test-winget.yml | 18 ++------------ 3 files changed, 28 insertions(+), 30 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5bbc6d2e..e7fe7dc5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -62,7 +62,7 @@ jobs: - uses: actions/setup-go@v5 with: go-version: '1.24' - - uses: golangci/golangci-lint-action@v6 + - uses: golangci/golangci-lint-action@v7 with: working-directory: tools/cfl version: v2.0.2 @@ -76,7 +76,7 @@ jobs: - uses: actions/setup-go@v5 with: go-version: '1.24' - - uses: golangci/golangci-lint-action@v6 + - uses: golangci/golangci-lint-action@v7 with: working-directory: tools/jtk version: v2.0.2 diff --git a/.github/workflows/test-chocolatey.yml b/.github/workflows/test-chocolatey.yml index aa9a2d62..b6904594 100644 --- a/.github/workflows/test-chocolatey.yml +++ b/.github/workflows/test-chocolatey.yml @@ -24,23 +24,29 @@ jobs: Write-Host "Title: $($nuspec.package.metadata.title)" - name: Validate install script syntax + shell: pwsh run: | $script = Get-Content tools/cfl/packaging/chocolatey/tools/chocolateyInstall.ps1 -Raw - $null = [System.Management.Automation.Language.Parser]::ParseInput($script, [ref]$null, [ref]$errors) - if ($errors.Count -gt 0) { + $tokens = $null + $parseErrors = $null + $null = [System.Management.Automation.Language.Parser]::ParseInput($script, [ref]$tokens, [ref]$parseErrors) + if ($parseErrors.Count -gt 0) { Write-Error "PowerShell syntax errors found:" - $errors | ForEach-Object { Write-Error $_.ToString() } + $parseErrors | ForEach-Object { Write-Error $_.ToString() } exit 1 } Write-Host "Install script syntax is valid" - name: Validate uninstall script syntax + shell: pwsh run: | $script = Get-Content tools/cfl/packaging/chocolatey/tools/chocolateyUninstall.ps1 -Raw - $null = [System.Management.Automation.Language.Parser]::ParseInput($script, [ref]$null, [ref]$errors) - if ($errors.Count -gt 0) { + $tokens = $null + $parseErrors = $null + $null = [System.Management.Automation.Language.Parser]::ParseInput($script, [ref]$tokens, [ref]$parseErrors) + if ($parseErrors.Count -gt 0) { Write-Error "PowerShell syntax errors found:" - $errors | ForEach-Object { Write-Error $_.ToString() } + $parseErrors | ForEach-Object { Write-Error $_.ToString() } exit 1 } Write-Host "Uninstall script syntax is valid" @@ -68,23 +74,29 @@ jobs: Write-Host "Title: $($nuspec.package.metadata.title)" - name: Validate install script syntax + shell: pwsh run: | $script = Get-Content tools/jtk/packaging/chocolatey/tools/chocolateyInstall.ps1 -Raw - $null = [System.Management.Automation.Language.Parser]::ParseInput($script, [ref]$null, [ref]$errors) - if ($errors.Count -gt 0) { + $tokens = $null + $parseErrors = $null + $null = [System.Management.Automation.Language.Parser]::ParseInput($script, [ref]$tokens, [ref]$parseErrors) + if ($parseErrors.Count -gt 0) { Write-Error "PowerShell syntax errors found:" - $errors | ForEach-Object { Write-Error $_.ToString() } + $parseErrors | ForEach-Object { Write-Error $_.ToString() } exit 1 } Write-Host "Install script syntax is valid" - name: Validate uninstall script syntax + shell: pwsh run: | $script = Get-Content tools/jtk/packaging/chocolatey/tools/chocolateyUninstall.ps1 -Raw - $null = [System.Management.Automation.Language.Parser]::ParseInput($script, [ref]$null, [ref]$errors) - if ($errors.Count -gt 0) { + $tokens = $null + $parseErrors = $null + $null = [System.Management.Automation.Language.Parser]::ParseInput($script, [ref]$tokens, [ref]$parseErrors) + if ($parseErrors.Count -gt 0) { Write-Error "PowerShell syntax errors found:" - $errors | ForEach-Object { Write-Error $_.ToString() } + $parseErrors | ForEach-Object { Write-Error $_.ToString() } exit 1 } Write-Host "Uninstall script syntax is valid" diff --git a/.github/workflows/test-winget.yml b/.github/workflows/test-winget.yml index 4a198b61..979dbcb8 100644 --- a/.github/workflows/test-winget.yml +++ b/.github/workflows/test-winget.yml @@ -15,16 +15,9 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Install winget-cli - run: | - # Install winget from GitHub release - $release = Invoke-RestMethod -Uri "https://api.github.com/repos/microsoft/winget-cli/releases/latest" - $msixBundle = $release.assets | Where-Object { $_.name -like "*.msixbundle" } | Select-Object -First 1 - Invoke-WebRequest -Uri $msixBundle.browser_download_url -OutFile winget.msixbundle - Add-AppxPackage -Path winget.msixbundle - - name: Validate manifests run: | + # winget is pre-installed on windows-latest winget validate tools/cfl/packaging/winget/ test-jtk: @@ -32,14 +25,7 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Install winget-cli - run: | - # Install winget from GitHub release - $release = Invoke-RestMethod -Uri "https://api.github.com/repos/microsoft/winget-cli/releases/latest" - $msixBundle = $release.assets | Where-Object { $_.name -like "*.msixbundle" } | Select-Object -First 1 - Invoke-WebRequest -Uri $msixBundle.browser_download_url -OutFile winget.msixbundle - Add-AppxPackage -Path winget.msixbundle - - name: Validate manifests run: | + # winget is pre-installed on windows-latest winget validate tools/jtk/packaging/winget/ From 8276a39785ad58af1fc464678e0f1db1fcf94911 Mon Sep 17 00:00:00 2001 From: Rian Stockbower Date: Thu, 29 Jan 2026 07:04:40 -0500 Subject: [PATCH 3/3] fix: use temp dir for winget manifest validation Copy manifests to temp dir with test values to avoid README.md being picked up by winget validate. --- .github/workflows/test-winget.yml | 74 ++++++++++++++++++++++++++++--- 1 file changed, 68 insertions(+), 6 deletions(-) diff --git a/.github/workflows/test-winget.yml b/.github/workflows/test-winget.yml index 979dbcb8..f498596a 100644 --- a/.github/workflows/test-winget.yml +++ b/.github/workflows/test-winget.yml @@ -15,17 +15,79 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Validate manifests + - name: Validate manifest schema + shell: pwsh run: | - # winget is pre-installed on windows-latest - winget validate tools/cfl/packaging/winget/ + $testDir = "winget-validate-test" + $testVersion = "0.0.1" + $testHash1 = "0000000000000000000000000000000000000000000000000000000000000001" + $testHash2 = "0000000000000000000000000000000000000000000000000000000000000002" + + New-Item -ItemType Directory -Path $testDir -Force | Out-Null + + # Version manifest + $content = Get-Content "tools/cfl/packaging/winget/OpenCLICollective.cfl.yaml" -Raw + $content = $content -replace "0\.0\.0", $testVersion + Set-Content "$testDir/OpenCLICollective.cfl.yaml" $content -Encoding UTF8 + + # Locale manifest + $content = Get-Content "tools/cfl/packaging/winget/OpenCLICollective.cfl.locale.en-US.yaml" -Raw + $content = $content -replace "0\.0\.0", $testVersion + Set-Content "$testDir/OpenCLICollective.cfl.locale.en-US.yaml" $content -Encoding UTF8 + + # Installer manifest + $content = Get-Content "tools/cfl/packaging/winget/OpenCLICollective.cfl.installer.yaml" -Raw + $content = $content -replace "0\.0\.0", $testVersion + $regex = [regex]"0{64}" + $content = $regex.Replace($content, $testHash1, 1) + $content = $regex.Replace($content, $testHash2, 1) + Set-Content "$testDir/OpenCLICollective.cfl.installer.yaml" $content -Encoding UTF8 + + Write-Host "Validating cfl winget manifest..." + winget validate --manifest $testDir/ + if ($LASTEXITCODE -ne 0) { + Write-Error "Manifest validation failed" + exit 1 + } + Write-Host "Manifest validation passed!" test-jtk: runs-on: windows-latest steps: - uses: actions/checkout@v4 - - name: Validate manifests + - name: Validate manifest schema + shell: pwsh run: | - # winget is pre-installed on windows-latest - winget validate tools/jtk/packaging/winget/ + $testDir = "winget-validate-test" + $testVersion = "0.0.1" + $testHash1 = "0000000000000000000000000000000000000000000000000000000000000001" + $testHash2 = "0000000000000000000000000000000000000000000000000000000000000002" + + New-Item -ItemType Directory -Path $testDir -Force | Out-Null + + # Version manifest + $content = Get-Content "tools/jtk/packaging/winget/OpenCLICollective.jira-ticket-cli.yaml" -Raw + $content = $content -replace "0\.0\.0", $testVersion + Set-Content "$testDir/OpenCLICollective.jira-ticket-cli.yaml" $content -Encoding UTF8 + + # Locale manifest + $content = Get-Content "tools/jtk/packaging/winget/OpenCLICollective.jira-ticket-cli.locale.en-US.yaml" -Raw + $content = $content -replace "0\.0\.0", $testVersion + Set-Content "$testDir/OpenCLICollective.jira-ticket-cli.locale.en-US.yaml" $content -Encoding UTF8 + + # Installer manifest + $content = Get-Content "tools/jtk/packaging/winget/OpenCLICollective.jira-ticket-cli.installer.yaml" -Raw + $content = $content -replace "0\.0\.0", $testVersion + $regex = [regex]"0{64}" + $content = $regex.Replace($content, $testHash1, 1) + $content = $regex.Replace($content, $testHash2, 1) + Set-Content "$testDir/OpenCLICollective.jira-ticket-cli.installer.yaml" $content -Encoding UTF8 + + Write-Host "Validating jtk winget manifest..." + winget validate --manifest $testDir/ + if ($LASTEXITCODE -ne 0) { + Write-Error "Manifest validation failed" + exit 1 + } + Write-Host "Manifest validation passed!"