Add Homebrew tap support (formula + script) #15
Workflow file for this run
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
| # ============================================================================== | |
| # .github/workflows/release.yml — cpp-gen | |
| # ============================================================================== | |
| # Release pipeline. Triggered automatically when a tag in the format | |
| # vX.Y.Z is pushed to the repository (e.g.: via `make release` or scripts/release.sh). | |
| # | |
| # Full flow: | |
| # git commit → tag vX.Y.Z → this workflow | |
| # ↓ | |
| # goreleaser → binaries + archives + GitHub Release (always) | |
| # ↓ | |
| # Publish to AUR (only if AUR_KEY is set) | |
| # ↓ | |
| # Publish to Homebrew tap (only if HOMEBREW_TAP_GITHUB_TOKEN is set) | |
| # | |
| # ── AUR_KEY secret ──────────────────────────────────────────────────────────── | |
| # Store the raw content of your AUR SSH private key as the AUR_KEY secret. | |
| # The key must have NO passphrase. To verify/strip the passphrase locally: | |
| # | |
| # ssh-keygen -p -N "" -f ~/.ssh/aur | |
| # | |
| # Then go to: Settings → Secrets and variables → Actions → AUR_KEY → Update | |
| # and paste the full content of ~/.ssh/aur (including BEGIN/END lines). | |
| # | |
| # ── HOMEBREW_TAP_GITHUB_TOKEN secret ────────────────────────────────────────── | |
| # A GitHub Personal Access Token (classic or fine-grained) with write access | |
| # to the matpdev/homebrew-tap repository. | |
| # | |
| # Required scopes (classic PAT): repo | |
| # Fine-grained PAT: Contents → Read and Write on the homebrew-tap repo. | |
| # | |
| # Create at: https://github.com/settings/tokens | |
| # Then add as: Settings → Secrets and variables → Actions → HOMEBREW_TAP_GITHUB_TOKEN | |
| # ============================================================================== | |
| name: Release | |
| on: | |
| push: | |
| tags: | |
| - "v[0-9]+.[0-9]+.[0-9]+" # v1.2.3 | |
| - "v[0-9]+.[0-9]+.[0-9]+-*" # v1.2.3-beta.1 (pre-release) | |
| permissions: | |
| contents: write | |
| packages: write | |
| jobs: | |
| # ── Release ────────────────────────────────────────────────────────────────── | |
| release: | |
| name: Release ${{ github.ref_name }} | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Setup Go | |
| uses: actions/setup-go@v5 | |
| with: | |
| go-version-file: go.mod | |
| cache: true | |
| - name: Verify dependencies | |
| run: | | |
| go mod verify | |
| go mod tidy | |
| git diff --exit-code go.mod go.sum | |
| - name: Test | |
| run: go test -race ./... | |
| - name: Set goreleaser skip flags | |
| id: goreleaser_skip | |
| env: | |
| HOMEBREW_TOKEN: ${{ secrets.HOMEBREW_TAP_GITHUB_TOKEN }} | |
| run: | | |
| SKIP="aur" | |
| if [ -z "$HOMEBREW_TOKEN" ]; then | |
| SKIP="${SKIP},brew" | |
| echo "::warning title=HOMEBREW_TAP_GITHUB_TOKEN ausente::Publicação no Homebrew ignorada." | |
| fi | |
| echo "flags=${SKIP}" >> "$GITHUB_OUTPUT" | |
| # ── Goreleaser (GitHub Release + Homebrew if token set — AUR handled below) ── | |
| - name: Run goreleaser | |
| uses: goreleaser/goreleaser-action@v6 | |
| with: | |
| distribution: goreleaser | |
| version: "~> v2" | |
| args: release --clean --skip=${{ steps.goreleaser_skip.outputs.flags }} | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| HOMEBREW_TAP_GITHUB_TOKEN: ${{ secrets.HOMEBREW_TAP_GITHUB_TOKEN }} | |
| # ── AUR publish ─────────────────────────────────────────────────────────── | |
| # Checks whether AUR_KEY is set and writes it to disk via Python, | |
| # auto-detecting raw PEM or base64-encoded content. | |
| - name: Prepare AUR key | |
| id: aur | |
| env: | |
| AUR_KEY: ${{ secrets.AUR_KEY }} | |
| run: | | |
| if [ -z "$AUR_KEY" ]; then | |
| echo "has_key=false" >> "$GITHUB_OUTPUT" | |
| echo "::warning title=AUR_KEY ausente::Publicação no AUR ignorada." | |
| exit 0 | |
| fi | |
| mkdir -p ~/.ssh | |
| chmod 700 ~/.ssh | |
| # Write key via Python: handles raw PEM and base64, normalises line endings | |
| python3 << 'PYEOF' | |
| import os, base64, sys | |
| raw = os.environ["AUR_KEY"] | |
| # Normalise CRLF | |
| raw = raw.replace("\r\n", "\n").replace("\r", "\n").strip() | |
| # Auto-detect base64: single line with no PEM header | |
| if "\n" not in raw and not raw.startswith("---"): | |
| try: | |
| raw = base64.b64decode(raw).decode("utf-8").strip() | |
| print("INFO: AUR_KEY decoded from base64") | |
| except Exception: | |
| pass # treat as raw | |
| raw += "\n" # ensure trailing newline | |
| path = os.path.expanduser("~/.ssh/aur_key") | |
| with open(path, "w") as f: | |
| f.write(raw) | |
| os.chmod(path, 0o600) | |
| lines = raw.splitlines() | |
| print(f"INFO: key first line : {lines[0]}") | |
| print(f"INFO: key last line : {lines[-1]}") | |
| print(f"INFO: key line count : {len(lines)}") | |
| PYEOF | |
| # Strip passphrase (no-op if already empty; fails silently if passphrase set) | |
| ssh-keygen -p -N "" -f ~/.ssh/aur_key < /dev/null 2>/dev/null \ | |
| && echo "INFO: key reformatted (passphrase cleared)" \ | |
| || echo "INFO: key reformat skipped" | |
| if ! ssh-keygen -y -f ~/.ssh/aur_key > /dev/null 2>&1; then | |
| echo "::error title=AUR_KEY inválida::Não foi possível extrair a chave pública." | |
| echo "::error title=AUR_KEY inválida::Verifique se a chave não tem passphrase e está no formato OpenSSH." | |
| echo "has_key=false" >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| fi | |
| echo "has_key=true" >> "$GITHUB_OUTPUT" | |
| # webfactory/ssh-agent loads the key into the SSH agent via Node.js, | |
| # bypassing the OpenSSH/libcrypto file-loading path that fails on | |
| # some runner configurations. | |
| - name: Start SSH agent for AUR | |
| if: steps.aur.outputs.has_key == 'true' | |
| uses: webfactory/ssh-agent@v0.9.1 | |
| with: | |
| ssh-private-key: ${{ secrets.AUR_KEY }} | |
| - name: Publish to AUR | |
| if: steps.aur.outputs.has_key == 'true' | |
| env: | |
| GIT_AUTHOR_NAME: goreleaserbot | |
| GIT_AUTHOR_EMAIL: bot@goreleaser.com | |
| GIT_COMMITTER_NAME: goreleaserbot | |
| GIT_COMMITTER_EMAIL: bot@goreleaser.com | |
| run: | | |
| ssh-keyscan -H aur.archlinux.org >> ~/.ssh/known_hosts 2>/dev/null | |
| VERSION="${GITHUB_REF_NAME#v}" | |
| SHA_X86_64=$(grep "linux_amd64.tar.gz" dist/checksums.txt | awk '{print $1}') | |
| SHA_I686=$(grep "linux_386.tar.gz" dist/checksums.txt | awk '{print $1}') | |
| if [ -z "$SHA_X86_64" ] || [ -z "$SHA_I686" ]; then | |
| echo "::error::Checksums não encontrados em dist/checksums.txt" | |
| exit 1 | |
| fi | |
| # Clone AUR repo (empty repo warning is expected on first push) | |
| git -c init.defaultBranch=master \ | |
| clone ssh://aur@aur.archlinux.org/cpp-gen-bin.git /tmp/aur-cpp-gen-bin | |
| # Generate PKGBUILD with real version and checksums | |
| sed \ | |
| -e "s/^pkgver=.*/pkgver=${VERSION}/" \ | |
| -e "s/^pkgrel=.*/pkgrel=1/" \ | |
| -e "s/sha256sums_x86_64=('SKIP')/sha256sums_x86_64=('${SHA_X86_64}')/" \ | |
| -e "s/sha256sums_i686=('SKIP')/sha256sums_i686=('${SHA_I686}')/" \ | |
| aur/PKGBUILD > /tmp/aur-cpp-gen-bin/PKGBUILD | |
| # Generate .SRCINFO (printf \t avoids literal tabs in YAML) | |
| { | |
| printf 'pkgbase = cpp-gen-bin\n' | |
| printf '\tpkgdesc = Modern C++ project generator with CMake, package managers, IDE configurations and development tools\n' | |
| printf '\tpkgver = %s\n' "${VERSION}" | |
| printf '\tpkgrel = 1\n' | |
| printf '\turl = https://github.com/matpdev/cpp-gen\n' | |
| printf '\tarch = x86_64\n' | |
| printf '\tarch = i686\n' | |
| printf '\tlicense = MIT\n' | |
| printf '\tprovides = cpp-gen\n' | |
| printf '\tconflicts = cpp-gen\n' | |
| printf '\toptions = !strip\n' | |
| printf '\tsource_x86_64 = cpp-gen-bin-%s-x86_64.tar.gz::https://github.com/matpdev/cpp-gen/releases/download/v%s/cpp-gen_%s_linux_amd64.tar.gz\n' "${VERSION}" "${VERSION}" "${VERSION}" | |
| printf '\tsha256sums_x86_64 = %s\n' "${SHA_X86_64}" | |
| printf '\tsource_i686 = cpp-gen-bin-%s-i686.tar.gz::https://github.com/matpdev/cpp-gen/releases/download/v%s/cpp-gen_%s_linux_386.tar.gz\n' "${VERSION}" "${VERSION}" "${VERSION}" | |
| printf '\tsha256sums_i686 = %s\n' "${SHA_I686}" | |
| printf '\n' | |
| printf 'pkgname = cpp-gen-bin\n' | |
| } > /tmp/aur-cpp-gen-bin/.SRCINFO | |
| cp aur/LICENSE /tmp/aur-cpp-gen-bin/LICENSE | |
| cd /tmp/aur-cpp-gen-bin | |
| git add PKGBUILD .SRCINFO LICENSE | |
| git diff --staged --quiet && echo "Nothing to commit." && exit 0 | |
| git commit -m "Update to v${VERSION}" | |
| git push origin master | |
| # ── Notify ─────────────────────────────────────────────────────────────────── | |
| notify: | |
| name: Notify | |
| runs-on: ubuntu-latest | |
| needs: release | |
| if: always() | |
| steps: | |
| - name: Release succeeded | |
| if: needs.release.result == 'success' | |
| run: | | |
| echo "::notice title=Release publicada::cpp-gen ${{ github.ref_name }} publicada com sucesso!" | |
| echo "URL: https://github.com/${{ github.repository }}/releases/tag/${{ github.ref_name }}" | |
| - name: Release failed | |
| if: needs.release.result == 'failure' | |
| run: | | |
| echo "::error title=Falha na release::goreleaser falhou para ${{ github.ref_name }}." | |
| exit 1 |