All checks were successful
CI / ci (pull_request) Successful in 8m50s
v2.7.3 is the first release built with `vcsInfo { include = false }` and is
verified reproducible: a clean from-source build matched the published
calendula_v2.7.3.apk byte-for-byte across all 1382 zip entries (only the
signature block differs, which F-Droid copies).
- Point the fdroiddata recipe's Builds entry + CurrentVersion at v2.7.3
(was the 2.7.2 placeholder, which lacks the fix and would fail verification).
- UpdateCheckMode: Tags ^v[0-9.]+$ — after this one-time submission F-Droid
auto-tracks new release tags and adds build entries itself; no manual recipe
edits per release.
- Add scripts/check_reproducible_release.sh + an always-on CI step asserting the
release build keeps VCS-info disabled, so reproducibility can't silently
regress and quietly stop official-repo publishing.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
145 lines
5.6 KiB
YAML
145 lines
5.6 KiB
YAML
name: CI
|
|
|
|
# One gate per pull request. Branch pushes no longer trigger CI on their own,
|
|
# so a change is built once on its PR (covering feature -> release/* and
|
|
# release/* -> main) instead of once per push and again on the merge to main.
|
|
# The merge itself is handled by release.yaml, which only does heavy work when
|
|
# the merge actually cuts a release.
|
|
on:
|
|
pull_request:
|
|
|
|
# Cancel superseded runs for the same PR.
|
|
concurrency:
|
|
group: ci-${{ github.ref }}
|
|
cancel-in-progress: true
|
|
|
|
jobs:
|
|
# Single job named `ci` so the required "CI" status check is always reported,
|
|
# even for docs-only PRs: those just skip the Android build and the job still
|
|
# succeeds (fast green check) instead of being filtered out and leaving the
|
|
# required check pending forever.
|
|
ci:
|
|
runs-on: docker
|
|
env:
|
|
ANDROID_HOME: /opt/android-sdk
|
|
ANDROID_SDK_ROOT: /opt/android-sdk
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
with:
|
|
# Full history so the base..HEAD diff below has a merge-base.
|
|
fetch-depth: 0
|
|
|
|
# Cheap, always-on guard: the release build must stay reproducible for the
|
|
# official F-Droid repo (no AGP VCS-info embedding). Runs regardless of
|
|
# change scope so a regression can't slip through on a "docs-only" PR.
|
|
- name: Reproducible-release invariant
|
|
run: bash scripts/check_reproducible_release.sh
|
|
|
|
# Decide whether anything that affects the app build changed. Docs,
|
|
# F-Droid metadata and the licence don't, so those PRs skip the SDK +
|
|
# Gradle work below but still report a green `ci`.
|
|
- name: Classify change scope
|
|
id: scope
|
|
run: |
|
|
set -e
|
|
BASE="${{ github.base_ref }}"
|
|
# Full (not --depth=1) base fetch so the merge-base is present even when
|
|
# the PR branch forked several commits back; a shallow tip has no merge
|
|
# base with a divergent branch and `git diff base...HEAD` aborts.
|
|
git fetch --no-tags origin "$BASE"
|
|
MB=$(git merge-base "origin/$BASE" HEAD 2>/dev/null || true)
|
|
if [ -z "$MB" ]; then
|
|
# No common ancestor available — don't risk skipping the build.
|
|
echo "No merge base with origin/$BASE — running the full build to be safe."
|
|
echo "code=true" >> "$GITHUB_OUTPUT"
|
|
exit 0
|
|
fi
|
|
CHANGED=$(git diff --name-only "$MB" HEAD)
|
|
echo "Changed files:"; echo "$CHANGED"
|
|
if echo "$CHANGED" | grep -vE '(\.md$|^docs/|^fdroid-metadata/|^fastlane/|^LICENSE$)' | grep -q .; then
|
|
echo "code=true" >> "$GITHUB_OUTPUT"
|
|
else
|
|
echo "code=false" >> "$GITHUB_OUTPUT"
|
|
echo "Docs/metadata-only change — skipping the Android build."
|
|
fi
|
|
|
|
- name: Setup Java
|
|
if: steps.scope.outputs.code == 'true'
|
|
uses: actions/setup-java@v4
|
|
with:
|
|
distribution: 'zulu'
|
|
java-version: '17'
|
|
|
|
- name: Setup Android SDK
|
|
if: steps.scope.outputs.code == 'true'
|
|
uses: android-actions/setup-android@v3
|
|
with:
|
|
# Default ("tools platform-tools") drags in the Android Emulator
|
|
# (~300 MB) which the build never uses.
|
|
packages: ''
|
|
|
|
- name: Setup Android SDK cache
|
|
if: steps.scope.outputs.code == 'true'
|
|
uses: actions/cache@v4
|
|
with:
|
|
path: /opt/android-sdk
|
|
key: ${{ runner.os }}-android-sdk-37-36.0.0
|
|
|
|
- name: Install Android SDK packages
|
|
if: steps.scope.outputs.code == 'true'
|
|
run: |
|
|
yes | sdkmanager --licenses >/dev/null || true
|
|
sdkmanager \
|
|
"platform-tools" \
|
|
"platforms;android-37.0" \
|
|
"build-tools;36.0.0"
|
|
|
|
- name: Setup Gradle cache
|
|
if: steps.scope.outputs.code == 'true'
|
|
uses: actions/cache@v4
|
|
with:
|
|
path: |
|
|
~/.gradle/caches
|
|
~/.gradle/wrapper
|
|
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties', 'gradle/libs.versions.toml') }}
|
|
restore-keys: |
|
|
${{ runner.os }}-gradle-
|
|
|
|
- name: Grant execute permission for gradlew
|
|
if: steps.scope.outputs.code == 'true'
|
|
run: chmod +x ./gradlew
|
|
|
|
# No --no-daemon: the daemon lives only as long as this job container
|
|
# and lets the following steps skip JVM startup + reconfiguration.
|
|
- name: Lint (debug variant only)
|
|
if: steps.scope.outputs.code == 'true'
|
|
run: ./gradlew lintDebug
|
|
|
|
- name: Unit tests
|
|
if: steps.scope.outputs.code == 'true'
|
|
run: ./gradlew testDebugUnitTest
|
|
|
|
- name: Assemble debug APK
|
|
if: steps.scope.outputs.code == 'true'
|
|
run: ./gradlew assembleDebug
|
|
|
|
- name: Trivy filesystem scan
|
|
if: steps.scope.outputs.code == 'true'
|
|
run: |
|
|
set -e
|
|
SUDO=""
|
|
if command -v sudo >/dev/null 2>&1; then
|
|
SUDO="sudo"
|
|
fi
|
|
if command -v apt-get >/dev/null 2>&1; then
|
|
$SUDO apt-get update
|
|
$SUDO apt-get install -y wget apt-transport-https gnupg lsb-release
|
|
wget -qO - https://aquasecurity.github.io/trivy-repo/deb/public.key | gpg --dearmor | $SUDO tee /usr/share/keyrings/trivy.gpg > /dev/null
|
|
echo "deb [signed-by=/usr/share/keyrings/trivy.gpg] https://aquasecurity.github.io/trivy-repo/deb generic main" | $SUDO tee /etc/apt/sources.list.d/trivy.list
|
|
$SUDO apt-get update
|
|
$SUDO apt-get install -y trivy
|
|
fi
|
|
trivy filesystem --severity HIGH,CRITICAL --exit-code 0 .
|
|
continue-on-error: true
|