Files
ProLibertateGames/.github/workflows/ci.yml
T
Claude e17272b909 Publish the dev channel from any build of dev, not only a push
The dev prerelease steps were gated on the event as well as the branch, so a
manual run from the Actions tab built, tested and linted dev and then skipped
the publish. That matters because a push does not always fire the workflow:
anything pushed by an automation token is suppressed by GitHub's own recursion
guard, which leaves the dev channel stuck on an older build with no way to move
it from the Actions tab.

Gated on the branch alone now, which is how release.yml has always gated main —
the inconsistency was between the two pipelines, not a deliberate rule. Nothing
about the safety property changes: publishing still only happens after the same
job has built, tested and linted clean, and a pull request is still excluded
without being named, because a PR build runs against refs/pull/N/merge and
never refs/heads/dev.

PLG_CHANNEL moves to the same condition, which is the part that would bite if
it were missed. It decides whether the APK is stamped with its run number, and
the publish steps decide whether that APK ships. Leave them out of step and the
dev channel gets an APK claiming versionCode 1 — an "update" the installed app
can never see as newer than what it already has.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_015pyhC1KyFkQk6hUnnX2Tof
2026-08-06 19:04:25 +00:00

123 lines
4.5 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:
# 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
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
# 1.0.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@v3
- 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
version="v1.0.${{ 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: 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."