Write a contributing guide, and fix what the forge move left stale (#96)
(docs) Update all the docs to be up to date with current status quo
This commit is contained in:
@@ -20,7 +20,7 @@ the package list (recurring writes, save conflicts, reminder delivery).
|
||||
repository tests. Instrumented tests are a last resort.
|
||||
4. **No network.** The app declares no `INTERNET` permission. Anything that
|
||||
would need one is an explicit, documented product decision first
|
||||
(see the roadmap's idea backlog).
|
||||
(the crash reporter's web-issue path is the worked example).
|
||||
|
||||
## Layers
|
||||
|
||||
@@ -62,9 +62,15 @@ flowchart TD
|
||||
- **`data/prefs/`** — DataStore-backed settings (theme, week start, form
|
||||
field defaults, reminders toggle) and small state (last-used calendar).
|
||||
- **`ui/`** — one package per screen, each with Screen + ViewModel +
|
||||
UiState. Shared pieces in `ui/common/` (OptionCard — the app's only
|
||||
sanctioned selection-dialog style —, recurrence humanizer, FAB column,
|
||||
drawer, transitions).
|
||||
UiState. Shared pieces in `ui/common/` (recurrence humanizer, FAB column,
|
||||
drawer, transitions). Selection pickers are full-screen and come from
|
||||
floret-kit (`FullScreenPicker` / `OptionPicker`); `AlertDialog` is reserved
|
||||
for plain confirmations and the compact recurring-scope choosers.
|
||||
- **`floret-kit/`** — the shared Material 3 Expressive kit for the Floret app
|
||||
family, wired in as a git submodule *and* a Gradle composite build
|
||||
(`includeBuild`), so it is compiled from source rather than resolved as a
|
||||
dependency. Pickers, crash plumbing, and locale/time helpers live there;
|
||||
changing them is a pull request against that repository plus a submodule bump.
|
||||
|
||||
## Navigation
|
||||
|
||||
@@ -81,7 +87,7 @@ exactly like an event tap.
|
||||
## Recurring writes
|
||||
|
||||
The provider's invariants drive the design (learned the hard way, verified
|
||||
on-device — see plan 03):
|
||||
on-device):
|
||||
|
||||
- Recurring rows carry `RRULE` + `DURATION` (no `DTEND`); one-off rows
|
||||
carry `DTEND`.
|
||||
@@ -167,6 +173,7 @@ JUnit 5 + Truth + Turbine on the JVM. The seams that make it work:
|
||||
`CalendarDataSource` is faked (`FakeCalendarDataSource` records writes),
|
||||
mappers parse `ColumnReader`/plain maps instead of cursors, domain logic
|
||||
(recurrence, validation, snapshots, write-value building) is pure. CI
|
||||
(Gitea Actions) runs `lint test assembleDebug` once per pull request; merging a
|
||||
(Forgejo Actions on Codeberg) runs `lint test assembleDebug` once per pull
|
||||
request; merging a
|
||||
bumped `versionName` to `main` builds, signs, and publishes to the self-hosted
|
||||
F-Droid repo and then mints the `vX.Y.Z` tag + release. See docs/RELEASING.md.
|
||||
|
||||
@@ -1,12 +1,35 @@
|
||||
# Building from source
|
||||
|
||||
Calendula builds with the standard Android Gradle toolchain — no extra setup
|
||||
beyond the SDK and a JDK.
|
||||
beyond the SDK, a JDK, and the submodule.
|
||||
|
||||
## Clone
|
||||
|
||||
```bash
|
||||
git clone --recurse-submodules https://codeberg.org/jlmakiola/calendula.git
|
||||
```
|
||||
|
||||
Calendula depends on **[floret-kit](https://codeberg.org/jlmakiola/floret-kit)**,
|
||||
the shared Material 3 Expressive kit, as a git submodule wired in as a Gradle
|
||||
composite build (`includeBuild("floret-kit")` in `settings.gradle.kts`) — it is
|
||||
compiled from source, not resolved from a repository. A clone without the
|
||||
submodule fails to configure. For an existing clone:
|
||||
|
||||
```bash
|
||||
git submodule update --init --recursive
|
||||
```
|
||||
|
||||
## Requirements
|
||||
|
||||
- **Android SDK 36+**
|
||||
- **JDK 17** — if your default JDK is not 17, set `JAVA_HOME` explicitly.
|
||||
- **JDK 17** — not newer; the Android Gradle Plugin requires exactly 17. If your
|
||||
default JDK differs, set `JAVA_HOME` explicitly.
|
||||
- **Android SDK** — platform **37** (`compileSdk`) and **build-tools 36.0.0**.
|
||||
`minSdk` is 29, `targetSdk` 36.
|
||||
|
||||
The SDK is located via `ANDROID_HOME` (or `ANDROID_SDK_ROOT`), or via a
|
||||
gitignored `local.properties` with `sdk.dir`. If you use `local.properties`, note
|
||||
that the composite build needs **its own** copy at `floret-kit/local.properties`;
|
||||
setting `ANDROID_HOME` covers both builds at once and is the simpler route.
|
||||
|
||||
The Gradle wrapper is checked in, so you don't need a system Gradle.
|
||||
|
||||
@@ -14,11 +37,44 @@ The Gradle wrapper is checked in, so you don't need a system Gradle.
|
||||
|
||||
```bash
|
||||
./gradlew assembleDebug # debug APK → app/build/outputs/apk/debug/
|
||||
./gradlew test # JVM unit tests
|
||||
./gradlew test # JVM unit tests (JUnit 5 + Truth + Turbine)
|
||||
./gradlew lint # Android lint
|
||||
```
|
||||
|
||||
A single test class, or a pattern:
|
||||
|
||||
```bash
|
||||
./gradlew testDebugUnitTest --tests "de.jeanlucmakiola.calendula.domain.SimpleRecurrenceTest"
|
||||
./gradlew testDebugUnitTest --tests "*SimpleRecurrence*"
|
||||
```
|
||||
|
||||
Translation-key invariants (stale and orphaned keys are fatal; missing ones are
|
||||
not) are checked outside Gradle:
|
||||
|
||||
```bash
|
||||
python3 scripts/check_translations.py
|
||||
```
|
||||
|
||||
## What CI runs
|
||||
|
||||
`.forgejo/workflows/ci.yaml` reports a single `CI` check per pull request on
|
||||
Codeberg: the reproducible-release guard, then `lintDebug`,
|
||||
`testDebugUnitTest`, `assembleDebug` and a Trivy filesystem scan. Pull requests
|
||||
that touch only docs, F-Droid metadata or the licence skip the Android build and
|
||||
still report green.
|
||||
|
||||
## Release builds
|
||||
|
||||
Release signing and the publishing pipeline are documented separately in
|
||||
[RELEASING.md](RELEASING.md).
|
||||
[RELEASING.md](RELEASING.md). To smoke-test a release candidate locally, the
|
||||
`releaseTest` build type is an R8-shrunk twin of `release`, debug-signed with its
|
||||
own `applicationId` suffix so it installs alongside the real app:
|
||||
|
||||
```bash
|
||||
scripts/verify-release.sh
|
||||
```
|
||||
|
||||
## Contributing
|
||||
|
||||
See [`../CONTRIBUTING.md`](../CONTRIBUTING.md) for the issue-first workflow,
|
||||
which branch to target, and the architectural rules a change is reviewed against.
|
||||
|
||||
@@ -4,19 +4,22 @@ Where to look for what:
|
||||
|
||||
| Document | What it is |
|
||||
|---|---|
|
||||
| [`../CONTRIBUTING.md`](../CONTRIBUTING.md) | How to contribute: issue-first workflow, which branch to target, translations, the rules a change is reviewed against |
|
||||
| [`BUILDING.md`](BUILDING.md) | Building from source: submodule, JDK/SDK requirements, Gradle tasks, what CI runs |
|
||||
| [`ARCHITECTURE.md`](ARCHITECTURE.md) | Orientation tour: principles, layers, navigation, recurring-write / conflict / reminder pipelines, testing |
|
||||
| [`RELEASING.md`](RELEASING.md) | Release process: versioning, the merge-driven pipeline, the two-forge split, secrets, key custody |
|
||||
| [`../CHANGELOG.md`](../CHANGELOG.md) | Release history (Keep a Changelog, SemVer) |
|
||||
| [`../.planning/ROADMAP.md`](../.planning/ROADMAP.md) | Living roadmap: shipped milestones, current scope, idea backlog |
|
||||
| [`../.planning/PROJECT.md`](../.planning/PROJECT.md) | What the project is, stack, naming, infrastructure |
|
||||
| [`../.planning/REQUIREMENTS.md`](../.planning/REQUIREMENTS.md) | Requirement checklist per milestone |
|
||||
| [`../.planning/STATE.md`](../.planning/STATE.md) | Snapshot of where development currently stands |
|
||||
| [`superpowers/specs/`](superpowers/specs/) | The original design spec (2026-06-08) — historical record, not updated |
|
||||
| [`superpowers/plans/`](superpowers/plans/) | Per-milestone implementation plans with task checklists — historical record of how each slice was built, including provider lessons learned |
|
||||
| [Issues](https://codeberg.org/jlmakiola/calendula/issues) + [milestones](https://codeberg.org/jlmakiola/calendula/milestones) | **The roadmap.** What's planned, in progress, and shipped — a milestone maps to its `release/vX.Y.Z` branch |
|
||||
| [`../.planning/PROJECT.md`](../.planning/PROJECT.md) | What the project is: core value, stack + version pins, constraints, naming, forge/release infrastructure |
|
||||
| [`design/`](design/) | Per-feature design notes kept for features whose provider behaviour is worth recording |
|
||||
| [`../fastlane/metadata/android/`](../fastlane/metadata/android/) | Store metadata (single source of truth): descriptions, title, icon, screenshots (DE + EN). Harvested directly by the official F-Droid repo; transformed into the self-hosted repo layout at release time by [`../scripts/fastlane_to_fdroid_localized.sh`](../scripts/fastlane_to_fdroid_localized.sh) |
|
||||
| [`../fdroid-metadata/`](../fdroid-metadata/) | App-level F-Droid control file (`*.yml`: Categories, License, links) for the self-hosted repo's `fdroid update` |
|
||||
| [`fdroid-official/`](fdroid-official/) | Draft recipe + notes for publishing to the **official** F-Droid repo (reproducible build + developer-signed binary) |
|
||||
| [`fdroid-official/`](fdroid-official/) | Recipe + notes for publishing to the **official** F-Droid repo (reproducible build + developer-signed binary) |
|
||||
|
||||
Conventions: plans and specs under `superpowers/` are point-in-time
|
||||
artifacts of the agentic workflow that built each milestone — they get
|
||||
status updates but are never rewritten. The `.planning/` files are living
|
||||
documents and should stay current.
|
||||
Conventions: planning lives in the **issue tracker**, not in this repository. The
|
||||
`.planning/` files that predated it (a roadmap, a development-state snapshot, and
|
||||
a per-milestone requirement checklist) are gone — issues and milestones say the
|
||||
same thing without going stale. `PROJECT.md` is what remains, and it describes
|
||||
the project rather than its plan.
|
||||
`ARCHITECTURE.md` is the authoritative orientation tour: it is updated with the
|
||||
code, and is the right place for a lesson learned about the calendar provider.
|
||||
|
||||
Reference in New Issue
Block a user