Skip to content

Add Homebrew tap support (formula + script) #15

Add Homebrew tap support (formula + script)

Add Homebrew tap support (formula + script) #15

Workflow file for this run

# ==============================================================================
# .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