diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d9bf791..edb1af6 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -131,6 +131,78 @@ jobs: name: dims-linux-${{ matrix.targetarch }} path: build/dims-linux-${{ matrix.targetarch }}.zip + build-macos: + name: Build macOS + strategy: + fail-fast: false + matrix: + include: + - { arch: arm64, os: macos-latest } + - { arch: amd64, os: macos-15-intel } + + runs-on: ${{ matrix.os }} + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Compute the release version + run: | + if [[ "${GITHUB_REF}" == refs/tags/* ]]; then + echo "RELEASE_VERSION=${GITHUB_REF_NAME#v}" >> "$GITHUB_ENV" + else + echo "RELEASE_VERSION=$(git rev-parse --short=8 HEAD)" >> "$GITHUB_ENV" + fi + + - name: Install libvips + run: brew install vips + + - uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: '21' + + # The same jar the builder image uses, so the generated parser matches + # the one every other target is built from. + - name: Install ANTLR + run: | + sudo mkdir -p /usr/local/lib + sudo curl -fsSL -o /usr/local/lib/antlr.jar \ + https://www.antlr.org/download/antlr-4.13.2-complete.jar + printf '#!/bin/sh\nexec java -jar /usr/local/lib/antlr.jar "$@"\n' \ + | sudo tee /usr/local/bin/antlr >/dev/null + sudo chmod +x /usr/local/bin/antlr + + - uses: actions/setup-go@v5 + with: + go-version-file: go.mod + + # make all links libvips dynamically. The static flags in make static are + # for GNU ld and do not apply here, so the formula depends on vips. + - name: Build + run: make all VERSION="$RELEASE_VERSION" + env: + PKG_CONFIG_PATH: /opt/homebrew/lib/pkgconfig:/usr/local/lib/pkgconfig + + - name: Check the version reaches the binary + run: | + actual="$(./build/dims version)" + test "$actual" = "$RELEASE_VERSION" || { + echo "want $RELEASE_VERSION, got $actual" + exit 1 + } + + - name: Package + run: | + cp LICENSE NOTICE build/ + cd build && zip "dims-macos-${{ matrix.arch }}.zip" dims LICENSE NOTICE + + - name: Upload macOS Binary + uses: actions/upload-artifact@v4 + with: + retention-days: 1 + name: dims-macos-${{ matrix.arch }} + path: build/dims-macos-${{ matrix.arch }}.zip + manifest: name: Push Manifest needs: [build] @@ -169,7 +241,7 @@ jobs: ghcr.io/beetlebugorg/go-dims:${{ env.TRACKING_TAG}}-arm64 release: - needs: [build] + needs: [build, build-macos] name: Release if: ${{ startsWith(github.ref_name, 'v') }} runs-on: ubuntu-latest @@ -204,8 +276,54 @@ jobs: name: dims-linux-amd64 path: ./build + - uses: actions/download-artifact@v4 + with: + name: dims-macos-arm64 + path: ./build + + - uses: actions/download-artifact@v4 + with: + name: dims-macos-amd64 + path: ./build + - name: Upload to GitHub Release run: gh release upload "$TAG_NAME" ./build/lambda-*.zip ./build/dims-*.zip --repo "$GITHUB_REPOSITORY" env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} TAG_NAME: ${{ github.ref_name }} + + homebrew: + name: Update the Homebrew tap + needs: [release] + # A candidate tag such as v1.0.0-rc1 leaves the tap alone. Cut one to + # prove the matrix, then tag the version the tap should carry. + if: ${{ startsWith(github.ref_name, 'v') && !contains(github.ref_name, '-') }} + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - uses: actions/download-artifact@v4 + with: + path: dist + merge-multiple: true + + - name: Update the tap + env: + TAP_TOKEN: ${{ secrets.HOMEBREW_TAP_TOKEN }} + run: | + if [ -z "$TAP_TOKEN" ]; then + echo "::warning::HOMEBREW_TAP_TOKEN is not set, so the tap is unchanged" + exit 0 + fi + version="${GITHUB_REF_NAME#v}" + git clone --depth 1 \ + "https://x-access-token:$TAP_TOKEN@github.com/${{ github.repository_owner }}/homebrew-tap" tap + mkdir -p tap/Formula + scripts/brew-formula.sh "$version" dist > tap/Formula/go-dims.rb + cd tap + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + git add Formula/go-dims.rb + git diff --cached --quiet || git commit -m "go-dims $version" + git push diff --git a/README.md b/README.md index 57901ce..adcadef 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,20 @@ renditions. - Docker: Launch anywhere in seconds. - AWS Lambda: Compile and deploy as a fast, small Lambda function. +## 🍺 Install the CLI + +```bash +brew install beetlebugorg/tap/go-dims +``` + +That installs the `dims` command on macOS and on Linux. Use it to sign URLs and +to run the server: + +```bash +dims sign --key-file=signing-key.txt "http://localhost:8080/v5/resize/200x200/?url=cat.jpg" +dims serve +``` + ## 🚀 Getting Started Run locally in development mode (no signature required): @@ -142,7 +156,7 @@ Use the built-in CLI to generate secure, signed URLs: ❯ cat signing-key.txt 0123456789abcdef0123456789abcdef -❯ ./build/dims sign --key-file=signing-key.txt "http://localhost:8080/v5/resize/200x200/?url=pexels-photo-1539116.jpeg" +❯ dims sign --key-file=signing-key.txt "http://localhost:8080/v5/resize/200x200/?url=pexels-photo-1539116.jpeg" http://localhost:8080/v5/resize/200x200/?sig=95abae1df702bcb894cbcc2625f5b044e9b7af316b02e92483efa7f330968dce&url=pexels-photo-1539116.jpeg ``` diff --git a/docs/docs/installation.md b/docs/docs/installation.md index 2653f6e..12fde29 100644 --- a/docs/docs/installation.md +++ b/docs/docs/installation.md @@ -49,10 +49,37 @@ http://127.0.0.1:8080/v5/resize/100x100/?url=https://images.pexels.com/photos/15 |---|---| | `latest` | The most recent tagged release. Only a release moves it. | | `` | A specific release, for example `0.4.1`. Never moves. | +| `next` | The most recent release candidate, a tag such as `v1.0.0-rc1`. | | `edge` | The most recent rebuild from `main`, published by hand. | | `` | The exact commit a rebuild was made from. Never moves. | -Pin a version in production. `latest` follows releases, and `edge` follows `main`, so both change under you. +Pin a version in production. `latest`, `next`, and `edge` all move, so each one changes under you. + +## 📦 Standalone Binary + +Install the `dims` command with Homebrew, on macOS or on Linux: + +```shell +$ brew install beetlebugorg/tap/go-dims +``` + +Confirm the install: + +```shell +❯ dims version +1.0.0 +``` + +The command runs the server and signs URLs: + +```shell +$ dims serve +$ dims sign --key-file=signing-key.txt "http://localhost:8080/v5/resize/200x200/?url=cat.jpg" +``` + +The formula carries a release candidate only once it becomes a release. A tag such as `v1.0.0-rc1` leaves the tap unchanged. + +Every release also attaches the binary directly. Download `dims--.zip` from the [releases page](https://github.com/beetlebugorg/go-dims/releases), unzip it, and run `dims`. The Linux build is static and needs nothing at run time. The macOS build links libvips, which Homebrew installs for you. ## ☁️ AWS Lambda diff --git a/scripts/brew-formula.sh b/scripts/brew-formula.sh new file mode 100755 index 0000000..3f11ad8 --- /dev/null +++ b/scripts/brew-formula.sh @@ -0,0 +1,67 @@ +#!/usr/bin/env bash +# Print the Homebrew formula for a released version, reading each archive's +# sha256 out of , the zips the release workflow just built. The tap +# job pipes this into Formula/go-dims.rb. +# +# Usage: brew-formula.sh +set -euo pipefail + +version="$1" +dist="$2" + +# The repository the release lives in, so a fork's test release yields a +# formula pointing at the fork's own downloads. +repo="${GITHUB_REPOSITORY:-beetlebugorg/go-dims}" +base="https://github.com/$repo/releases/download/v$version" + +sha() { shasum -a 256 "$dist/dims-$1.zip" | cut -d' ' -f1; } + +# Resolved before the heredoc. A command substitution that fails inside one is +# not caught by set -e, and a missing archive would emit an empty sha256. +macos_arm="$(sha macos-arm64)" +macos_intel="$(sha macos-amd64)" +linux_arm="$(sha linux-arm64)" +linux_intel="$(sha linux-amd64)" + +cat <