6.5 KiB
Repository instructions
Gitea issue workflow
Use this repository's gotcha CLI to list, inspect, create, update, comment on,
and close Gitea issues. Run it from the repository root so the configured Git
remote selects the server and repository:
cargo run -q -p gotcha-cli -- issue list
cargo run -q -p gotcha-cli -- issue list --milestones "first feature complete release"
cargo run -q -p gotcha-cli -- issue show 7
cargo run -q -p gotcha-cli -- issue comment 7 < comment.txt
cargo run -q -p gotcha-cli -- issue close 7
Use gotcha issue list --help for state, kind, keyword, label, milestone,
author, assignee, mention, date, and pagination filters. Grant network access
before invoking commands that contact Gitea in a sandboxed runner.
Required pre-commit gates
Run every gate below from the repository root before committing. Every command must succeed; do not commit code that is unformatted, fails Clippy, or compiles with warnings.
cargo fmt --all -- --check
RUSTFLAGS="-D warnings" cargo check --workspace --all-targets
cargo clippy --workspace --all-targets -- -D warnings
cargo test --workspace
Do not weaken or skip these gates to make a commit pass. Fix the underlying warning, lint, formatting issue, or test failure.
Gitea, app, CLI, and Swift ownership boundary
gotcha_gitea owns Gitea networking and authentication plus the behavior of
Gitea objects: validation, pagination, name-to-ID resolution, mutations,
ownership checks, object relationships, activity targets, commit graphs, and
diff parsing. The app and CLI must not import generated Gitea API modules or
build generated-client configurations. Add a concrete Client operation to
gotcha_gitea instead. Generated response models may cross the boundary when a
frontend only needs to present their fields; the CLI's explicit api request
command is the sole low-level escape hatch.
crates/app owns application state, persistence, preferences, favorites,
content classification, navigation targets, and view-ready UniFFI records. The
CLI owns argument and YAML parsing plus terminal formatting. Do not duplicate
Gitea object transformations or relationship handling in either frontend.
Swift is the native iOS presentation layer. Limit ios/Sources to UIKit and
SwiftUI lifecycle, view-controller navigation, native controls, layout, drawing,
fonts, colors, symbols, accessibility, task cancellation tied to view lifetime,
and Apple presentation integrations such as Quick Look. Swift may map
Rust-provided states to visual treatments and maintain transient control state;
it must not infer domain state from display strings, duplicate Rust
transformations, classify content, or implement persistence and API behavior.
When changing iOS functionality:
- Trace the complete flow before editing and implement Gitea behavior in
gotcha_giteaand app behavior incrates/appfirst. - Prefer view-ready Rust records over exposing raw Gitea models or rebuilding titles, summaries, selections, progress, and categories in Swift.
- Treat a pure Swift helper that does not require an Apple UI framework as a boundary warning; move it to Rust unless it only calculates view geometry.
- Regenerate and commit the UniFFI Swift and C bindings whenever the exported Rust interface changes.
- During review, inspect both sides of the bridge and reject new business logic added to Swift merely because its caller is a view controller.
UI verification conventions
TESTING.md is the source of truth for iOS visual verification and the release
regression suite.
- Update
TESTING.mdin the same commit whenever UI appearance, behavior, navigation, or interaction changes so its scenarios remain current. - For each ordinary commit, run every
TESTING.mdscenario relevant to the changed UI in addition to the required pre-commit gates. Report which visual scenarios were exercised. - When asked to perform a release test, run the complete
TESTING.mdchecklist. Every scenario must succeed before reporting release sign-off; record failures and resolve release blockers instead of skipping them.
iOS simulator build and deployment
This Apple Silicon project builds the simulator app for arm64. Do not disable
code signing: the Rust build script consumes Xcode's generated simulator
entitlement paths. Do not request an x86_64 simulator build unless the
x86_64-apple-ios Rust target has explicitly been installed.
Use this sequence from the repository root:
cd ios
xcodegen generate
xcodebuild \
-project Gotcha.xcodeproj \
-scheme Gotcha \
-configuration Debug \
-sdk iphonesimulator \
-destination 'platform=iOS Simulator,name=iPhone 17 Pro' \
ARCHS=arm64 \
ONLY_ACTIVE_ARCH=YES \
build
gotcha_build_dir="$(
xcodebuild \
-project Gotcha.xcodeproj \
-scheme Gotcha \
-configuration Debug \
-sdk iphonesimulator \
-destination 'platform=iOS Simulator,name=iPhone 17 Pro' \
-showBuildSettings -json \
ARCHS=arm64 \
ONLY_ACTIVE_ARCH=YES |
plutil -extract 0.buildSettings.TARGET_BUILD_DIR raw -o - -
)"
xcrun simctl install booted "$gotcha_build_dir/Gotcha.app"
xcrun simctl launch booted de.rfc1437.gotcha
Before deploying, check for a booted simulator with
xcrun simctl list devices available. If none is booted, boot an available
iPhone (currently xcrun simctl boot "iPhone 17 Pro") and open Simulator.
CoreSimulator access may require running xcodebuild and simctl outside the
workspace sandbox.
Post-issue release deployment
After an issue is verified, committed, pushed, commented on, and closed, deploy the completed version according to the code it changes:
- For CLI changes, build
gotcha-cliin release mode and install the resultinggotchaexecutable in~/.local/bin/so the command is available onPATH. - For iOS app changes, install the completed app on the currently paired iPhone.
- The Gitea crate is shared by the CLI and iOS app, so changes to that crate also require installing the completed app on the paired iPhone.
A purely CLI change does not require an iPhone deployment. If an issue changes both release surfaces, perform both deployments.
Generated build data
Use Xcode's default DerivedData location; do not pass -derivedDataPath.
Cargo's ignored target/ directory is a disposable build cache. Cargo does not
bound or garbage-collect stale target artifacts, so check it with
du -sh target and run cargo clean when disk space is worth a full rebuild.
Do not add a custom cache-pruning tool or disable incremental compilation just
to reduce routine cache usage.