diff --git a/.github/workflows/README.md b/.github/workflows/README.md index 1dbdf82..2848084 100644 --- a/.github/workflows/README.md +++ b/.github/workflows/README.md @@ -13,11 +13,11 @@ This directory contains the CI/CD workflows for the Letterbox project. The workf **Jobs:** - **lint-and-test**: Runs Rust format checks, Rust tests, Android lint, and Android unit tests -- **build**: Builds debug and release APKs with native libraries for all architectures +- **build**: Builds staging debug and prod release APKs with native libraries for all architectures **Outputs:** -- `debug-artifact-name`: Name of the uploaded debug APK artifact -- `release-artifact-name`: Name of the uploaded release APK artifact +- `test-artifact-name`: Name of the uploaded staging debug APK artifact +- `prod-release-artifact-name`: Name of the uploaded prod release (unsigned) APK artifact ### 2. `android-ui.yml` - Android UI Tests **Trigger:** On completion of the Build workflow (via `workflow_run`). @@ -120,13 +120,21 @@ The `android-ui.yml` workflow runs instrumented tests using Gradle Managed Devic ```bash # Run UI tests locally -./gradlew pixel7Api34DebugAndroidTest +./gradlew pixel7Api34StagingDebugAndroidTest ``` -Test files are located in `app/src/androidTest/java/com/btreemap/letterbox/`: +Test files are located in `app/src/androidTest/java/org/joefang/letterbox/`: - `HomeScreenTest.kt` - Core UI element tests - `NavigationTest.kt` - Navigation flow tests +- `BackNavigationTest.kt` - Back navigation behavior tests - `AccessibilityTest.kt` - Accessibility compliance tests +- `EmailDetailScreenTest.kt` - Email detail screen tests +- `EmailOpeningE2ETest.kt` - End-to-end email opening tests +- `AttachmentInteractionE2ETest.kt` - Attachment interaction tests +- `HistoryFeaturesE2ETest.kt` - History feature tests +- `LinkHandlingE2ETest.kt` - Link handling tests +- `CloudflareTermsConsentE2ETest.kt` - Cloudflare consent flow tests +- `ImageProxyIntegrationTest.kt` - Image proxy integration tests ## Artifact Retention Policies diff --git a/.jules/atlas.md b/.jules/atlas.md new file mode 100644 index 0000000..9da2001 --- /dev/null +++ b/.jules/atlas.md @@ -0,0 +1,9 @@ +# Atlas Journal — Critical Learnings + +## 2026-02-27 - Package path mismatch pattern +**Learning:** The Android package is `org.joefang.letterbox` (see `app/build.gradle.kts` applicationId), but the GitHub org is `BTreeMap`. Documentation that references file paths may use the wrong package path (e.g., `com/btreemap/letterbox` instead of `org/joefang/letterbox`). Always verify package paths against the actual `applicationId` in `build.gradle.kts`. +**Action:** When auditing docs that reference Java/Kotlin file paths, cross-check against `applicationId` in `app/build.gradle.kts` and the actual directory structure. + +## 2026-02-27 - Cargo workspace has two crates, not one +**Learning:** The Cargo workspace includes both `rust/letterbox-core` and `rust/letterbox-proxy`. Documentation and CI both build/test these independently. Any doc claiming to describe the Rust workspace should mention both crates. +**Action:** When auditing Rust-related docs, verify all workspace members from `Cargo.toml` are mentioned. diff --git a/README.md b/README.md index bd502be..d9999bb 100644 --- a/README.md +++ b/README.md @@ -24,8 +24,10 @@ Letterbox is an Android application built with Jetpack Compose that opens and in - `app/`: Android application module, Compose UI, Room data layer, UniFFI bindings, and Gradle tasks to build native artifacts. - `rust/letterbox-core/`: Rust library that parses emails with `mail-parser` and exposes UniFFI bindings for Kotlin/Android. +- `rust/letterbox-proxy/`: Rust library implementing a privacy-preserving image proxy using Cloudflare WARP. +- `docs/`: Project documentation (architecture, troubleshooting, versioning, signing, and more). - `gradle/`, `build.gradle.kts`, `settings.gradle.kts`: Gradle wrapper and version catalog configuration for the Android project. -- `Cargo.toml`: Rust workspace definition pointing to `rust/letterbox-core`. +- `Cargo.toml`: Rust workspace definition for `rust/letterbox-core` and `rust/letterbox-proxy`. - `LICENSE`: MIT license for the project. ## Quickstart diff --git a/scripts/check-doc-drift.sh b/scripts/check-doc-drift.sh new file mode 100755 index 0000000..235c20a --- /dev/null +++ b/scripts/check-doc-drift.sh @@ -0,0 +1,134 @@ +#!/usr/bin/env bash +# check-doc-drift.sh — Detect documentation drift for key CI/workflow claims. +# +# Usage: ./scripts/check-doc-drift.sh +# +# Exits 0 if all checks pass, 1 if any drift is detected. +# Run this locally or in CI to prevent docs from silently going stale. + +set -euo pipefail + +REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)" +WORKFLOWS_README="$REPO_ROOT/.github/workflows/README.md" +ROOT_README="$REPO_ROOT/README.md" +BUILD_YML="$REPO_ROOT/.github/workflows/build.yml" +UI_YML="$REPO_ROOT/.github/workflows/android-ui.yml" +CARGO_TOML="$REPO_ROOT/Cargo.toml" +ANDROID_TEST_DIR="$REPO_ROOT/app/src/androidTest/java/org/joefang/letterbox" + +ERRORS=0 + +fail() { + echo "❌ DRIFT: $1" + ERRORS=$((ERRORS + 1)) +} + +pass() { + echo "✅ $1" +} + +echo "=== Documentation Drift Check ===" +echo "" + +# --- 1. Workflow output names in workflows README must match build.yml --- +echo "--- Checking build.yml output names in workflows README ---" + +for output_name in "test-artifact-name" "prod-release-artifact-name"; do + if grep -qF "$output_name" "$BUILD_YML" && grep -qF "$output_name" "$WORKFLOWS_README"; then + pass "Workflow output '$output_name' found in both build.yml and workflows README" + elif ! grep -qF "$output_name" "$BUILD_YML"; then + fail "Workflow output '$output_name' referenced in README but not in build.yml" + else + fail "Workflow output '$output_name' exists in build.yml but missing from workflows README" + fi +done + +# Check for stale output names that no longer exist in build.yml +# Use word-boundary-aware matching to avoid false positives from substrings +for stale_name in "debug-artifact-name" "release-artifact-name"; do + # Match the stale name as a standalone backtick-delimited identifier (e.g. `debug-artifact-name`) + if grep -qP '(?