# J621 CD — manual release workflow (Actions tab -> "Run workflow"). # # One dispatch does everything: # * builds and pushes the backend + frontend images (multi-arch, :latest # and :, GIT_HASH baked in for the version pill), # * builds the desktop packages and attaches them (plus the update # metadata) to the Gitea release tagged `desktop-v`. # # The live update feed (deploy/data/desktop, served by the frontend nginx at # /desktop/) is not touched here: it is runtime state on the deploy host and # is still published with `deploy/push_desktop.sh --no-build` from a machine # that can reach it. # # Registry login uses the REGISTRY_USER / REGISTRY_TOKEN repo secrets. # Jobs run on the user-scoped nitro-ci runner (ubuntu-latest). name: CD on: workflow_dispatch: inputs: platforms: description: Image platforms (comma separated) required: false default: linux/amd64,linux/arm64 windows: description: Also cross-build the Windows installer (needs wine, slow) required: false default: "false" concurrency: group: cd cancel-in-progress: false jobs: images: name: Build & push images runs-on: ubuntu-latest env: REGISTRY_USER: ${{ secrets.REGISTRY_USER || github.actor }} REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN || secrets.GITHUB_TOKEN }} PLATFORMS: ${{ inputs.platforms || 'linux/amd64,linux/arm64' }} steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Register binfmt (multi-arch builds) run: docker run --privileged --rm tonistiigi/binfmt --install all - name: Build & push both images run: | set -euo pipefail SHA="$(git rev-parse --short HEAD)" echo "Publishing $SHA for $PLATFORMS" PLATFORMS="$PLATFORMS" ./deploy/push_frontend.sh "$SHA" PLATFORMS="$PLATFORMS" ./deploy/push_backend.sh "$SHA" desktop: name: Desktop release runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: "22" - name: Install packaging tools run: | sudo apt-get update sudo apt-get install -y --no-install-recommends fakeroot libarchive-tools if [ "${{ inputs.windows }}" = "true" ]; then sudo apt-get install -y --no-install-recommends wine fi - name: Install frontend + desktop dependencies run: | npm --prefix frontend ci --no-audit --no-fund npm --prefix desktop ci --no-audit --no-fund - name: Build desktop packages run: | if [ "${{ inputs.windows }}" = "true" ]; then ./deploy/build_desktop.sh --all else ./deploy/build_desktop.sh --linux fi - name: Add the Gitea release env: GITEA_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | set -euo pipefail VERSION="$(node -p "require('./desktop/package.json').version")" TAG="desktop-v$VERSION" API="${{ github.server_url }}/api/v1/repos/${{ github.repository }}" AUTH="Authorization: token $GITEA_TOKEN" NOTES="$(printf 'J621 desktop %s\n\n' "$VERSION" cd desktop/release sha256sum ./*.deb ./*.pkg.tar.zst ./*.exe 2>/dev/null || true)" RELEASE_ID="$(curl -sf -H "$AUTH" "$API/releases/tags/$TAG" \ | python3 -c 'import json,sys; print(json.load(sys.stdin).get("id",""))' \ 2>/dev/null || true)" if [ -z "$RELEASE_ID" ]; then echo "Creating release $TAG" PAYLOAD="$(python3 - "$TAG" "${{ github.sha }}" "$NOTES" <<'PY' import json, sys print(json.dumps({ "tag_name": sys.argv[1], "name": sys.argv[1], "body": sys.argv[3], "target_commitish": sys.argv[2], })) PY )" RELEASE_ID="$(curl -sf -X POST -H "$AUTH" \ -H "Content-Type: application/json" -d "$PAYLOAD" "$API/releases" \ | python3 -c 'import json,sys; print(json.load(sys.stdin)["id"])')" else echo "Release $TAG already exists (id $RELEASE_ID); attaching missing files." fi EXISTING="$(curl -sf -H "$AUTH" "$API/releases/$RELEASE_ID/assets" \ | python3 -c 'import json,sys; print("\n".join(a["name"] for a in json.load(sys.stdin)))' \ || true)" for FILE in desktop/release/*"$VERSION"*.deb \ desktop/release/*"$VERSION"*.pkg.tar.zst \ desktop/release/latest-linux.yml \ desktop/release/latest.yml \ desktop/release/*"$VERSION"*.exe \ desktop/release/*"$VERSION"*.exe.blockmap; do [ -e "$FILE" ] || continue NAME="$(basename "$FILE")" case "$EXISTING" in *"$NAME"*) echo " already attached: $NAME"; continue ;; esac echo " attaching $NAME" curl -sf -X POST -H "$AUTH" -H "Content-Type: application/octet-stream" \ --data-binary @"$FILE" "$API/releases/$RELEASE_ID/assets?name=$NAME" >/dev/null done echo "Release: ${{ github.server_url }}/${{ github.repository }}/releases/tag/$TAG"