Skip to content

docs: refresh cycle 11 research queue #325

docs: refresh cycle 11 research queue

docs: refresh cycle 11 research queue #325

Workflow file for this run

name: SwiftFloris CI
on:
push:
branches: [ main, master ]
paths-ignore:
- ".github/ISSUE_TEMPLATE/**"
- ".github/PULL_REQUEST_TEMPLATE.md"
- ".github/FUNDING.yml"
- ".dockerignore"
- ".editorconfig"
- "fastlane/**"
- "AI_POLICY.md"
- "CODE_OF_CONDUCT.md"
- "CONTRIBUTING.md"
- "LICENSE"
- "README.md"
- "ROADMAP.md"
- "RELEASE_NOTES_*.md"
pull_request:
branches: [ main, master ]
# ROADMAP §6 N6.1 — gate PRs on tests + lint + build (was: assembleDebug only).
# verifyNoInternetPermission (N7.1) runs as a preBuild dependency on every variant,
# so it is implicitly re-checked by both lintDebug and assembleDebug below; we also
# call it explicitly first so a contract violation fails fast before slower tasks.
# Lock the default GITHUB_TOKEN to read-only. Build jobs that only need to
# upload artefacts and report status do not need write access to issues,
# pull-requests, packages, or contents. A future supply-chain compromise of a
# transitive action dependency cannot abuse the token to push commits or
# comment on issues.
permissions:
contents: read
concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
with:
submodules: recursive
- uses: gradle/actions/wrapper-validation@48b5f213c81028ace310571dc5ec0fbbca0b2947 # v4
- name: Check root crash/replay logs
run: bash scripts/check-no-root-crash-logs.sh
- name: Check repo hygiene
run: bash scripts/check-repo-hygiene.sh
- name: Check fastlane / F-Droid metadata
# F-Droid build server reads fastlane/metadata/android/en-US/ for the
# listing title, descriptions, and per-versionCode changelog. If those
# files drift behind gradle.properties, the listing's "What's New"
# falls back to a stale prior changelog. See RESEARCH_FEATURE_PLAN.md
# F1 + the v1.8.175 release notes for the historical rationale (the
# tree shipped FlorisBoard v0.3.16-era metadata through v1.8.173).
run: bash scripts/check-fastlane-metadata.sh
- name: Set up JDK 17
uses: actions/setup-java@c1e323688fd81a25caa38c78aa6df2d33d3e20d9 # v4
with:
java-version: 17
distribution: temurin
- name: Set up CMake and Ninja
uses: lukka/get-cmake@ea004816823209b8d1211e47b216185caee12cc5 # v4.0.2
- name: Cache Gradle
uses: gradle/actions/setup-gradle@48b5f213c81028ace310571dc5ec0fbbca0b2947 # v4
- name: Verify no-network contract (N7.1)
run: ./gradlew :app:verifyNoInternetPermission
# ROADMAP §0 N12.5b — explicit verifyDataExtractionRules step. The
# gate also fires transitively from preBuild (registered in
# app/build.gradle.kts), but calling it directly here makes the
# green/red signal legible in the workflow run summary and pins the
# data_extraction_rules.xml excludes (personal-dictionary + clipboard
# encrypted-stores) against accidental rewrite.
- name: Verify data-extraction rules
run: ./gradlew :app:verifyDataExtractionRules
- name: Unit tests
run: ./gradlew :app:testDebugUnitTest
# ROADMAP §6 N14.1 — Roborazzi visual-regression verify (1.55.0 line ships
# the AGP-9 plugin, so the plugin alias is now applied in app/build.gradle.kts).
# `verifyRoborazziDebug` re-runs every Roborazzi-annotated JUnit test and
# diff-compares the captured PNG against the baseline under
# `app/src/test/snapshots/`. If a snapshot drifts beyond the default
# change threshold (0.01), the task fails the PR. Baseline captures land
# separately via `recordRoborazziDebug` on a maintainer push (run locally
# and commit the resulting PNGs).
- name: Roborazzi visual-regression verify (N14.1)
run: ./gradlew :app:verifyRoborazziDebug
- name: Lint (debug + baseline drift)
run: bash scripts/run-lint-debug-with-baseline-check.sh
- name: Build debug APK
run: ./gradlew :app:assembleDebug
# ROADMAP §7 Next-12.4 — 16 KB memory-page alignment guard. Per Google
# Play's Nov 1 2025 cutoff [STD-A15-16KB], every native .so shipped on
# a target-Android-15+ APK must be 16 KB ELF-segment aligned. SwiftFloris
# currently ships zero native libs in :app (native runtimes for optional
# capabilities live in out-of-tree signed addon APKs per the AddonContract
# enrolment path), so this check is a forward-looking guard: as soon as
# Next-2 (whisper.cpp),
# N1.2 (CleverKeys ONNX), L1 (LiteRT-LM), or L7 (MCP bridge) bring native
# code back in, the gate catches a 4 KB regression at PR time instead of
# at Play upload time. If no .so files exist in the APK the check is a
# no-op (zipalign exits 0 on a debug APK with no native libs).
- name: 16 KB native-library alignment guard
run: |
set -euo pipefail
ANDROID_HOME="${ANDROID_HOME:-/usr/local/lib/android/sdk}"
BUILD_TOOLS=$(ls -1 "$ANDROID_HOME/build-tools" | sort -V | tail -1)
ZIPALIGN="$ANDROID_HOME/build-tools/$BUILD_TOOLS/zipalign"
APK="app/build/outputs/apk/debug/app-debug.apk"
if [ ! -f "$APK" ]; then
echo "No APK produced; skipping."
exit 0
fi
# zipalign -P 16 = require 16 KB alignment for *.so entries (page-size
# in KB units). Exits non-zero if any .so is misaligned.
"$ZIPALIGN" -c -P 16 -v 4 "$APK" || {
echo "::error::APK contains a native library aligned to less than 16 KB. Rebuild against NDK r28+ (see ROADMAP §7 Next-12.4 + [STD-A15-16KB])."
exit 1
}
echo "All shipped native libraries (if any) are 16 KB aligned."
- name: Upload debug APK
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: app-debug.apk
path: app/build/outputs/apk/debug/app-debug.apk
- name: Upload lint report
if: always()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: lint-debug-report
path: |
app/build/reports/lint-results-debug.html
app/build/reports/lint-results-debug.xml
app/build/reports/lintDebug-console.log
- name: Upload unit-test report
if: always()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: unit-test-report
path: app/build/reports/tests/testDebugUnitTest/