name: CI

# Quality, security, and release-hygiene checks on every PR and on pushes to
# main. Three independent jobs run in parallel:
#   * flutter             — format, analyze, test, lockfile-enforced pub get.
#   * secret-scan         — offline scan for committed secrets / private data.
#   * release-bump-guard  — release/* PRs only: the bump must be version-only.
on:
  push:
    branches: [main]
  pull_request:

# Read-only: every job here only inspects the checkout. No secrets are used, so
# these checks run identically on fork PRs.
permissions:
  contents: read

jobs:
  flutter:
    name: Flutter checks
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      # Pinned to a 3.27.x (Dart 3.6.x) stable release for reproducible runs.
      # Keep this in sync with the SDK constraint in pubspec.yaml; bumping it
      # may require reformatting with the newer `dart format`.
      - name: Set up Flutter
        uses: subosito/flutter-action@v2
        with:
          channel: stable
          flutter-version: 3.27.4
          cache: true

      # --enforce-lockfile makes `pub get` FAIL instead of silently rewriting
      # pubspec.lock when it has drifted from pubspec.yaml. This is the same
      # resolution the reproducible F-Droid build depends on — the lockfile is
      # committed for exactly this reason (docs/release-process.md §7) — so a PR
      # that changes a dependency without refreshing the lockfile is caught here
      # instead of at release time.
      - name: Install dependencies (lockfile-enforced)
        run: flutter pub get --enforce-lockfile

      - name: Verify formatting
        run: dart format --set-exit-if-changed .

      - name: Analyze
        run: flutter analyze

      - name: Run tests
        run: flutter test

  secret-scan:
    name: Secret & privacy scan
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      # Pure bash + git: no Flutter, no network, no secrets. Catches an
      # accidentally committed keystore / .env / private key / token and a
      # diagnostics fixture carrying a real URL or home path. Local twin:
      # `./scripts/check_secrets.sh` (also wired into scripts/verify_android.sh).
      - name: Scan for secrets and private data
        run: ./scripts/check_secrets.sh

  release-bump-guard:
    name: Release bump touches only version files
    runs-on: ubuntu-latest
    # Only meaningful for the version-bump PRs the "Prepare release bump"
    # workflow opens (it pushes a release/v<version> branch). github.head_ref is
    # set only for pull_request events, so this naturally skips pushes to main
    # and every non-release PR.
    if: ${{ startsWith(github.head_ref, 'release/') }}
    steps:
      - name: Checkout
        uses: actions/checkout@v4
        with:
          fetch-depth: 0

      # Diff the PR against its base and assert the changed files stay within the
      # version-bump allowlist (pubspec, app_info, Fastlane changelog, F-Droid
      # metadata, …). Local twin: scripts/check_release_bump_files.sh.
      - name: Check changed files
        env:
          BASE_SHA: ${{ github.event.pull_request.base.sha }}
        run: |
          set -euo pipefail
          git diff --name-only "$BASE_SHA" HEAD \
            | ./scripts/check_release_bump_files.sh
