🔥 docs: strip legacy opds-sync rebrand notes; add F-Droid instal… #183
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: android-ci | |
| on: | |
| push: | |
| paths: | |
| - "app/**" | |
| - "auth/**" | |
| - "core/**" | |
| - "data/**" | |
| - "reader/**" | |
| - "build.gradle.kts" | |
| - "settings.gradle.kts" | |
| - "gradle.properties" | |
| - "gradle/**" | |
| - "gradlew" | |
| - ".github/workflows/android-ci.yaml" | |
| pull_request: | |
| paths: | |
| - "app/**" | |
| - "auth/**" | |
| - "core/**" | |
| - "data/**" | |
| - "reader/**" | |
| - "build.gradle.kts" | |
| - "settings.gradle.kts" | |
| - "gradle.properties" | |
| - "gradle/**" | |
| - "gradlew" | |
| - ".github/workflows/android-ci.yaml" | |
| # Cancel obsolete runs on PR / branch pushes. Never cancel runs on main — | |
| # we want a Release for every commit that lands. | |
| concurrency: | |
| group: android-ci-${{ github.ref }} | |
| cancel-in-progress: ${{ github.ref != 'refs/heads/main' }} | |
| jobs: | |
| build: | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write # to push the version-bump commit and tag | |
| outputs: | |
| version: ${{ steps.version.outputs.version }} | |
| steps: | |
| - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5 | |
| with: | |
| fetch-depth: 0 | |
| fetch-tags: true | |
| - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5 | |
| with: | |
| distribution: temurin | |
| java-version: "21" | |
| - uses: android-actions/setup-android@40fd30fb8d7440372e1316f5d1809ec01dcd3699 # v4 | |
| with: | |
| packages: "platform-tools platforms;android-34 build-tools;34.0.0" | |
| - uses: gradle/actions/setup-gradle@4c125117fe7c5aed11272ec4213f602f012f89f2 # v5 | |
| - id: version | |
| name: Compute version | |
| env: | |
| # Use the GitHub-provided token to push the bump commit and tag. | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| if [ "$GITHUB_REF" = "refs/heads/main" ]; then | |
| # On main: compute the next CalVer from date + run number, | |
| # write it into gradle.properties, commit + tag, then push | |
| # both before Gradle runs. The build then reads the bumped | |
| # values directly from gradle.properties. | |
| BUILD_DATE=$(date -u +%Y-%m-%d) | |
| NEW_NAME="${BUILD_DATE//-/.}.${GITHUB_RUN_NUMBER}" | |
| YY=$(date -u +%y) | |
| MM=$(date -u +%m) | |
| DD=$(date -u +%d) | |
| NEW_CODE=$(( (10#$YY * 10000 + 10#$MM * 100 + 10#$DD) * 100 + GITHUB_RUN_NUMBER % 100 )) | |
| sed -i "s/^VERSION_NAME=.*/VERSION_NAME=$NEW_NAME/" gradle.properties | |
| sed -i "s/^VERSION_CODE=.*/VERSION_CODE=$NEW_CODE/" gradle.properties | |
| git config user.name "github-actions[bot]" | |
| git config user.email "41898282+github-actions[bot]@users.noreply.github.com" | |
| git remote set-url origin "https://x-access-token:${GH_TOKEN}@github.com/${GITHUB_REPOSITORY}.git" | |
| # If another main push lands between our checkout and our push | |
| # (or between two consecutive bump runs), HEAD is non-fast-forward. | |
| # The naive `git rebase` strategy conflicts when both bump commits | |
| # mutate the same `VERSION_NAME=` line — that's unrecoverable | |
| # without manual resolution. Instead, on rejection we reset hard | |
| # to the latest main, re-apply the bump on top, and retry. The | |
| # bump value is derived from GITHUB_RUN_NUMBER which is stable | |
| # across retries, so we always end up with a unique tag. | |
| apply_bump() { | |
| sed -i "s/^VERSION_NAME=.*/VERSION_NAME=$NEW_NAME/" gradle.properties | |
| sed -i "s/^VERSION_CODE=.*/VERSION_CODE=$NEW_CODE/" gradle.properties | |
| git add gradle.properties | |
| git commit -m ":bookmark: chore: release v$NEW_NAME" | |
| git tag -f "v$NEW_NAME" | |
| } | |
| apply_bump | |
| attempts=0 | |
| until git push origin "HEAD:$GITHUB_REF" "v$NEW_NAME"; do | |
| attempts=$((attempts + 1)) | |
| if [ "$attempts" -ge 5 ]; then | |
| echo "release bump push failed after $attempts attempts" >&2 | |
| exit 1 | |
| fi | |
| echo "release bump push rejected; resetting + re-applying bump ($attempts)…" | |
| git fetch origin "$GITHUB_REF" | |
| git tag -d "v$NEW_NAME" 2>/dev/null || true | |
| git reset --hard "origin/${GITHUB_REF#refs/heads/}" | |
| apply_bump | |
| done | |
| VERSION="$NEW_NAME" | |
| else | |
| # On PRs / feature branches: just read the static value from | |
| # gradle.properties — no bump, no tag, no commit. | |
| VERSION=$(grep '^VERSION_NAME=' gradle.properties | cut -d= -f2) | |
| fi | |
| echo "VERSION_NAME=$VERSION" >> "$GITHUB_ENV" | |
| echo "version=$VERSION" >> "$GITHUB_OUTPUT" | |
| echo "Building version $VERSION" | |
| - name: Install ripgrep (rename guard) | |
| run: | | |
| if ! command -v rg >/dev/null; then | |
| sudo apt-get update && sudo apt-get install -y ripgrep | |
| fi | |
| - name: Rename guard self-test | |
| run: | | |
| set -e | |
| # Proves the rename-guard regex catches OPDS_SYNC_<X> patterns. | |
| tmp=$(mktemp /tmp/rename-guard-self-test-XXXX.txt) | |
| printf 'OPDS_SYNC_AI_ENABLED: true\n' > "$tmp" | |
| if ! rg -P '\bopds[-_]sync\b|(?<![A-Z0-9_])OPDS_SYNC_[A-Z0-9_]*' "$tmp" >/dev/null; then | |
| echo "::error::Rename guard regex failed self-test (did NOT match OPDS_SYNC_AI_ENABLED)." | |
| rm -f "$tmp" | |
| exit 1 | |
| fi | |
| rm -f "$tmp" | |
| - name: Rename guard | |
| run: | | |
| set -o pipefail | |
| # Mirror of the server-ci rename guard. Lives here too because | |
| # server-ci is path-filtered to server/** and would not run for | |
| # Android-side regressions that smuggle in legacy names. | |
| if rg -n -P '\bopds[-_]sync\b|(?<![A-Z0-9_])OPDS_SYNC_[A-Z0-9_]*' \ | |
| -g '!.claude/**' \ | |
| -g '!CHANGELOG.md' \ | |
| -g '!server/migrations/versions/*.py' \ | |
| -g '!server/quire_server/config.py' \ | |
| -g '!server/docker-compose.yml' \ | |
| -g '!server/docker-compose.full.yml' \ | |
| -g '!server/alembic.ini' \ | |
| -g '!server/migrations/env.py' \ | |
| -g '!server/tests/conftest.py' \ | |
| -g '!server/tests/unit/test_no_stale_opds_sync_imports.py' \ | |
| . ; then | |
| echo "::error::Rename guard found un-allowlisted OPDS_SYNC / opds-sync / opds_sync references." | |
| exit 1 | |
| fi | |
| - name: Assemble debug APK | |
| run: ./gradlew assembleDebug --stacktrace | |
| - name: Unit tests | |
| run: ./gradlew test --stacktrace | |
| - name: Lint | |
| run: ./gradlew lint --stacktrace | |
| - name: Upload debug APK | |
| if: github.ref == 'refs/heads/main' | |
| uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 | |
| with: | |
| name: app-debug-${{ env.VERSION_NAME }} | |
| path: app/build/outputs/apk/debug/*.apk | |
| if-no-files-found: error | |
| # On main only: build the signed release APK and publish a GitHub | |
| # Release. The release action creates the tag itself, so we don't push | |
| # tags from the workflow (workflow-pushed tags via GITHUB_TOKEN don't | |
| # trigger downstream runs anyway, which is why this used to be split). | |
| release: | |
| needs: build | |
| if: github.ref == 'refs/heads/main' | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| steps: | |
| - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5 | |
| with: | |
| ref: v${{ needs.build.outputs.version }} | |
| fetch-depth: 0 | |
| fetch-tags: true | |
| - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5 | |
| with: | |
| distribution: temurin | |
| java-version: "21" | |
| - uses: android-actions/setup-android@40fd30fb8d7440372e1316f5d1809ec01dcd3699 # v4 | |
| with: | |
| packages: "platform-tools platforms;android-34 build-tools;34.0.0" | |
| - uses: gradle/actions/setup-gradle@4c125117fe7c5aed11272ec4213f602f012f89f2 # v5 | |
| - name: Decode keystore | |
| if: env.KEYSTORE_B64 != '' | |
| run: echo "$KEYSTORE_B64" | base64 -d > "$RUNNER_TEMP/release.keystore" | |
| env: | |
| KEYSTORE_B64: ${{ secrets.QUIRE_RELEASE_KEYSTORE_B64 }} | |
| - name: Assemble release APK | |
| env: | |
| QUIRE_RELEASE_KEYSTORE: ${{ secrets.QUIRE_RELEASE_KEYSTORE_B64 != '' && format('{0}/release.keystore', runner.temp) || '' }} | |
| QUIRE_RELEASE_KEYSTORE_PASSWORD: ${{ secrets.QUIRE_RELEASE_KEYSTORE_PASSWORD }} | |
| QUIRE_RELEASE_KEY_ALIAS: ${{ secrets.QUIRE_RELEASE_KEY_ALIAS }} | |
| QUIRE_RELEASE_KEY_PASSWORD: ${{ secrets.QUIRE_RELEASE_KEY_PASSWORD }} | |
| run: ./gradlew :app:assembleRelease --stacktrace | |
| - name: Create GitHub Release | |
| uses: softprops/action-gh-release@b4309332981a82ec1c5618f44dd2e27cc8bfbfda # v3 | |
| with: | |
| tag_name: v${{ needs.build.outputs.version }} | |
| files: app/build/outputs/apk/release/*.apk | |
| generate_release_notes: true |