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. # # On a push to dev it also publishes the build as a dev-channel prerelease on # this Gitea instance, so the in-app updater can offer it to anyone on the dev # channel. Prereleases are used deliberately: the "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. # # These files live in .github/workflows/ on purpose: Gitea Actions reads that # path as well as .gitea/workflows/, so one file serves both. Publishing goes # through Gitea's REST API (the same routes the app's updater reads) rather # than the `gh` CLI, which a runner image need not carry. on: push: branches: [ dev ] pull_request: branches: [ main, dev ] workflow_dispatch: # Needed by the job token to create the release and attach the APK. 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 # .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. 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 gates 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 and the offset come 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. The number # is run number + offset, exactly the arithmetic build.gradle.kts # did for versionCode. series="$(sed -n 's/^plgVersionSeries=//p' gradle.properties)" offset="$(sed -n 's/^plgVersionRunOffset=//p' gradle.properties)" test -n "$series" test -n "$offset" stamp="$(( ${{ github.run_number }} + offset ))" version="v${series}.${stamp}-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: # The job's built-in token: contents: write is declared above. GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }} RELEASE_TAG: ${{ steps.stage.outputs.version }} RELEASE_APK: ${{ steps.stage.outputs.apk }} RELEASE_KIND: prerelease RELEASE_TARGET: ${{ github.sha }} # One script, also runnable by hand — see docs/CI.md. run: ./scripts/publish-release.sh