Files
thoughtsync/.gitignore
T
bvandeusen d0a9c73bf9
Desktop (Tauri) / Windows installer (cross-compiled) (push) Successful in 2m54s
Android / Kotlin + Rust (APK) (push) Failing after 4m10s
Desktop (Tauri) / Tauri desktop (Linux) (push) Successful in 5m15s
Desktop (Tauri) / Update manifest (push) Successful in 3s
android: sign the release build, and give it a version that rises
Two separate reasons updates were impossible, both fixed here.

**Every CI build was signed with a different key** (issue #2803, measured with
`apksigner --print-certs` across two runs). No signing config meant AGP's debug
keystore, which AGP GENERATES when absent — and every job starts from a fresh
container. So no build could ever be installed over another: the only way
through was uninstall-then-install, which deletes the app's database and every
local note with it.

**versionCode was hardcoded to 1.** `build.gradle.kts` has read a
`THOUGHTSYNC_VERSION_CODE` property since the skeleton landed; nothing ever
passed it. Even with signing fixed, every APK would have claimed to be the same
version and nothing could tell a newer one existed. It now comes from
`GITHUB_RUN_NUMBER` — the same monotonic counter the desktop's version scheme
already uses, needing no state between runs and immune to the shallow checkout
that makes a commit count useless here. The version NAME comes from the
desktop's `build-version.sh`, so both surfaces report one product version rather
than two that can disagree.

**The alias is hardcoded, not a secret.** It is fixed for the life of the app and
already written into the certificate every install carries; hiding it would buy
nothing and stop this file describing its own signing. Two secrets, not three —
and PKCS12 cannot hold a key password distinct from the store password anyway,
so `keyPassword` is the same value by necessity rather than by shortcut.

**The lane now builds RELEASE when it can sign, debug when it cannot.** That is
not cosmetic. A debug APK is `debuggable`, which on a phone holding personal
notes and a device sync token means anyone with adb can read both.

Which meant confronting something the release path would have shipped quietly:
`cargoNdkDebug` was hardcoded to the debug Cargo profile and every variant took
its `.so` from it, so `assembleRelease` would have packaged an UNOPTIMISED store
and sync engine. Now one `cargoNdk` task takes its profile from a property, and
the whole run uses one profile. A debug/release task pair would have been the
tidier shape and would have made a run that both type-checks and packages pay
the four-minute cross-compile twice — this runner has no working Gradle or Cargo
cache, so that cost is real on every push.

The run prints the signing certificate after assembling, so the fingerprint can
be compared against the one recorded at generation. Signing with the wrong key
produces a perfectly valid APK that simply refuses to install — a failure that
otherwise surfaces on the device, long after the run is green.

`.gitignore` learns `*.jks`, `*.keystore`, `*.p12`, `*.b64` first, so generating
a keystore anywhere near this tree cannot go wrong.

Also corrects the record: the comment this replaces cited "Scribe task 2136" as
though it were a standing rule. It is not one — none of the 46 always-on rules
mentions signing keys. 2136 is a desktop-updater task whose REASONING got
repeated until it sounded like policy. The reasoning holds, and holds harder on
Android where a key cannot be rotated without the original, so the practice is
unchanged; the citation is now honest about what it is.
2026-08-20 19:03:57 -04:00

208 lines
4.5 KiB
Plaintext

# ---> Python
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# UV
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
#uv.lock
# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock
# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm.fming.dev/latest/usage/project/#working-with-version-control
.pdm.toml
.pdm-python
.pdm-build/
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/
# PyCharm
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
# Ruff stuff:
.ruff_cache/
# PyPI configuration file
.pypirc
# Rust workspace build output (one target dir for core + desktop + android)
/target/
# Android / Gradle build output.
#
# `local.properties` holds the machine's SDK path — it is per-workstation and
# must never be committed; CI gets the SDK from ANDROID_HOME in the image.
# The wrapper JAR is deliberately NOT ignored: it is how a clean checkout gets
# the right Gradle without one installed first.
android/.gradle/
android/build/
android/app/build/
android/local.properties
.kotlin/
# Locally-downloaded APKs for emulator/device testing.
#
# CI builds these and attaches them to the run as artifacts; a copy sitting in
# the working tree is a convenience, never a source. Ignored because they are
# ~57 MB and `git add -A` would otherwise put one in history forever.
*.apk
# Signing material. NEVER committed — an Android signing key cannot be rotated
# without the original (v3 lineage needs it), so a leaked or lost one means every
# install has to be removed and replaced by hand. Listed before any keystore
# exists so that generating one in this directory cannot go wrong.
*.jks
*.keystore
*.p12
*.b64