Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,24 @@ jobs:
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha,scope=embed
cache-to: type=gha,mode=max,scope=embed

# Ships the new tag to Carrel: carrel-deployd on the machine runs
# deploy/carrel-start.sh and rolls back if web is unhealthy.
deploy:
needs: image
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
steps:
- uses: actions/checkout@v4
- run: |
mkdir release
cp deploy/carrel-start.sh release/
echo "sha-${GITHUB_SHA::7}" > release/VERSION
tar czf "$RUNNER_TEMP/gallery.tar.gz" -C release .
- uses: NYCU-WinLab/carrel-deploy@v1
with:
tenant: winfra
app: gallery
artifact: ${{ runner.temp }}/gallery.tar.gz
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ This starts Postgres, runs the migrations once, then serves the gallery from `gh
> [!IMPORTANT]
> Put a reverse proxy with TLS in front, at the host in `BETTER_AUTH_URL`, and let it pass request bodies of 100 MB. MCP clients only accept an HTTPS resource, and the Keycloak redirect URI must match it.

gallery.winlab.tw deploys on every push to `main`. The release workflow pushes the image, then sends a Carrel app release (`winfra/gallery`). On the machine, carrel-deployd runs [deploy/carrel-start.sh](deploy/carrel-start.sh): it sets `GALLERY_VERSION` in `/opt/gallery/.env` and waits until web is healthy. A failed health check rolls back to the previous release. The app unit has a drop-in with `Type=notify`, `NotifyAccess=all` and `TimeoutStartSec=300`, so the check waits for the new container.

## Use

1. In your Keycloak realm, create a confidential OpenID Connect client with the redirect URI `<BETTER_AUTH_URL>/api/auth/callback/keycloak`, and put its ID and secret in `.env`. Give its service account `view-users` so `/mcp` can check that a member still exists.
Expand Down
18 changes: 18 additions & 0 deletions deploy/carrel-start.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#!/bin/sh
# carrel-deployd runs this from the release directory on every deploy and
# rollback. It points the Compose stack in /opt/gallery at the image in
# VERSION, reports ready once web is healthy, then follows the web logs.
# The unit needs Type=notify and NotifyAccess=all (see README, Deploy).
set -eu

version=$(cat VERSION)
cd /opt/gallery

tmp=$(mktemp .env.XXXXXX)
sed "s/^GALLERY_VERSION=.*/GALLERY_VERSION=$version/" .env >"$tmp"
mv "$tmp" .env

docker compose pull --quiet migrate web
docker compose up -d --wait web
systemd-notify --ready
exec docker compose logs -f --since 1s web
Loading