Files
cloudlink/.gitea/workflows/docker-build.yml
T
nmemmertandClaude Sonnet 4.6 596e5fffe6
Build & Release / Docker / backend (push) Successful in 1m6s
Build & Release / Docker / frontend (push) Successful in 1m21s
Build & Release / Desktop / Linux & Windows (push) Successful in 18m49s
Build & Release / Deploy to server (push) Has been skipped
Build & Release / Create release (push) Failing after 29s
fix: deploy step stops containers before recreating to avoid ContainerConfig bug
docker-compose 1.29.x fails with KeyError: 'ContainerConfig' when trying
to recreate containers built from newer image manifests. Explicitly stopping
and removing before 'up -d' avoids the inspection of old container state.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-08-31 11:59:06 -04:00

189 lines
7.0 KiB
YAML

name: Build & Release
on:
push:
branches: [master, main]
tags: ['v*']
pull_request:
branches: [master, main]
env:
REGISTRY: git.necloud.us
OWNER: nate
REPO: cloudlink
jobs:
# ─── Docker: Backend ────────────────────────────────────────────────────────
build-backend:
name: Docker / backend
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: docker/setup-buildx-action@v3
- name: Log in to registry
if: github.event_name != 'pull_request'
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ secrets.REGISTRY_USER }}
password: ${{ secrets.REGISTRY_TOKEN }}
- uses: docker/build-push-action@v5
with:
context: ./backend
file: ./backend/Dockerfile
push: ${{ github.event_name != 'pull_request' }}
tags: |
${{ env.REGISTRY }}/${{ env.OWNER }}/${{ env.REPO }}/backend:latest
${{ env.REGISTRY }}/${{ env.OWNER }}/${{ env.REPO }}/backend:${{ github.sha }}
cache-from: type=registry,ref=${{ env.REGISTRY }}/${{ env.OWNER }}/${{ env.REPO }}/backend:cache
cache-to: type=registry,ref=${{ env.REGISTRY }}/${{ env.OWNER }}/${{ env.REPO }}/backend:cache,mode=max
# ─── Docker: Frontend ───────────────────────────────────────────────────────
build-frontend:
name: Docker / frontend
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: docker/setup-buildx-action@v3
- name: Log in to registry
if: github.event_name != 'pull_request'
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ secrets.REGISTRY_USER }}
password: ${{ secrets.REGISTRY_TOKEN }}
- uses: docker/build-push-action@v5
with:
context: ./frontend
file: ./frontend/Dockerfile
push: ${{ github.event_name != 'pull_request' }}
build-args: |
VITE_API_URL=/api
VITE_WS_URL=/ws
tags: |
${{ env.REGISTRY }}/${{ env.OWNER }}/${{ env.REPO }}/frontend:latest
${{ env.REGISTRY }}/${{ env.OWNER }}/${{ env.REPO }}/frontend:${{ github.sha }}
cache-from: type=registry,ref=${{ env.REGISTRY }}/${{ env.OWNER }}/${{ env.REPO }}/frontend:cache
cache-to: type=registry,ref=${{ env.REGISTRY }}/${{ env.OWNER }}/${{ env.REPO }}/frontend:cache,mode=max
# ─── Desktop installers (Linux + Windows, built on Linux runner) ─────────────
build-desktop:
name: Desktop / Linux & Windows
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
cache-dependency-path: desktop/package-lock.json
- name: Install desktop dependencies
working-directory: desktop
run: npm ci
- name: Install Wine (Windows cross-compile)
run: |
sudo dpkg --add-architecture i386
sudo apt-get update -q
sudo apt-get install -y --no-install-recommends wine wine32 wine64
- name: Build Linux AppImage
working-directory: desktop
run: npx electron-builder --linux AppImage --x64 --publish never
- name: Build Windows NSIS installer
working-directory: desktop
run: npx electron-builder --win nsis --x64 --publish never
- uses: actions/upload-artifact@v3
with:
name: desktop-linux-windows-${{ github.sha }}
path: |
desktop/dist/*.AppImage
desktop/dist/*.exe
if-no-files-found: warn
retention-days: 30
# ─── Deploy (on push to master only, not PRs or tags) ───────────────────────
deploy:
name: Deploy to server
runs-on: ubuntu-latest
needs: [build-backend, build-frontend]
if: github.event_name == 'push' && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/main')
steps:
- name: SSH deploy
uses: appleboy/ssh-action@v1
with:
host: ${{ secrets.DEPLOY_HOST }}
username: ${{ secrets.DEPLOY_USER }}
key: ${{ secrets.DEPLOY_SSH_KEY }}
script: |
cd ${{ secrets.DEPLOY_PATH }}
echo "${{ secrets.REGISTRY_TOKEN }}" | docker login git.necloud.us -u "${{ secrets.REGISTRY_USER }}" --password-stdin
# Pull new images first
if docker compose version > /dev/null 2>&1; then
COMPOSE="docker compose"
else
COMPOSE="docker-compose"
fi
$COMPOSE pull backend frontend
# Stop and remove old containers so docker-compose up creates fresh ones
# (works around ContainerConfig bug in docker-compose 1.29.x)
$COMPOSE stop backend frontend || true
$COMPOSE rm -f backend frontend || true
$COMPOSE up -d backend frontend
docker logout git.necloud.us
docker image prune -f
# ─── Release (only on v* tags) ───────────────────────────────────────────────
release:
name: Create release
runs-on: ubuntu-latest
needs: [build-desktop, build-backend, build-frontend]
if: startsWith(github.ref, 'refs/tags/v')
steps:
- name: Download desktop artifacts
uses: actions/download-artifact@v3
with:
name: desktop-linux-windows-${{ github.sha }}
path: ./release-assets
- name: Publish Gitea release
env:
GITEA_TOKEN: ${{ secrets.REGISTRY_TOKEN }}
TAG: ${{ github.ref_name }}
SHA: ${{ github.sha }}
run: |
# Create the release
RELEASE=$(curl -sf -X POST \
-H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
"https://git.necloud.us/api/v1/repos/nate/cloudlink/releases" \
-d "{\"tag_name\":\"$TAG\",\"name\":\"CloudLink $TAG\",\"body\":\"Docker images pushed to registry. Desktop installers attached below.\"}")
RELEASE_ID=$(echo "$RELEASE" | python3 -c "import sys,json; print(json.load(sys.stdin)['id'])")
echo "Release ID: $RELEASE_ID"
# Upload each installer as a release asset
for file in ./release-assets/*; do
NAME=$(basename "$file")
echo "Uploading $NAME..."
curl -sf -X POST \
-H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/octet-stream" \
"https://git.necloud.us/api/v1/repos/nate/cloudlink/releases/$RELEASE_ID/assets?name=$NAME" \
--data-binary @"$file"
done