all: add minimal GoReleaser configuration for nightly builds

This is step one of many towards automated nightly releases.

This gets us downloadable binaries, which can be grabbed manually
from GitHub Releases...in theory, since this is untested,
because GitHub Actions.

Once this is working, future steps include:

- documentation
- homebrew support (and other package managers?)
- auto-updates
- installers
- blah blah blah

diff --git a/.github/workflows/release-build.yml b/.github/workflows/release-build.yml
new file mode 100644
index 0000000..44494eb
--- /dev/null
+++ b/.github/workflows/release-build.yml
@@ -0,0 +1,101 @@
+name: Release Build (Nightly)
+
+on:
+  schedule:
+    - cron: "47 9 * * *" # 1:47 AM Pacific Time (9:47 UTC)
+  workflow_dispatch: # Allow manual triggering
+
+permissions:
+  contents: write
+
+jobs:
+  nightly:
+    runs-on: ubuntu-latest
+    if: github.ref == 'refs/heads/main'
+    steps:
+      - name: Checkout
+        uses: actions/checkout@v4
+        with:
+          fetch-depth: 0
+
+      - name: Set up Node.js
+        uses: actions/setup-node@v4
+        with:
+          node-version: "20"
+          cache: "npm"
+          cache-dependency-path: "webui/package-lock.json"
+
+      - uses: actions/setup-go@v5
+        with:
+          go-version-file: "${{ inputs.working-directory || '.'}}/go.mod"
+          cache: true
+
+      - name: Check for changes since last tag
+        id: check_changes
+        run: |
+          git fetch --tags --force
+          # find latest nightly tag that looks like nightly/v0.0.N
+          latest_nightly=$(git tag -l "nightly/v0.0.*" --sort=-v:refname | head -n1)
+          if [ -z "$latest_nightly" ]; then
+            echo "has_changes=true" >> $GITHUB_OUTPUT
+            echo "tag=v0.0.1" >> $GITHUB_OUTPUT
+            echo "nightly_tag=nightly/v0.0.1" >> $GITHUB_OUTPUT
+          else
+            echo "Latest nightly tag is $latest_nightly"
+            # Check if there are any new commits since the last nightly tag
+            changes=$(git log $latest_nightly..HEAD --oneline)
+            if [ -z "$changes" ]; then
+              echo "No new changes since last nightly tag, skipping nightly build"
+              echo "has_changes=false" >> $GITHUB_OUTPUT
+            else
+              echo "Changes found since last nightly tag:"
+              echo "$changes"
+              echo "has_changes=true" >> $GITHUB_OUTPUT
+              # Extract N from nightly/v0.0.N and increment
+              version_part="${latest_nightly#nightly/v0.0.}"
+              new_n=$((version_part + 1))
+              new_tag="v0.0.${new_n}"
+              new_nightly_tag="nightly/v0.0.${new_n}"
+              echo "tag=$new_tag" >> $GITHUB_OUTPUT
+              echo "nightly_tag=$new_nightly_tag" >> $GITHUB_OUTPUT
+            fi
+          fi
+
+      - name: Create and push nightly git tag
+        if: steps.check_changes.outputs.has_changes == 'true'
+        env:
+          TAG: ${{ steps.check_changes.outputs.tag }}
+          NIGHTLY_TAG: ${{ steps.check_changes.outputs.nightly_tag }}
+        run: |
+          git config user.name "Sketch Nightly Bot"
+          git config user.email "hello@sketch.dev"
+          git tag -a "$TAG" -m "Nightly build $TAG"
+          git tag -a "$NIGHTLY_TAG" -m "Nightly build tracking tag for $TAG"
+          git push origin "$TAG"
+          git push origin "$NIGHTLY_TAG"
+
+      - name: Run GoReleaser (Nightly)
+        if: steps.check_changes.outputs.has_changes == 'true'
+        uses: goreleaser/goreleaser-action@v4
+        with:
+          version: latest
+          args: release --clean
+        env:
+          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+
+      - name: Mark release as prerelease
+        if: steps.check_changes.outputs.has_changes == 'true'
+        uses: actions/github-script@v6
+        with:
+          script: |
+            const tag = process.env.TAG;
+            const [owner, repo] = process.env.GITHUB_REPOSITORY.split('/');
+            const release = await github.rest.repos.getReleaseByTag({ owner, repo, tag });
+            await github.rest.repos.updateRelease({
+              owner,
+              repo,
+              release_id: release.data.id,
+              prerelease: true
+            });
+        env:
+          TAG: ${{ steps.check_changes.outputs.tag }}