feat: support cask upgrades (#111) #26
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 | |
| on: | |
| push: | |
| branches: [main] | |
| workflow_dispatch: | |
| inputs: | |
| version: | |
| description: 'Override version (e.g. 1.2.3). Leave empty for auto-detection.' | |
| required: false | |
| type: string | |
| permissions: | |
| contents: write | |
| jobs: | |
| version: | |
| runs-on: ubuntu-latest | |
| outputs: | |
| version: ${{ steps.calc.outputs.version }} | |
| skip: ${{ steps.calc.outputs.skip }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Calculate version from conventional commits | |
| id: calc | |
| run: | | |
| set -euo pipefail | |
| # Manual override takes precedence | |
| if [[ -n "${OVERRIDE_VERSION}" ]]; then | |
| echo "version=${OVERRIDE_VERSION}" >> "$GITHUB_OUTPUT" | |
| echo "skip=false" >> "$GITHUB_OUTPUT" | |
| echo "Using manual override: v${OVERRIDE_VERSION}" | |
| exit 0 | |
| fi | |
| # Get latest tag, default to v0.0.0 if none exist | |
| LATEST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0") | |
| CURRENT=${LATEST_TAG#v} | |
| IFS='.' read -r MAJOR MINOR PATCH <<< "$CURRENT" | |
| echo "Latest tag: ${LATEST_TAG} (${MAJOR}.${MINOR}.${PATCH})" | |
| # Get commit subjects since last tag | |
| if [[ "$LATEST_TAG" == "v0.0.0" ]]; then | |
| SUBJECTS=$(git log --pretty=format:"%s") | |
| BODIES=$(git log --pretty=format:"%b") | |
| else | |
| SUBJECTS=$(git log "${LATEST_TAG}..HEAD" --pretty=format:"%s") | |
| BODIES=$(git log "${LATEST_TAG}..HEAD" --pretty=format:"%b") | |
| fi | |
| if [[ -z "$SUBJECTS" ]]; then | |
| echo "No commits since last tag — skipping release" | |
| echo "skip=true" >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| fi | |
| echo "Commits since ${LATEST_TAG}:" | |
| echo "$SUBJECTS" | sed 's/^/ /' | |
| # Collect candidate conventional-commit lines from both subjects | |
| # and body bullets. GitHub squash-merges put the PR title in the | |
| # subject and nest each original commit as "* type: ..." in the | |
| # body, so scanning subjects alone misses squash-merged PRs whose | |
| # title is not itself a conventional commit. | |
| CANDIDATES=$( | |
| printf '%s\n' "$SUBJECTS" | |
| printf '%s\n' "$BODIES" | sed -nE 's/^[[:space:]]*\*[[:space:]]+//p' | |
| ) | |
| # Determine bump type from conventional commits | |
| # Priority: major > minor > patch > none | |
| BUMP="none" | |
| # Check bodies for BREAKING CHANGE footer | |
| if echo "$BODIES" | grep -qE "^BREAKING[ -]CHANGE:"; then | |
| BUMP="major" | |
| fi | |
| while IFS= read -r msg; do | |
| # type(scope)!: description → major | |
| if echo "$msg" | grep -qE '^[a-z]+(\(.+\))?!:'; then | |
| BUMP="major" | |
| fi | |
| # feat → minor (unless already major) | |
| if echo "$msg" | grep -qE '^feat(\(.+\))?:'; then | |
| [[ "$BUMP" == "none" || "$BUMP" == "patch" ]] && BUMP="minor" | |
| fi | |
| # fix, perf, refactor → patch | |
| if echo "$msg" | grep -qE '^(fix|perf|refactor)(\(.+\))?:'; then | |
| [[ "$BUMP" == "none" ]] && BUMP="patch" | |
| fi | |
| done <<< "$CANDIDATES" | |
| if [[ "$BUMP" == "none" ]]; then | |
| echo "No releasable commits (only docs/ci/chore/etc.) — skipping release" | |
| echo "skip=true" >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| fi | |
| # Calculate next version | |
| case "$BUMP" in | |
| major) NEXT="$((MAJOR + 1)).0.0" ;; | |
| minor) NEXT="${MAJOR}.$((MINOR + 1)).0" ;; | |
| patch) NEXT="${MAJOR}.${MINOR}.$((PATCH + 1))" ;; | |
| esac | |
| echo "Bump type: ${BUMP} → v${NEXT}" | |
| echo "version=${NEXT}" >> "$GITHUB_OUTPUT" | |
| echo "skip=false" >> "$GITHUB_OUTPUT" | |
| env: | |
| OVERRIDE_VERSION: ${{ inputs.version }} | |
| build: | |
| needs: version | |
| if: needs.version.outputs.skip != 'true' | |
| strategy: | |
| matrix: | |
| include: | |
| - target: aarch64-macos | |
| name: darwin-aarch64 | |
| - target: x86_64-macos | |
| name: darwin-x86_64 | |
| runs-on: macos-14 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: mlugg/setup-zig@v2 | |
| with: | |
| version: 0.15.2 | |
| - name: Run tests | |
| if: matrix.target == 'aarch64-macos' | |
| run: zig build test -Dversion=${{ needs.version.outputs.version }} | |
| - name: Build release binary | |
| run: zig build -Doptimize=ReleaseFast -Dtarget=${{ matrix.target }} -Dversion=${{ needs.version.outputs.version }} | |
| - name: Rename binary | |
| run: mv zig-out/bin/bru bru-${{ matrix.name }} | |
| - uses: actions/upload-artifact@v4 | |
| with: | |
| name: bru-${{ matrix.name }} | |
| path: bru-${{ matrix.name }} | |
| release: | |
| needs: [version, build] | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/download-artifact@v4 | |
| with: | |
| path: artifacts | |
| merge-multiple: true | |
| - name: Create release | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| chmod +x artifacts/bru-* | |
| gh release create "v${{ needs.version.outputs.version }}" \ | |
| --title "v${{ needs.version.outputs.version }}" \ | |
| --generate-notes \ | |
| artifacts/bru-darwin-aarch64 \ | |
| artifacts/bru-darwin-x86_64 | |
| deploy-pages: | |
| needs: release | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Deploy to GitHub Pages | |
| uses: peaceiris/actions-gh-pages@v4 | |
| with: | |
| github_token: ${{ secrets.GITHUB_TOKEN }} | |
| publish_dir: ./pages | |
| force_orphan: true |