v0.2.2 #65
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Release | |
| run-name: ${{ inputs.tag_name }} | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref_name }} | |
| cancel-in-progress: true | |
| permissions: | |
| contents: write | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| tag_name: | |
| required: true | |
| type: string | |
| description: "Release tag (e.g. v0.1.0)" | |
| jobs: | |
| validate-tag: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Validate tag format | |
| env: | |
| TAG_NAME: ${{ inputs.tag_name }} | |
| run: | | |
| if [[ ! "$TAG_NAME" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then | |
| echo "Invalid tag format. Must be v1.2.3" | |
| exit 1 | |
| fi | |
| # ── Job 1: Build MSI on Windows ────────────────────────────────────── | |
| build-msi: | |
| needs: validate-tag | |
| runs-on: windows-2022 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Set up Go | |
| uses: actions/setup-go@v5 | |
| with: | |
| go-version-file: 'go.mod' | |
| - name: Build Windows binary | |
| env: | |
| TAG_NAME: ${{ inputs.tag_name }} | |
| shell: pwsh | |
| run: | | |
| $VERSION = $env:TAG_NAME -replace '^v', '' | |
| $env:GOOS = "windows" | |
| $env:GOARCH = "amd64" | |
| $env:CGO_ENABLED = "0" | |
| go build ` | |
| -ldflags "-s -w -X main.version=$VERSION -X main.commit=$env:GITHUB_SHA" ` | |
| -o build/windows/amd64/pgxcli.exe ` | |
| ./cmd/pgxcli | |
| - name: Set up MSBuild | |
| id: setupmsbuild | |
| uses: microsoft/setup-msbuild@v2 | |
| - name: Build MSI (x64) | |
| env: | |
| TAG_NAME: ${{ inputs.tag_name }} | |
| shell: pwsh | |
| run: | | |
| $VERSION = $env:TAG_NAME -replace '^v', '' | |
| $MSBUILD = "${{ steps.setupmsbuild.outputs.msbuildPath }}\MSBuild.exe" | |
| & $MSBUILD build/windows/pgxcli.wixproj ` | |
| -p:Configuration=Release ` | |
| -p:Platform=x64 ` | |
| -p:SourceDir="$PWD\build\windows\amd64\" ` | |
| -p:OutputPath="$PWD\dist" ` | |
| -p:OutputName="pgxcli_${VERSION}_windows_amd64" ` | |
| -p:ProductVersion="$VERSION" | |
| - name: Upload MSI artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: windows-msi | |
| if-no-files-found: error | |
| retention-days: 7 | |
| path: dist/*.msi | |
| # ── Job 2: GoReleaser draft release ────────────────────────────────── | |
| goreleaser: | |
| needs: validate-tag | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Set up Go | |
| uses: actions/setup-go@v5 | |
| with: | |
| go-version-file: 'go.mod' | |
| - name: Install GoReleaser | |
| uses: goreleaser/goreleaser-action@v6 | |
| with: | |
| version: v2.13.1 | |
| install-only: true | |
| - name: Extract release notes | |
| env: | |
| TAG_NAME: ${{ inputs.tag_name }} | |
| run: | | |
| VERSION="${TAG_NAME#v}" # strip the 'v' → 0.1.0 | |
| # Escape dots so awk treats them as literals, not regex wildcards | |
| ESCAPED_VERSION=$(echo "$VERSION" | sed 's/\./\\./g') | |
| awk "/^## \[${ESCAPED_VERSION}\]/{found=1; next} /^## \[/{if(found) exit} found{print}" \ | |
| CHANGELOG.md \ | |
| | sed -e '/./,$!d' -e ':a;/^\n*$/{$d;N;ba}' \ | |
| > /tmp/release_notes.md | |
| if [ ! -s /tmp/release_notes.md ]; then | |
| echo "ERROR: No release notes found for version $VERSION in CHANGELOG.md" | |
| echo "Available versions:" | |
| grep '^## \[' CHANGELOG.md | |
| exit 1 | |
| fi | |
| echo "--- Release notes preview ---" | |
| cat /tmp/release_notes.md | |
| - name: Create temporary tag | |
| env: | |
| TAG_NAME: ${{ inputs.tag_name }} | |
| run: git tag "$TAG_NAME" | |
| - name: Run GoReleaser (creates draft) | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }} | |
| DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }} | |
| run: | | |
| # Set up docker buildx for multi-arch builds | |
| docker buildx create --name=goreleaser --use | |
| docker run --privileged --rm tonistiigi/binfmt --install all | |
| # Log in to GitHub Container Registry | |
| echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin | |
| # Log in to Docker Hub (if secrets are provided) | |
| if [ -n "$DOCKER_USERNAME" ] && [ -n "$DOCKER_PASSWORD" ]; then | |
| echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin | |
| fi | |
| goreleaser release --clean --fail-fast --release-notes /tmp/release_notes.md | |
| # ── Job 3: Upload MSI to draft + publish ───────────────────────────── | |
| publish: | |
| needs: [build-msi, goreleaser] | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Download MSI artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: windows-msi | |
| path: dist/ | |
| - name: Upload MSI to draft release + publish | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| TAG_NAME: ${{ inputs.tag_name }} | |
| run: | | |
| # Re-extract release notes so gh doesn't wipe the body on edit | |
| VERSION="${TAG_NAME#v}" | |
| ESCAPED_VERSION=$(echo "$VERSION" | sed 's/\./\\./g') | |
| awk "/^## \[${ESCAPED_VERSION}\]/{found=1; next} /^## \[/{if(found) exit} found{print}" \ | |
| CHANGELOG.md \ | |
| | sed -e '/./,$!d' -e ':a;/^\n*$/{$d;N;ba}' \ | |
| > /tmp/release_notes.md | |
| # upload MSI to the existing draft release | |
| gh release upload "$TAG_NAME" dist/*.msi | |
| # publish the draft, preserving the release body | |
| gh release edit "$TAG_NAME" --draft=false --notes-file /tmp/release_notes.md |