Compare commits
8 Commits
v2.7.0
...
6640794721
| Author | SHA1 | Date | |
|---|---|---|---|
| 6640794721 | |||
| 81baadfaf3 | |||
| 35022267dc | |||
| 588e024036 | |||
| eeef089e4a | |||
| 9023899ddb | |||
| 2f153fef56 | |||
| 290a905f8b |
42
.gitea/workflows/renovate.yml
Normal file
42
.gitea/workflows/renovate.yml
Normal file
@@ -0,0 +1,42 @@
|
||||
name: Renovate
|
||||
|
||||
on:
|
||||
# Weekly sweep. Mondays 05:00 UTC — this cron owns the cadence; the repo's
|
||||
# renovate.json5 deliberately has no internal schedule (avoids double-gating).
|
||||
schedule:
|
||||
- cron: '0 5 * * 1'
|
||||
# Manual run for an on-demand sweep from the Actions tab.
|
||||
workflow_dispatch:
|
||||
|
||||
# Never let two Renovate runs touch the repo at once.
|
||||
concurrency:
|
||||
group: renovate
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
renovate:
|
||||
runs-on: docker
|
||||
# Run the Renovate image *as* the job container and invoke the `renovate`
|
||||
# binary directly. The renovatebot/github-action wrapper is a thin Node
|
||||
# action that shells out to `docker run …` — it needs a Docker CLI + socket
|
||||
# inside the job, which the Gitea runner's plain node container has not, so
|
||||
# it died on "Unable to locate executable file: docker". Running the image
|
||||
# directly drops the docker-in-docker requirement entirely.
|
||||
# Full tag pinned; Renovate's github-actions manager keeps it bumped.
|
||||
container:
|
||||
image: ghcr.io/renovatebot/renovate:43.232.0
|
||||
steps:
|
||||
- name: Run Renovate
|
||||
run: renovate
|
||||
env:
|
||||
# Self-hosted Gitea, not github.com.
|
||||
RENOVATE_PLATFORM: gitea
|
||||
RENOVATE_ENDPOINT: https://gitea.jeanlucmakiola.de/api/v1
|
||||
# Bot-account token (Gitea secret). Needs repo read/write + PR scope.
|
||||
RENOVATE_TOKEN: ${{ secrets.RENOVATE_TOKEN }}
|
||||
# Scope to this repo only — no org-wide autodiscovery.
|
||||
RENOVATE_AUTODISCOVER: 'false'
|
||||
RENOVATE_REPOSITORIES: '["makiolaj/calendula"]'
|
||||
# Commits/PRs authored as the bot, not a real maintainer.
|
||||
RENOVATE_GIT_AUTHOR: 'Renovate Bot <renovate@jeanlucmakiola.de>'
|
||||
LOG_LEVEL: info
|
||||
@@ -61,6 +61,21 @@ android {
|
||||
applicationIdSuffix = ".debug"
|
||||
isMinifyEnabled = false
|
||||
}
|
||||
// A locally-installable twin of `release`: same R8 shrinking + obfuscation
|
||||
// and resource shrinking, but debug-signed and given its own applicationId
|
||||
// suffix so it installs alongside both the production app (signed with the
|
||||
// real key) and the debug build. Used to smoke-test a release candidate on
|
||||
// a real device before tagging — R8-only breakage and first-run/permission
|
||||
// states don't surface in the unminified debug build, nor on a device that
|
||||
// already holds the permission. Never published. See docs/RELEASING.md.
|
||||
create("releaseTest") {
|
||||
initWith(getByName("release"))
|
||||
applicationIdSuffix = ".releasetest"
|
||||
signingConfig = signingConfigs.getByName("debug")
|
||||
isMinifyEnabled = true
|
||||
isShrinkResources = true
|
||||
matchingFallbacks += "release"
|
||||
}
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
|
||||
@@ -22,20 +22,44 @@ Published version codes so far: `v0.1.0`→100 … `v1.0.0`→10000 … `v2.0.0`
|
||||
|
||||
## Cutting a release
|
||||
|
||||
1. Move the `## [Unreleased]` section of `CHANGELOG.md` under a new
|
||||
1. **Assemble the release branch.** Create `release/vX.Y.Z` and merge the
|
||||
feature/fix branches that make up this release into it. This branch is the
|
||||
release candidate — everything below happens on it, before it reaches `main`.
|
||||
2. Move the `## [Unreleased]` section of `CHANGELOG.md` under a new
|
||||
`## [X.Y.Z] — <date>` heading (Keep a Changelog format). The text between
|
||||
that heading and the next `## [` becomes both the Gitea release notes and
|
||||
the F-Droid per-version changelog.
|
||||
2. Optionally bump the committed `versionCode`/`versionName` in
|
||||
`app/build.gradle.kts` to match the new version (keeps local builds tidy).
|
||||
3. Commit, then tag and push:
|
||||
3. Bump the committed `versionCode`/`versionName` in `app/build.gradle.kts` to
|
||||
match the new version (keeps local builds tidy; CI overwrites from the tag).
|
||||
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
|
||||
already granted the calendar permission (this is how the v2.7.0 launch
|
||||
crash slipped through). Run:
|
||||
```bash
|
||||
scripts/verify-release.sh
|
||||
```
|
||||
It builds the `releaseTest` variant (same R8 config as `release`, debug-signed
|
||||
with a `.releasetest` suffix so it installs alongside the real app) and resets
|
||||
it to a first-run state. Then, on the device:
|
||||
- launch from a **clean / permission-not-granted** state — the permission
|
||||
screen must appear, no crash;
|
||||
- grant access — the calendar must load;
|
||||
- add both home-screen **widgets** and confirm they render;
|
||||
- exercise this release's headline changes.
|
||||
|
||||
Only proceed once all of that passes on-device.
|
||||
5. Merge `release/vX.Y.Z` into `main`, then tag and push:
|
||||
```bash
|
||||
git tag vX.Y.Z
|
||||
git push origin vX.Y.Z
|
||||
```
|
||||
4. The push triggers the release workflow. **Hold UI releases for on-device
|
||||
6. The push triggers the release workflow. **Hold UI releases for on-device
|
||||
review and explicit go-ahead before tagging.**
|
||||
|
||||
> The `releaseTest` build type exists only for step 4 — it is never published.
|
||||
> The pipeline always builds and signs the real `release` variant from the tag.
|
||||
|
||||
## What the pipeline does
|
||||
|
||||
`release.yaml` has three jobs:
|
||||
|
||||
56
renovate.json5
Normal file
56
renovate.json5
Normal file
@@ -0,0 +1,56 @@
|
||||
{
|
||||
$schema: "https://docs.renovatebot.com/renovate-schema.json",
|
||||
|
||||
extends: [
|
||||
"config:recommended",
|
||||
// chore(deps): … — match the repo's conventional-commit style.
|
||||
":semanticCommits",
|
||||
],
|
||||
|
||||
// No automerge: a dependency bump goes through the same review (and, for
|
||||
// anything touching the build, the same on-device check) as a feature
|
||||
// before it can ride a release — see docs/RELEASING.md and the
|
||||
// "hold release for approval" rule.
|
||||
automerge: false,
|
||||
|
||||
// One reviewable surface; the dashboard issue lists everything pending.
|
||||
dependencyDashboard: true,
|
||||
labels: ["dependencies"],
|
||||
prConcurrentLimit: 5,
|
||||
prHourlyLimit: 0,
|
||||
|
||||
// Cadence is owned by the Gitea Actions cron (.gitea/workflows/renovate.yml,
|
||||
// Mondays) — no internal `schedule` here, so the two don't double-gate and
|
||||
// silently skip a run.
|
||||
|
||||
// Gitea Actions workflows live under .gitea/workflows, not .github — extend
|
||||
// the github-actions manager (same syntax) to watch them too.
|
||||
"github-actions": {
|
||||
fileMatch: ["^\\.gitea/workflows/[^/]+\\.ya?ml$"],
|
||||
},
|
||||
|
||||
packageRules: [
|
||||
// material3 is deliberately pinned to the 1.5 *alpha* line for the
|
||||
// Expressive APIs (see gradle/libs.versions.toml). Follow the alpha train
|
||||
// but keep it in its own PR, reviewed in isolation; revisit the pin when
|
||||
// 1.5.0 stable lands.
|
||||
{
|
||||
matchPackageNames: ["androidx.compose.material3:material3"],
|
||||
ignoreUnstable: false,
|
||||
groupName: "material3 (alpha)",
|
||||
},
|
||||
// Test-only deps: group into one low-noise PR.
|
||||
{
|
||||
matchPackageNames: [
|
||||
"org.junit.jupiter:**",
|
||||
"org.junit.platform:**",
|
||||
"com.google.truth:**",
|
||||
"app.cash.turbine:**",
|
||||
"androidx.test:**",
|
||||
"androidx.test.espresso:**",
|
||||
"androidx.test.ext:**",
|
||||
],
|
||||
groupName: "test dependencies",
|
||||
},
|
||||
],
|
||||
}
|
||||
42
scripts/verify-release.sh
Executable file
42
scripts/verify-release.sh
Executable file
@@ -0,0 +1,42 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Build the release-candidate APK and install it on a connected device for the
|
||||
# mandatory pre-tag on-device check (see docs/RELEASING.md).
|
||||
#
|
||||
# It builds the `releaseTest` variant: the same R8 shrinking + obfuscation and
|
||||
# resource shrinking as the published `release` build, but debug-signed and
|
||||
# with a `.releasetest` applicationId suffix so it installs alongside the
|
||||
# production and debug apps. This is what surfaces release-only breakage (R8
|
||||
# stripping) and first-run states (permission not yet granted) that the
|
||||
# unminified debug build — or a device that already holds the permission —
|
||||
# silently hides.
|
||||
#
|
||||
# Usage: scripts/verify-release.sh
|
||||
set -euo pipefail
|
||||
|
||||
cd "$(dirname "$0")/.."
|
||||
|
||||
PKG="de.jeanlucmakiola.calendula.releasetest"
|
||||
APK="app/build/outputs/apk/releaseTest/app-releaseTest.apk"
|
||||
|
||||
echo "==> Building release-candidate APK (releaseTest, R8 minified)…"
|
||||
./gradlew :app:assembleReleaseTest
|
||||
|
||||
echo "==> Installing $PKG …"
|
||||
adb install -r "$APK"
|
||||
|
||||
echo "==> Resetting to a first-run state (revoking calendar permission)…"
|
||||
# The release build crashed at launch precisely because this state was never
|
||||
# tested. Force it so the permission gate / onboarding is exercised every time.
|
||||
adb shell pm revoke "$PKG" android.permission.READ_CALENDAR 2>/dev/null || true
|
||||
adb shell pm revoke "$PKG" android.permission.WRITE_CALENDAR 2>/dev/null || true
|
||||
|
||||
echo
|
||||
echo "Installed and reset. Now verify ON THE DEVICE before tagging:"
|
||||
echo " 1. Launch from a clean state — the permission screen must appear (no crash)."
|
||||
echo " 2. Grant calendar access — the calendar must load with events."
|
||||
echo " 3. Add both home-screen widgets and confirm they render (not a spinner)."
|
||||
echo " 4. Exercise the release's headline changes end to end."
|
||||
echo
|
||||
echo "Watch for crashes with: adb logcat -b crash"
|
||||
echo "Only tag the release once all of the above pass on a real device."
|
||||
Reference in New Issue
Block a user