diff --git a/.opencode/skills/release/SKILL.md b/.opencode/skills/release/SKILL.md index 64292fc34..75f970a87 100644 --- a/.opencode/skills/release/SKILL.md +++ b/.opencode/skills/release/SKILL.md @@ -76,12 +76,26 @@ Ensure every user-facing change is represented in `CHANGELOG.md`. Dependency bum 3. Add a new empty `## [Unreleased]` section above the release section. 4. Keep fork/CI/signing-only changes in a `### Fork infrastructure` subsection when relevant. -### Step 5: Clear Snapshot Version +### Step 5: Choose Bump Type and Set Version + +Based on the changes since the last release, decide the bump type: + +- **major** -- breaking changes, new major API +- **minor** -- new features, backwards-compatible +- **patch** -- bug fixes only (default) + +If the version already has the correct numbers but carries a `-SNAPSHOT` suffix, strip it: ```bash ./gradlew :app:clearPreRelease ``` +Otherwise, bump to the new version directly: + +```bash +./gradlew :app:bumpMajor # or bumpMinor, or bumpPatch +``` + Verify `app/version.properties` version matches the changelog release section exactly. ### Step 6: Commit And Push Release @@ -95,7 +109,7 @@ git push origin main The auto-tag workflow runs only when `app/version.properties` changes on `main` and the version is not a snapshot/pre-release. -### Step 7: Monitor Tag And Release Workflows +### Step 7: Monitor Tag and Release ```bash gh run list --limit 5 @@ -109,22 +123,7 @@ Expected flow: Do not manually create tags. CI handles tags and releases. -### Step 8: Start Next Development Cycle - -After the release is published: - -```bash -./gradlew :app:bumpSnapshot -``` - -Ensure `CHANGELOG.md` still has an empty `## [Unreleased]` section, then commit: - -```bash -NEXT_VERSION=$(grep 'versioning-plugin.versionName' app/version.properties | cut -d= -f2 | tr -d '[:space:]') -git add app/version.properties CHANGELOG.md -git commit -m "chore: start $NEXT_VERSION" -git push origin main -``` +No further action is needed after the release is published. The version in `app/version.properties` stays at the release version until the next release is cut. ## What Not To Do @@ -153,9 +152,8 @@ git push origin main - [ ] Repository has full history/tags if using git log for release notes - [ ] Reviewed commits since latest tag - [ ] Updated `CHANGELOG.md` release section -- [ ] Ran `./gradlew :app:clearPreRelease` +- [ ] Chose bump type (major/minor/patch) and set version - [ ] Verified version matches changelog section - [ ] Committed `app/version.properties` and `CHANGELOG.md` together - [ ] Pushed to main - [ ] Confirmed auto-tag and release workflows passed -- [ ] Ran `./gradlew :app:bumpSnapshot` and committed next snapshot diff --git a/.opencode/skills/setup-android-release/SKILL.md b/.opencode/skills/setup-android-release/SKILL.md index 6d482a7bb..31eec2b22 100644 --- a/.opencode/skills/setup-android-release/SKILL.md +++ b/.opencode/skills/setup-android-release/SKILL.md @@ -300,27 +300,22 @@ cat gpg-private.txt | gh secret set GPG_PRIVATE_KEY --repo After initial setup, the day-to-day release flow is: ```bash -# 1. Update CHANGELOG.md: rename [Unreleased] to [version] with date -# Example: ## [1.17.1] - 2026-06-30 +# 1. Choose bump type based on changes: major / minor / patch + +# 2. Bump version (or clear SNAPSHOT if version is already correct) +./gradlew :app:bumpPatch # or bumpMinor, or bumpMajor -# 2. Prepare release version (removes -SNAPSHOT suffix) -./gradlew :app:clearPreRelease +# 3. Update CHANGELOG.md: rename [Unreleased] to [version] with date +# Example: ## [1.17.1] - 2026-06-30 -# 3. Commit and push +# 4. Commit and push git add app/version.properties CHANGELOG.md git commit -m "release: " git push origin main -# 4. Auto-tag fires → creates GPG-signed tag → release.yml builds APK +# 5. Auto-tag fires → creates GPG-signed tag → release.yml builds APK # Release notes are extracted from CHANGELOG.md entry matching the version # (wait ~8 minutes for CI) - -# 5. Start next development cycle -./gradlew :app:bumpSnapshot -# Add a new [Unreleased] section to CHANGELOG.md -git add app/version.properties CHANGELOG.md -git commit -m "chore: start -SNAPSHOT" -git push origin main ``` The auto-tag workflow only fires when: @@ -412,7 +407,7 @@ After setup, report: 1. Which workflow files were created 2. Which secrets were set (names only, never values) 3. The release URL if a release was triggered -4. How to cut the next release (clearPreRelease → push → bumpSnapshot cycle) +4. How to cut the next release (choose bump type → bumpMajor/bumpMinor/bumpPatch → push) When cutting a release, report: 1. The CHANGELOG.md changes (what was moved from [Unreleased] to [version]) diff --git a/RELEASE.md b/RELEASE.md index 8a6bc3716..1fd2f8e83 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -14,29 +14,27 @@ Releases are fully automated via GitHub Actions: ## Cutting a release ```bash -# 1. Update CHANGELOG.md: rename [Unreleased] to [version] with today's date -# Example: ## [1.17.1] - 2026-06-30 +# 1. Choose bump type based on changes: major / minor / patch -# 2. Remove SNAPSHOT suffix +# 2. Bump version (or clear SNAPSHOT if version is already correct) +./gradlew :app:bumpPatch # or bumpMinor, or bumpMajor +# If only removing -SNAPSHOT suffix: ./gradlew :app:clearPreRelease -# 3. Commit and push +# 3. Update CHANGELOG.md: rename [Unreleased] to [version] with today's date +# Example: ## [1.17.1] - 2026-06-30 + +# 4. Commit and push git add app/version.properties CHANGELOG.md git commit -m "release: $(grep 'versionName' app/version.properties | cut -d= -f2)" git push origin main -# 4. Wait ~8 minutes for CI to build and publish +# 5. Wait ~8 minutes for CI to build and publish # Auto-tag creates GPG-signed tag → release.yml builds APK # Release notes are extracted from CHANGELOG.md entry -# 5. Verify +# 6. Verify gh release view v$(grep 'versionName' app/version.properties | cut -d= -f2 | tr -d ' ') - -# 6. Start next development cycle -./gradlew :app:bumpSnapshot -git add app/version.properties -git commit -m "chore: start next SNAPSHOT" -git push origin main ``` ## CHANGELOG.md format @@ -93,5 +91,4 @@ If no entry is found for the version, the release fails. └───────────────────┘ ``` -The version follows semver with `-SNAPSHOT` for development builds. -`clearPreRelease` removes the suffix; `bumpSnapshot` increments and re-adds it. +The version follows semver. `clearPreRelease` removes a pre-release suffix; `bumpMajor`, `bumpMinor`, and `bumpPatch` increment the version directly. diff --git a/build-logic/src/main/kotlin/app/passwordstore/gradle/versioning/VersioningPlugin.kt b/build-logic/src/main/kotlin/app/passwordstore/gradle/versioning/VersioningPlugin.kt index 0a1331818..2ee1395c4 100644 --- a/build-logic/src/main/kotlin/app/passwordstore/gradle/versioning/VersioningPlugin.kt +++ b/build-logic/src/main/kotlin/app/passwordstore/gradle/versioning/VersioningPlugin.kt @@ -79,8 +79,16 @@ class VersioningPlugin : Plugin { propertyFile.set(propFile) } tasks.register("bumpSnapshot") { - description = "Increment the minor version and add the `SNAPSHOT` suffix" - semverString.set(version.nextMinorVersion("SNAPSHOT").toString()) + val type = (project.findProperty("bumpType") as? String)?.lowercase() ?: "patch" + description = + "Increment the version and add the `SNAPSHOT` suffix. Use -PbumpType=major|minor|patch (default: patch)" + semverString.set( + when (type) { + "major" -> version.nextMajorVersion("SNAPSHOT").toString() + "minor" -> version.nextMinorVersion("SNAPSHOT").toString() + else -> version.nextPatchVersion("SNAPSHOT").toString() + } + ) propertyFile.set(propFile) } afterEvaluate {