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 docker compose pull backend frontend docker compose up -d --no-build 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