Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| eb51175ceb | |||
| bc59200f77 | |||
| ed6b0fa89f | |||
| c503199e06 | |||
| f3f155b5ff |
@@ -38,10 +38,20 @@ jobs:
|
||||
run: |
|
||||
set -e
|
||||
BASE="${{ github.base_ref }}"
|
||||
git fetch --no-tags --depth=1 origin "$BASE"
|
||||
CHANGED=$(git diff --name-only "origin/$BASE...HEAD")
|
||||
# Full (not --depth=1) base fetch so the merge-base is present even when
|
||||
# the PR branch forked several commits back; a shallow tip has no merge
|
||||
# base with a divergent branch and `git diff base...HEAD` aborts.
|
||||
git fetch --no-tags origin "$BASE"
|
||||
MB=$(git merge-base "origin/$BASE" HEAD 2>/dev/null || true)
|
||||
if [ -z "$MB" ]; then
|
||||
# No common ancestor available — don't risk skipping the build.
|
||||
echo "No merge base with origin/$BASE — running the full build to be safe."
|
||||
echo "code=true" >> "$GITHUB_OUTPUT"
|
||||
exit 0
|
||||
fi
|
||||
CHANGED=$(git diff --name-only "$MB" HEAD)
|
||||
echo "Changed files:"; echo "$CHANGED"
|
||||
if echo "$CHANGED" | grep -vE '(\.md$|^docs/|^fdroid-metadata/|^LICENSE$)' | grep -q .; then
|
||||
if echo "$CHANGED" | grep -vE '(\.md$|^docs/|^fdroid-metadata/|^fastlane/|^LICENSE$)' | grep -q .; then
|
||||
echo "code=true" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "code=false" >> "$GITHUB_OUTPUT"
|
||||
|
||||
@@ -222,31 +222,27 @@ jobs:
|
||||
mkdir -p fdroid/repo
|
||||
cp app/build/outputs/apk/release/app-release.apk "fdroid/repo/calendula_v${VERSION}.apk"
|
||||
|
||||
- name: Copy metadata to F-Droid repo
|
||||
# Per-version "What's New": ensure this version's changelog exists in the
|
||||
# fastlane tree (committed at release-cut time for the official repo; this
|
||||
# regenerates it from CHANGELOG.md so the self-hosted repo never depends on
|
||||
# the commit having happened). The transform below then carries it across.
|
||||
- name: Ensure this version's changelog is in the fastlane tree
|
||||
if: env.IS_RELEASE == 'true'
|
||||
run: bash scripts/sync_changelog_to_fastlane.sh
|
||||
|
||||
- name: Build F-Droid metadata from fastlane (single source of truth)
|
||||
run: |
|
||||
mkdir -p fdroid/metadata
|
||||
cp -r fdroid-metadata/* fdroid/metadata/
|
||||
|
||||
# Per-version "What's New" for F-Droid clients: this version's CHANGELOG
|
||||
# section written to changelogs/<versionCode>.txt (same extraction as the
|
||||
# Gitea release notes). en-US only — F-Droid falls back to it for locales
|
||||
# without their own changelog. fdroid update bakes this into the index.
|
||||
- name: Generate F-Droid changelog for this version
|
||||
if: env.IS_RELEASE == 'true'
|
||||
run: |
|
||||
set -e
|
||||
awk -v ver="$VERSION" '
|
||||
$0 ~ "^## \\[" ver "\\]" { flag = 1; next }
|
||||
/^## \[/ { flag = 0 }
|
||||
flag' CHANGELOG.md > /tmp/changelog.txt
|
||||
sed -i -e '/./,$!d' /tmp/changelog.txt
|
||||
if [ ! -s /tmp/changelog.txt ]; then
|
||||
echo "See CHANGELOG.md for $VERSION." > /tmp/changelog.txt
|
||||
fi
|
||||
CL_DIR="fdroid/metadata/de.jeanlucmakiola.calendula/en-US/changelogs"
|
||||
mkdir -p "$CL_DIR"
|
||||
cp /tmp/changelog.txt "$CL_DIR/${VERSION_CODE}.txt"
|
||||
echo "Wrote $CL_DIR/${VERSION_CODE}.txt"
|
||||
# App-level control file (Categories/License/links) for the self-hosted
|
||||
# repo's `fdroid update`.
|
||||
cp fdroid-metadata/de.jeanlucmakiola.calendula.yml fdroid/metadata/
|
||||
# Localized text + graphics + per-version changelogs come from the SAME
|
||||
# fastlane tree the official F-Droid repo harvests from source,
|
||||
# transformed into the F-Droid repo "localized" layout. One source of
|
||||
# truth, both channels.
|
||||
bash scripts/fastlane_to_fdroid_localized.sh \
|
||||
fastlane/metadata/android \
|
||||
fdroid/metadata/de.jeanlucmakiola.calendula
|
||||
|
||||
- name: Generate F-Droid Index
|
||||
run: |
|
||||
|
||||
@@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [2.7.3] — 2026-06-21
|
||||
|
||||
### Fixed
|
||||
- Home-screen widgets no longer get stuck on a loading spinner in the published
|
||||
(F-Droid) release build. They render via Android's background-work system, and
|
||||
release optimisation (R8) was stripping a helper class it loads by name, so the
|
||||
render job never ran. Added the missing keep rule — widgets now load normally.
|
||||
|
||||
## [2.7.2] — 2026-06-21
|
||||
|
||||
### Added
|
||||
|
||||
12
README.md
@@ -1,6 +1,6 @@
|
||||
<div align="center">
|
||||
|
||||
<img src="fdroid-metadata/de.jeanlucmakiola.calendula/en-US/icon.png" width="112" alt="Calendula icon">
|
||||
<img src="fastlane/metadata/android/en-US/images/icon.png" width="112" alt="Calendula icon">
|
||||
|
||||
<h1>Calendula</h1>
|
||||
|
||||
@@ -16,11 +16,11 @@ Reads, writes, and reminds — on top of the system calendar, with zero network
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<img src="fdroid-metadata/de.jeanlucmakiola.calendula/en-US/phoneScreenshots/01-week.png" width="19%" alt="Week view">
|
||||
<img src="fdroid-metadata/de.jeanlucmakiola.calendula/en-US/phoneScreenshots/02-month.png" width="19%" alt="Month view">
|
||||
<img src="fdroid-metadata/de.jeanlucmakiola.calendula/en-US/phoneScreenshots/04-detail.png" width="19%" alt="Event detail">
|
||||
<img src="fdroid-metadata/de.jeanlucmakiola.calendula/en-US/phoneScreenshots/05-edit.png" width="19%" alt="Event form">
|
||||
<img src="fdroid-metadata/de.jeanlucmakiola.calendula/en-US/phoneScreenshots/06-onboarding.png" width="19%" alt="Reminder onboarding">
|
||||
<img src="fastlane/metadata/android/en-US/images/phoneScreenshots/01-week.png" width="19%" alt="Week view">
|
||||
<img src="fastlane/metadata/android/en-US/images/phoneScreenshots/02-month.png" width="19%" alt="Month view">
|
||||
<img src="fastlane/metadata/android/en-US/images/phoneScreenshots/04-detail.png" width="19%" alt="Event detail">
|
||||
<img src="fastlane/metadata/android/en-US/images/phoneScreenshots/05-edit.png" width="19%" alt="Event form">
|
||||
<img src="fastlane/metadata/android/en-US/images/phoneScreenshots/06-onboarding.png" width="19%" alt="Reminder onboarding">
|
||||
</p>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -28,8 +28,8 @@ android {
|
||||
// which builds this version and then creates the matching vX.Y.Z tag +
|
||||
// release itself (versionCode is pinned to MAJOR*10000 + MINOR*100 +
|
||||
// PATCH from versionName, e.g. 2.7.2 -> 20702). See docs/RELEASING.md.
|
||||
versionCode = 20702
|
||||
versionName = "2.7.2"
|
||||
versionCode = 20703
|
||||
versionName = "2.7.3"
|
||||
|
||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
@@ -47,6 +47,11 @@ android {
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
// Keep release builds reproducible for F-Droid: don't let AGP embed
|
||||
// build-environment git metadata (META-INF/version-control-info.textproto),
|
||||
// whose `revision`/path content varies by build machine and is the only
|
||||
// thing that otherwise differs from a clean from-source rebuild.
|
||||
vcsInfo { include = false }
|
||||
isMinifyEnabled = true
|
||||
isShrinkResources = true
|
||||
proguardFiles(
|
||||
|
||||
11
app/proguard-rules.pro
vendored
@@ -15,3 +15,14 @@
|
||||
# Keep the generated Room database implementations fully intact.
|
||||
-keep class * extends androidx.room.RoomDatabase { *; }
|
||||
-dontwarn androidx.room.paging.**
|
||||
|
||||
# WorkManager instantiates an InputMerger reflectively (Class.newInstance) from
|
||||
# the fully-qualified class name persisted in the WorkSpec, so the class must
|
||||
# keep both its name and a no-arg constructor. Glance renders every widget
|
||||
# through a WorkManager worker (androidx.glance.session.SessionWorker) whose
|
||||
# default merger is androidx.work.OverwritingInputMerger. Under R8 full mode
|
||||
# (AGP 9 default) that unused no-arg constructor was stripped, so WorkManager
|
||||
# threw "OverwritingInputMerger has no zero argument constructor", the
|
||||
# SessionWorker never ran, and widgets were stuck on their loading layout
|
||||
# (a blank spinner) in release builds. Keep every InputMerger's name + ctor.
|
||||
-keep class * extends androidx.work.InputMerger { <init>(...); }
|
||||
|
||||
@@ -12,7 +12,9 @@ Where to look for what:
|
||||
| [`../.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 |
|
||||
| [`../fdroid-metadata/`](../fdroid-metadata/) | F-Droid/fastlane store metadata: descriptions, icon, screenshots (DE + EN) |
|
||||
| [`../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) |
|
||||
|
||||
Conventions: plans and specs under `superpowers/` are point-in-time
|
||||
artifacts of the agentic workflow that built each milestone — they get
|
||||
|
||||
@@ -33,7 +33,15 @@ Published version codes so far: `v0.1.0`→100 … `v1.0.0`→10000 … `v2.0.0`
|
||||
the F-Droid per-version changelog.
|
||||
3. Bump the committed `versionName` (and `versionCode`) in
|
||||
`app/build.gradle.kts` to the new version. **This bump is what triggers the
|
||||
release** when the branch merges to `main`.
|
||||
release** when the branch merges to `main`. Then run
|
||||
```bash
|
||||
scripts/sync_changelog_to_fastlane.sh
|
||||
```
|
||||
and commit the generated
|
||||
`fastlane/metadata/android/en-US/changelogs/<versionCode>.txt`. This is what
|
||||
makes the **official** F-Droid repo show this version's changelog (it reads
|
||||
the changelog from the tagged source tree). The self-hosted pipeline
|
||||
regenerates it regardless, so forgetting only affects the official listing.
|
||||
4. **Verify the release build on a real device** — the mandatory gate. The
|
||||
shipped APK is R8-shrunk/obfuscated, and bugs that only appear there, or
|
||||
only on first run, never show up in the debug build or on a device that
|
||||
|
||||
94
docs/fdroid-official/README.md
Normal file
@@ -0,0 +1,94 @@
|
||||
# Official F-Droid submission (draft)
|
||||
|
||||
Goal: publish Calendula to the **official F-Droid repo** *alongside* the
|
||||
self-hosted repo, as **one app** — same signed binary in both channels, so
|
||||
existing self-hosted users migrate with no reinstall and no data loss.
|
||||
|
||||
This folder holds the **draft** fdroiddata recipe. Nothing here is submitted
|
||||
yet. The self-hosted pipeline (`../../fdroid-metadata/`, `.gitea/workflows/release.yaml`)
|
||||
is unaffected by these files.
|
||||
|
||||
## Publishing model: reproducible build + developer-signed binary
|
||||
|
||||
F-Droid builds Calendula from source on its buildserver, then verifies the
|
||||
output is byte-for-byte identical to **our** signed APK (fetched via the
|
||||
`Binaries` URL). On a match it publishes **our** binary, signed with **our**
|
||||
key — identified by `AllowedAPKSigningKeys`. Result: official and self-hosted
|
||||
both carry the same signature. If a build ever fails to match, F-Droid simply
|
||||
skips that version (fails safe — no bad publish).
|
||||
|
||||
## Verification status (2026-06-21)
|
||||
|
||||
- ✅ **Run-to-run reproducible** — `v2.7.0` built twice from a clean worktree
|
||||
(R8 minify + resource-shrink, build cache off) → byte-for-byte identical
|
||||
(`sha256 568c944a…`).
|
||||
- ✅ **Cross-JDK reproducible** — rebuilt with JDK 17 and JDK 21 → identical
|
||||
APK. JDK version is not a sensitivity, so it need not be pinned.
|
||||
- ✅ **Tag self-consistent** — committed `versionCode`/`versionName` already
|
||||
equal the tag-derived values, so F-Droid building the tag as-is matches the
|
||||
CI-published binary (CI's `sed` substitution is a no-op).
|
||||
- ✅ **App signing cert SHA-256 extracted** from published APKs (identical
|
||||
across v1.0.0 / v2.0.0 / v2.4.0): `5cdaee8e…`. No keystore needed.
|
||||
- ✅ **Eligibility** — MIT, 100% FOSS deps (no Play Services / Firebase /
|
||||
analytics / billing), no `INTERNET` permission, no native code.
|
||||
- ✅ **End-to-end reproducible vs the DISTRIBUTED binary** — built tag `v2.7.1`
|
||||
from source and compared against the published `calendula_v2.7.1.apk`: every
|
||||
app entry (dex / resources / assets / manifest) byte-identical. The only
|
||||
difference was `META-INF/version-control-info.textproto` (AGP's git metadata,
|
||||
env-dependent). Fixed with `vcsInfo { include = false }` on the release build;
|
||||
re-validated → 0 non-signature differences. **Takes effect from the first
|
||||
release built after that change — submit the recipe starting at that version**
|
||||
(v2.7.1 and earlier still embed the textproto and won't verify).
|
||||
- ⚠️ **Not yet proven**: cross-host / fixed-build-path reproducibility on
|
||||
F-Droid's buildserver (low risk for a no-NDK pure-JVM app; with vcsInfo
|
||||
disabled, the env-dependent field is gone; F-Droid confirms at review).
|
||||
- ✅ **Buildserver toolchain supported** (checked 2026-06-21):
|
||||
- **Gradle 9.5.1** is in F-Droid's gradle-transparency-log (`checksums.json`)
|
||||
with a verified sha256, so `gradlew.py` will download + verify + run it.
|
||||
- **AGP 9.2** is in `gradlew.py`'s `MIN_GRADLE_VERSION` map (`9.2 -> 9.4.1`).
|
||||
- **JDK 17** is standard on the buildserver (AGP 9.2 requires exactly 17).
|
||||
- **build-tools 36.0.0 / android-37**: not statically preinstalled (baseline
|
||||
stops at 33), but `provision-android-sdk` makes `$ANDROID_HOME/build-tools`
|
||||
and `/platforms` group-writable so AGP/Gradle install newer ones on demand.
|
||||
|
||||
## Before submitting — checklist
|
||||
|
||||
1. Confirm the `Binaries` URL is publicly reachable and stable long-term, e.g.
|
||||
`https://apps.dev.jeanlucmakiola.de/dev/fdroid/repo/calendula_v2.7.0.apk`
|
||||
resolves to the dev-signed APK. F-Droid re-fetches it on every build.
|
||||
2. Confirm F-Droid's buildserver supports the toolchain (see timing risk).
|
||||
3. (Recommended) Reproduce one published release end-to-end: build the tag from
|
||||
source, strip signatures, and diff against the downloaded `calendula_v<ver>.apk`
|
||||
to confirm the from-source build matches the *distributed* binary — not just
|
||||
another local build.
|
||||
|
||||
## Submission steps (fdroiddata, GitLab)
|
||||
|
||||
1. Fork `https://gitlab.com/fdroid/fdroiddata`.
|
||||
2. Copy `de.jeanlucmakiola.calendula.yml` to `metadata/` in the fork.
|
||||
3. Test locally with `fdroid build -v de.jeanlucmakiola.calendula` and
|
||||
`fdroid lint de.jeanlucmakiola.calendula` (and `fdroid readmeta`).
|
||||
4. Open a Merge Request. Initial review can take weeks to months; the
|
||||
self-hosted repo keeps serving in the meantime, so there's no rush.
|
||||
|
||||
## Listing metadata (descriptions, screenshots, icon)
|
||||
|
||||
These are **not** in the recipe `.yml`. F-Droid's `fdroid update` harvests them
|
||||
automatically from the fastlane tree in the app's source repo:
|
||||
|
||||
fastlane/metadata/android/<locale>/
|
||||
short_description.txt full_description.txt title.txt
|
||||
images/icon.png images/phoneScreenshots/*.png
|
||||
changelogs/<versionCode>.txt (optional, per release)
|
||||
|
||||
This is the single source of truth: en-US + de-DE already exist there, and the
|
||||
self-hosted repo is generated from the same tree at release time via
|
||||
`scripts/fastlane_to_fdroid_localized.sh`. Nothing extra to add to fdroiddata —
|
||||
F-Droid picks the listing up from source. (Screenshots may not be committed to
|
||||
the fdroiddata repo anyway, so the source-tree fastlane layout is required.)
|
||||
|
||||
Per-version changelogs: the self-hosted release workflow generates
|
||||
`changelogs/<versionCode>.txt` at release time. For the official repo to show a
|
||||
changelog, that file must be committed into `fastlane/metadata/android/<locale>/changelogs/`
|
||||
at the tagged commit — wire this into the release/version-bump step, or accept
|
||||
no in-client changelog for the official listing initially.
|
||||
58
docs/fdroid-official/de.jeanlucmakiola.calendula.yml
Normal file
@@ -0,0 +1,58 @@
|
||||
# ---------------------------------------------------------------------------
|
||||
# DRAFT fdroiddata metadata for the OFFICIAL F-Droid repository.
|
||||
#
|
||||
# This is NOT the self-hosted metadata (that lives in ../../fdroid-metadata/).
|
||||
# When submitting, this file's contents go to fdroiddata on GitLab as
|
||||
# metadata/de.jeanlucmakiola.calendula.yml
|
||||
# See README.md in this folder for the verification status and submission steps.
|
||||
#
|
||||
# Publishing model: REPRODUCIBLE BUILD + developer-signed binary.
|
||||
# F-Droid builds from source on its buildserver, then verifies the result is
|
||||
# identical to our own signed APK (fetched via `Binaries`). If it matches,
|
||||
# F-Droid publishes OUR binary signed with OUR key (`AllowedAPKSigningKeys`),
|
||||
# so the official and self-hosted channels carry the SAME signature and users
|
||||
# migrate between them with no reinstall / no data loss.
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
Categories:
|
||||
- Time
|
||||
License: MIT
|
||||
AuthorName: Jean-Luc Makiola
|
||||
SourceCode: https://gitea.jeanlucmakiola.de/makiolaj/calendula
|
||||
IssueTracker: https://gitea.jeanlucmakiola.de/makiolaj/calendula/issues
|
||||
Changelog: https://gitea.jeanlucmakiola.de/makiolaj/calendula/src/branch/main/CHANGELOG.md
|
||||
|
||||
AutoName: Calendula
|
||||
|
||||
RepoType: git
|
||||
Repo: https://gitea.jeanlucmakiola.de/makiolaj/calendula.git
|
||||
|
||||
# IMPORTANT: the first build entry MUST target the first release that contains
|
||||
# `vcsInfo { include = false }` (added on branch chore/release-verification-process).
|
||||
# v2.7.1 and earlier embed META-INF/version-control-info.textproto, whose
|
||||
# env-dependent git metadata breaks reproducibility — they will NOT verify.
|
||||
# Update the versionName/versionCode/commit/Binaries below once that release is
|
||||
# tagged (e.g. v2.7.2 -> versionCode 20702). Values below are placeholders.
|
||||
Builds:
|
||||
- versionName: 2.7.2
|
||||
versionCode: 20702
|
||||
commit: v2.7.2
|
||||
subdir: app
|
||||
gradle:
|
||||
- yes
|
||||
# No NDK / no flavors. The release buildType applies a signingConfig only
|
||||
# when key.properties exists; on the buildserver it does not, so this
|
||||
# produces the unsigned APK F-Droid compares against our binary.
|
||||
|
||||
# SHA-256 of our app signing certificate (public; embedded in every published
|
||||
# APK). Locks F-Droid to publish only binaries signed with our key.
|
||||
AllowedAPKSigningKeys: 5cdaee8eb31cb0df9157c646ae3ec8b3dc43b5bb72624e088c9ddea0c4eb5ec1
|
||||
|
||||
# Our own developer-signed APK for reproducible-build verification. %v -> the
|
||||
# versionName, so v2.7.2 resolves to calendula_v2.7.2.apk on the self-hosted repo.
|
||||
Binaries: https://apps.dev.jeanlucmakiola.de/dev/fdroid/repo/calendula_v%v.apk
|
||||
|
||||
AutoUpdateMode: Version v%v
|
||||
UpdateCheckMode: Tags
|
||||
CurrentVersion: 2.7.2
|
||||
CurrentVersionCode: 20702
|
||||
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 108 KiB After Width: | Height: | Size: 108 KiB |
|
Before Width: | Height: | Size: 85 KiB After Width: | Height: | Size: 85 KiB |
|
Before Width: | Height: | Size: 80 KiB After Width: | Height: | Size: 80 KiB |
|
Before Width: | Height: | Size: 106 KiB After Width: | Height: | Size: 106 KiB |
|
Before Width: | Height: | Size: 116 KiB After Width: | Height: | Size: 116 KiB |
|
Before Width: | Height: | Size: 156 KiB After Width: | Height: | Size: 156 KiB |
1
fastlane/metadata/android/de-DE/title.txt
Normal file
@@ -0,0 +1 @@
|
||||
Calendula
|
||||
8
fastlane/metadata/android/en-US/changelogs/20701.txt
Normal file
@@ -0,0 +1,8 @@
|
||||
### Fixed
|
||||
- Fixed the app crashing immediately on launch whenever calendar access hadn't
|
||||
been granted yet (a fresh install, or after revoking the permission). The app
|
||||
set up its live calendar-change listener before the permission screen could
|
||||
appear, which newer Android versions reject outright — so the app died before
|
||||
you could grant access. The listener now waits for the permission and attaches
|
||||
itself the moment it's granted.
|
||||
|
||||
6
fastlane/metadata/android/en-US/changelogs/20703.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
### Fixed
|
||||
- Home-screen widgets no longer get stuck on a loading spinner in the published
|
||||
(F-Droid) release build. They render via Android's background-work system, and
|
||||
release optimisation (R8) was stripping a helper class it loads by name, so the
|
||||
render job never ran. Added the missing keep rule — widgets now load normally.
|
||||
|
||||
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 108 KiB After Width: | Height: | Size: 108 KiB |
|
Before Width: | Height: | Size: 87 KiB After Width: | Height: | Size: 87 KiB |
|
Before Width: | Height: | Size: 77 KiB After Width: | Height: | Size: 77 KiB |
|
Before Width: | Height: | Size: 106 KiB After Width: | Height: | Size: 106 KiB |
|
Before Width: | Height: | Size: 117 KiB After Width: | Height: | Size: 117 KiB |
|
Before Width: | Height: | Size: 135 KiB After Width: | Height: | Size: 135 KiB |
1
fastlane/metadata/android/en-US/title.txt
Normal file
@@ -0,0 +1 @@
|
||||
Calendula
|
||||
48
scripts/fastlane_to_fdroid_localized.sh
Executable file
@@ -0,0 +1,48 @@
|
||||
#!/usr/bin/env bash
|
||||
# Single source of truth: fastlane/metadata/android/<locale>/ feeds BOTH the
|
||||
# official F-Droid repo (harvested from source automatically) and the
|
||||
# self-hosted repo. This script transforms the fastlane layout into the F-Droid
|
||||
# "localized" layout that the self-hosted `fdroid update` consumes, so we don't
|
||||
# maintain two copies.
|
||||
#
|
||||
# usage: fastlane_to_fdroid_localized.sh <fastlane_android_dir> <out_localized_dir>
|
||||
# e.g. scripts/fastlane_to_fdroid_localized.sh \
|
||||
# fastlane/metadata/android \
|
||||
# fdroid/metadata/de.jeanlucmakiola.calendula
|
||||
#
|
||||
# Mapping (fastlane -> F-Droid repo localized):
|
||||
# short_description.txt -> summary.txt
|
||||
# full_description.txt -> description.txt
|
||||
# title.txt -> name.txt
|
||||
# images/icon.png -> icon.png
|
||||
# images/phoneScreenshots/* -> phoneScreenshots/*
|
||||
# changelogs/<versionCode>.txt -> changelogs/<versionCode>.txt
|
||||
# (changelogs are seeded into the fastlane tree by
|
||||
# scripts/sync_changelog_to_fastlane.sh.)
|
||||
set -euo pipefail
|
||||
|
||||
SRC="${1:?need fastlane android dir, e.g. fastlane/metadata/android}"
|
||||
OUT="${2:?need output localized dir, e.g. fdroid/metadata/<appid>}"
|
||||
|
||||
shopt -s nullglob
|
||||
for locdir in "$SRC"/*/; do
|
||||
loc="$(basename "$locdir")"
|
||||
dst="$OUT/$loc"
|
||||
mkdir -p "$dst"
|
||||
[ -f "$locdir/short_description.txt" ] && cp "$locdir/short_description.txt" "$dst/summary.txt"
|
||||
[ -f "$locdir/full_description.txt" ] && cp "$locdir/full_description.txt" "$dst/description.txt"
|
||||
[ -f "$locdir/title.txt" ] && cp "$locdir/title.txt" "$dst/name.txt"
|
||||
[ -f "$locdir/images/icon.png" ] && cp "$locdir/images/icon.png" "$dst/icon.png"
|
||||
if [ -d "$locdir/images/phoneScreenshots" ]; then
|
||||
mkdir -p "$dst/phoneScreenshots"
|
||||
cp "$locdir"images/phoneScreenshots/* "$dst/phoneScreenshots/"
|
||||
fi
|
||||
# Per-version changelogs live in the same fastlane tree (see
|
||||
# scripts/sync_changelog_to_fastlane.sh) and map straight across.
|
||||
if [ -d "$locdir/changelogs" ]; then
|
||||
mkdir -p "$dst/changelogs"
|
||||
cp "$locdir"changelogs/* "$dst/changelogs/"
|
||||
fi
|
||||
done
|
||||
|
||||
echo "Built F-Droid localized metadata in '$OUT' from '$SRC'"
|
||||
41
scripts/sync_changelog_to_fastlane.sh
Executable file
@@ -0,0 +1,41 @@
|
||||
#!/usr/bin/env bash
|
||||
# Write the current version's CHANGELOG.md section into the fastlane changelog
|
||||
# file that F-Droid harvests: fastlane/metadata/android/en-US/changelogs/<code>.txt
|
||||
# (en-US is F-Droid's fallback locale, so it covers every language).
|
||||
#
|
||||
# Run this when cutting a release (after editing CHANGELOG.md and bumping
|
||||
# versionName in app/build.gradle.kts) and COMMIT the result, so the OFFICIAL
|
||||
# F-Droid repo — which reads the changelog from the tagged source tree — shows
|
||||
# this version's "What's New". The self-hosted release pipeline also runs it so
|
||||
# its changelog never depends on the file having been committed. Idempotent.
|
||||
#
|
||||
# Extraction matches the awk used for the Gitea release notes so all three
|
||||
# (release notes, self-hosted changelog, official changelog) stay in sync.
|
||||
set -euo pipefail
|
||||
cd "$(dirname "$0")/.." # repo root
|
||||
|
||||
VERSION=$(grep -oP 'versionName\s*=\s*"\K[^"]+' app/build.gradle.kts)
|
||||
[ -n "$VERSION" ] || { echo "No versionName in app/build.gradle.kts" >&2; exit 1; }
|
||||
MAJOR=${VERSION%%.*}; rest=${VERSION#*.}; MINOR=${rest%%.*}; PATCH=${rest##*.}
|
||||
MAJOR=${MAJOR:-0}; MINOR=${MINOR:-0}; PATCH=${PATCH:-0}
|
||||
VERSION_CODE=$(( MAJOR * 10000 + MINOR * 100 + PATCH ))
|
||||
|
||||
CL_DIR="fastlane/metadata/android/en-US/changelogs"
|
||||
mkdir -p "$CL_DIR"
|
||||
OUT="$CL_DIR/${VERSION_CODE}.txt"
|
||||
|
||||
awk -v ver="$VERSION" '
|
||||
$0 ~ "^## \\[" ver "\\]" { flag = 1; next }
|
||||
/^## \[/ { flag = 0 }
|
||||
flag' CHANGELOG.md > "$OUT"
|
||||
# Trim leading blank lines (same as the pipeline did).
|
||||
sed -i -e '/./,$!d' "$OUT"
|
||||
if [ ! -s "$OUT" ]; then
|
||||
echo "See CHANGELOG.md for $VERSION." > "$OUT"
|
||||
fi
|
||||
|
||||
CHARS=$(wc -m < "$OUT" | tr -d ' ')
|
||||
echo "Wrote $OUT (version $VERSION, code $VERSION_CODE, ${CHARS} chars)"
|
||||
if [ "$CHARS" -gt 500 ]; then
|
||||
echo " note: >500 chars — F-Droid may truncate this changelog in-client." >&2
|
||||
fi
|
||||