vx 0.4.1

Universal Development Tool Manager
Documentation
name: Package Managers

# Publish to various package managers using pre-built artifacts
# Downloads binaries from GitHub Release (built by tag-release-assets.yml)
# No building - only packaging and distribution

on:
  workflow_run:
    workflows: ["Tag Release Assets"]
    types:
      - completed
  workflow_dispatch:
    inputs:
      version:
        description: 'Version to publish (e.g., v1.0.0)'
        required: true
        type: string
      force_run:
        description: 'Force run even if Release workflow failed'
        required: false
        default: false
        type: boolean

permissions:
  contents: read

jobs:
  # Only run if the Release workflow was successful or forced
  check-release:
    runs-on: ubuntu-latest
    if: github.event.workflow_run.conclusion == 'success' || github.event_name == 'workflow_dispatch'
    outputs:
      should-publish: ${{ steps.check.outputs.should-publish }}
      version: ${{ steps.version.outputs.version }}
    steps:
      - name: Debug workflow event
        run: |
          echo "Event name: ${{ github.event_name }}"
          echo "Workflow run conclusion: ${{ github.event.workflow_run.conclusion }}"
          echo "Workflow run head branch: ${{ github.event.workflow_run.head_branch }}"
          echo "Force run input: ${{ github.event.inputs.force_run }}"

      - name: Check if should publish
        id: check
        run: |
          if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
            echo "Manual dispatch - will publish"
            echo "should-publish=true" >> $GITHUB_OUTPUT
          elif [[ "${{ github.event.inputs.force_run }}" == "true" ]]; then
            echo "Force run enabled - will publish"
            echo "should-publish=true" >> $GITHUB_OUTPUT
          elif [[ "${{ github.event.workflow_run.conclusion }}" == "success" ]]; then
            echo "Release workflow successful - will publish"
            echo "should-publish=true" >> $GITHUB_OUTPUT
          else
            echo "Release workflow failed or conditions not met - will not publish"
            echo "should-publish=false" >> $GITHUB_OUTPUT
          fi

      - name: Get version
        id: version
        run: |
          if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
            echo "version=${{ github.event.inputs.version }}" >> $GITHUB_OUTPUT
          else
            # Get the latest release tag from GitHub API
            echo "Getting latest release version from GitHub API..."
            latest_release=$(curl -s -H "Accept: application/vnd.github.v3+json" \
              "https://api.github.com/repos/loonghao/vx/releases/latest" | \
              jq -r '.tag_name // empty')

            if [[ -n "$latest_release" && "$latest_release" != "null" ]]; then
              echo "Found latest release: $latest_release"
              echo "version=$latest_release" >> $GITHUB_OUTPUT
            else
              echo "No release found, trying to get from workflow run..."
              version="${{ github.event.workflow_run.head_branch }}"
              if [[ "$version" =~ ^v[0-9]+\.[0-9]+\.[0-9]+ ]]; then
                echo "version=$version" >> $GITHUB_OUTPUT
              else
                echo "version=unknown" >> $GITHUB_OUTPUT
              fi
            fi
          fi

      - name: Verify GitHub Release exists
        run: |
          version="${{ steps.version.outputs.version }}"
          echo "Checking if GitHub Release exists for version: $version"

          # Check if release exists
          release_url="https://api.github.com/repos/loonghao/vx/releases/tags/$version"
          if curl -s -f -H "Accept: application/vnd.github.v3+json" "$release_url" > /dev/null; then
            echo "✅ GitHub Release found for $version"

            # List available assets
            echo "📦 Available release assets:"
            curl -s -H "Accept: application/vnd.github.v3+json" "$release_url" | \
              jq -r '.assets[] | "  - \(.name) (\(.size) bytes)"'
          else
            echo "❌ GitHub Release not found for $version"
            echo "Please ensure the Release workflow completed successfully"
            exit 1
          fi

  # Publish to Windows Package Manager (WinGet)
  # WinGet automatically detects new GitHub releases, no manual upload needed
  publish-winget:
    needs: check-release
    runs-on: windows-latest
    if: needs.check-release.outputs.should-publish == 'true'
    steps:
      - name: Publish to WinGet
        uses: vedantmgoyal9/winget-releaser@main
        with:
          identifier: loonghao.vx
          max-versions-to-keep: 5
          token: ${{ secrets.WINGET_TOKEN }}
          # WinGet automatically uses GitHub release assets

  # Publish to Chocolatey
  # Downloads release assets and creates Chocolatey package
  publish-chocolatey:
    needs: check-release
    runs-on: windows-latest
    if: needs.check-release.outputs.should-publish == 'true'
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Download Windows binary from release
        run: |
          # Download pre-built binary from GitHub Release (built by tag-release-assets.yml)
          $version = "${{ needs.check-release.outputs.version }}"
          $downloadUrl = "https://github.com/loonghao/vx/releases/download/$version/vx-windows-x64.zip"
          Write-Host "Downloading pre-built binary from: $downloadUrl"

          try {
            # Download the zip file
            Invoke-WebRequest -Uri $downloadUrl -OutFile "vx-windows-x64.zip" -ErrorAction Stop
            Write-Host "Downloaded zip size: $((Get-Item vx-windows-x64.zip).Length) bytes"

            # Extract the exe from zip
            Expand-Archive -Path "vx-windows-x64.zip" -DestinationPath "." -Force

            # Find the vx.exe file (it might be in a subdirectory)
            $exeFile = Get-ChildItem -Recurse -Name "vx.exe" | Select-Object -First 1
            if ($exeFile) {
              Copy-Item $exeFile "vx.exe"
              Write-Host "Extracted vx.exe size: $((Get-Item vx.exe).Length) bytes"
            } else {
              Write-Host "vx.exe not found in the zip file"
              Write-Host "Contents of zip:"
              Get-ChildItem -Recurse | ForEach-Object { Write-Host "  - $($_.FullName)" }
              exit 1
            }
          } catch {
            Write-Host "Failed to download or extract binary: $_"
            Write-Host "Available releases:"
            $releases = Invoke-RestMethod -Uri "https://api.github.com/repos/loonghao/vx/releases"
            $releases | ForEach-Object { Write-Host "  - $($_.tag_name)" }
            exit 1
          }

      - name: Create Chocolatey package
        run: |
          $version = "${{ needs.check-release.outputs.version }}"

          # Create chocolatey package structure
          New-Item -ItemType Directory -Force -Path "chocolatey/tools"
          Copy-Item "vx.exe" "chocolatey/tools/"

          # Update nuspec file with current version
          $nuspecContent = Get-Content "chocolatey/vx.nuspec" -Raw
          $nuspecContent = $nuspecContent -replace "{{VERSION}}", $version.TrimStart('v')
          $nuspecContent = $nuspecContent -replace "{{RELEASE_NOTES}}", "See https://github.com/loonghao/vx/releases/tag/$version"
          Set-Content "chocolatey/vx.nuspec" $nuspecContent

          # Build package
          choco pack chocolatey/vx.nuspec --outputdirectory .

          Write-Host "Created Chocolatey package for version $version"
          Get-ChildItem *.nupkg | ForEach-Object { Write-Host "Package: $($_.Name)" }

      - name: Publish to Chocolatey
        run: |
          $nupkgFile = Get-ChildItem *.nupkg | Select-Object -First 1
          if ($nupkgFile) {
            Write-Host "Publishing $($nupkgFile.Name) to Chocolatey..."
            choco push $nupkgFile.Name --source https://push.chocolatey.org/ --api-key ${{ secrets.CHOCOLATEY_API_KEY }}
          } else {
            Write-Host "No .nupkg file found!"
            exit 1
          }

  # Publish to Homebrew
  # Automatically creates formula using GitHub release assets
  publish-homebrew:
    needs: check-release
    runs-on: ubuntu-latest
    if: needs.check-release.outputs.should-publish == 'true'
    steps:
      - name: Publish to Homebrew
        uses: Justintime50/homebrew-releaser@v2
        with:
          homebrew_owner: loonghao
          homebrew_tap: homebrew-vx
          github_token: ${{ secrets.HOMEBREW_TAP_GITHUB_TOKEN }}
          commit_owner: vx-bot
          commit_email: vx-bot@users.noreply.github.com
          install: 'bin.install "vx"'
          test: 'assert_match("vx", shell_output("#{bin}/vx --version"))'
          target_darwin_amd64: true
          target_darwin_arm64: true
          target_linux_amd64: true
          # Automatically uses GitHub release assets:
          # - vx-macos-x64 for Darwin x86_64
          # - vx-macos-arm64 for Darwin ARM64
          # - vx-linux-x64 for Linux x86_64

  # Publish to Scoop (Custom implementation)
  publish-scoop:
    needs: check-release
    runs-on: ubuntu-latest
    if: needs.check-release.outputs.should-publish == 'true'
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Update Scoop Bucket
        uses: Ash258/Scoop-GithubActions@stable
        with:
          bucket_repository: loonghao/scoop-vx
          app_name: vx
          github_token: ${{ secrets.SCOOP_BUCKET_TOKEN }}
          # Automatically generates manifest from GitHub release

  # Summary job
  publish-summary:
    needs: [check-release, publish-winget, publish-chocolatey, publish-homebrew, publish-scoop]
    runs-on: ubuntu-latest
    if: always() && needs.check-release.outputs.should-publish == 'true'
    steps:
      - name: Publish Summary
        run: |
          echo "📦 Package Manager Publishing Summary"
          echo "Version: ${{ needs.check-release.outputs.version }}"
          echo ""
          echo "🪟 WinGet: ${{ needs.publish-winget.result }}"
          echo "🍫 Chocolatey: ${{ needs.publish-chocolatey.result }}"
          echo "🍺 Homebrew: ${{ needs.publish-homebrew.result }}"
          echo "🥄 Scoop: ${{ needs.publish-scoop.result }}"
          echo ""
          if [[ "${{ needs.publish-winget.result }}" == "success" && "${{ needs.publish-chocolatey.result }}" == "success" && "${{ needs.publish-homebrew.result }}" == "success" ]]; then
            echo "✅ All package managers published successfully!"
          else
            echo "⚠️ Some package managers failed to publish. Check the logs above."
          fi