Files
ProLibertateGames/.github/workflows/ci.yml
T
Claude 4369d15cec Add first_deploy dispatch input so the first Cloudflare deploy can bootstrap
The domain answers 403 (error 1014) until the Pages project exists, which
made the carry-over fetch abort the very deploy that would create it.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01JdMNbY5hLR7FjtfEE712xG
2026-10-14 15:39:03 +00:00

185 lines
7.0 KiB
YAML

name: CI
# Pre-merge checks. Runs on the dev branch and on every pull request aimed at
# dev or main, so breakage is caught before it reaches main and triggers a
# release.
#
# On a push to dev it also publishes the build as a dev-channel prerelease, so
# the in-app updater can offer it to anyone who has switched to that channel.
# Prereleases are used deliberately: GitHub's "latest release" endpoint skips
# them, so a production-channel user never sees a dev build. Pull requests only
# build and check — they never publish, which keeps a PR from a fork from
# shipping anything.
on:
push:
branches: [ dev ]
pull_request:
branches: [ main, dev ]
workflow_dispatch:
inputs:
first_deploy:
description: "First Cloudflare deploy: skip carrying over the other channel (the site does not exist yet)"
type: boolean
default: false
# Needed to publish the dev-channel prerelease below.
permissions:
contents: write
# A newer push to the same branch or PR makes the in-flight run obsolete.
concurrency:
group: ci-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
build:
name: Build and check
runs-on: ubuntu-latest
outputs:
version: ${{ steps.stage.outputs.version }}
env:
# Stamp the APK as a dev-channel build exactly when it is a build of the
# dev branch, which is exactly when it can be published below. Pull
# request builds run against refs/pull/N/merge, so they stay unstamped at
# <series>.0-dev: they are never published and must not claim a channel
# version.
#
# This condition has to stay in step with the publish steps' own. Stamping
# a build the publish steps would ship, or shipping one this left
# unstamped, both end the same way — an APK claiming versionCode 1, which
# the updater can never see as an upgrade over anything.
PLG_CHANNEL: ${{ github.ref == 'refs/heads/dev' && 'dev' || '' }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: '17'
cache: gradle
- name: Set up Android SDK
uses: android-actions/setup-android@v4
- name: Build debug APK
run: ./gradlew assembleDebug --no-daemon
- name: Run unit tests
run: ./gradlew testDebugUnitTest --no-daemon
- name: Run Android lint
run: ./gradlew lintDebug --no-daemon
- name: Upload debug APK
uses: actions/upload-artifact@v4
with:
name: ProLibertateGames-debug-apk
path: app/build/outputs/apk/debug/app-debug.apk
if-no-files-found: error
retention-days: 14
- name: Upload lint and test reports
# Reports are most useful precisely when a step above failed.
if: always()
uses: actions/upload-artifact@v4
with:
name: ProLibertateGames-reports
path: |
app/build/reports/
if-no-files-found: ignore
retention-days: 14
# Everything below publishes the dev channel, and only ever from the dev
# branch itself, after it has built, tested and linted clean above.
#
# Gated on the branch alone rather than on the event, which is how
# release.yml has always gated main. A pull request is still excluded
# without needing to name it: a PR build runs against refs/pull/N/merge,
# never refs/heads/dev, so a fork still cannot ship anything.
- name: Stage dev APK
id: stage
if: github.ref == 'refs/heads/dev'
run: |
set -euo pipefail
# The series comes from gradle.properties, which is the same file the
# build read when it stamped the APK — so the tag and what is inside
# it cannot name different versions.
series="$(sed -n 's/^plgVersionSeries=//p' gradle.properties)"
test -n "$series"
version="v${series}.${{ github.run_number }}-dev"
src="app/build/outputs/apk/debug/app-debug.apk"
dest="ProLibertateGames-${version}.apk"
cp "$src" "$dest"
echo "version=$version" >> "$GITHUB_OUTPUT"
echo "apk=$dest" >> "$GITHUB_OUTPUT"
- name: Upload staged dev APK for the Pages deploy
if: github.ref == 'refs/heads/dev'
uses: actions/upload-artifact@v4
with:
name: plg-dev-staged
path: ${{ steps.stage.outputs.apk }}
if-no-files-found: error
retention-days: 1
- name: Publish dev channel prerelease
if: github.ref == 'refs/heads/dev'
env:
GH_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
gh release create "${{ steps.stage.outputs.version }}" \
"${{ steps.stage.outputs.apk }}" \
--repo "${{ github.repository }}" \
--target "${{ github.sha }}" \
--title "ProLibertateGames ${{ steps.stage.outputs.version }}" \
--prerelease \
--notes "Automated **dev channel** build from \`${{ github.sha }}\` on \`dev\`.
Preview build: newer than production, and less tested. Switch to the
Dev update channel in Settings to be offered these. Marked as a
prerelease so production-channel installs never see it."
# Publishes the build to https://plg.wallacenet.ca (Cloudflare Pages). Runs
# alongside the GitHub release above for one deployment so already-installed
# apps, which still read GitHub, can fetch the updater that reads Cloudflare.
#
# Both workflows deploy into one Pages site, and a deploy replaces the whole
# site, so they share a concurrency group and never run at the same time.
deploy-pages:
name: Deploy to Cloudflare Pages
needs: build
if: github.ref == 'refs/heads/dev'
runs-on: ubuntu-latest
concurrency:
group: plg-pages-deploy
cancel-in-progress: false
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Download staged APK
uses: actions/download-artifact@v4
with:
name: plg-dev-staged
path: staged
- name: Assemble site
env:
PLG_SKIP_OTHER: ${{ inputs.first_deploy && '1' || '' }}
run: .github/scripts/stage-pages-site.sh dev "${{ needs.build.outputs.version }}" "staged/ProLibertateGames-${{ needs.build.outputs.version }}.apk"
- name: Deploy
env:
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
run: |
set -euo pipefail
# Creates the project on first run; fails harmlessly if it exists.
npx --yes wrangler@3 pages project create plg --production-branch main || true
# --branch main makes this the production deployment, which is what
# plg.wallacenet.ca serves, whichever branch the workflow ran on.
npx --yes wrangler@3 pages deploy pages-out --project-name plg --branch main --commit-dirty=true