From 5335f0d4099b1e0010d840e63b99d74ec62b7fac Mon Sep 17 00:00:00 2001 From: Compot Developer Date: Sat, 17 Oct 2026 19:22:47 +0000 Subject: [PATCH 1/2] ci: versions are MAJOR.MINOR.PATCH, a new one with every app change (#230) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit .github/check-version.sh, run by a new pull-request job: if android/ (except the unit tests in android/app/src/test) changed against the base branch, versionName must change too. A new version must be MAJOR.MINOR.PATCH without leading zeros, greater than the base one (sort -V), with a CHANGELOG.md section "## — YYYY-MM-DD" that the base branch does not have. The format is checked only when the version changes, so the current 2.17 stays valid until the next app change takes 2.17.1 or 2.18.0. The base branch reaches the script through the environment. docs/testing.md: the MAJOR.MINOR.PATCH rule replaces "2.xx, +0.01"; numbers are no longer reserved for open pull requests; basic 1.07.1 is 1.7.1. CHANGELOG.md: the header says where the scheme changes. Tested in compot/cross on a scratch clone (11 cases): no change, docs only and unit tests only pass; app code or gradle.properties without a bump fail; 2.18 (old style), a missing section, 2.16.9 and 2.017.0 fail; 2.17.1 and 2.18.0 with a section pass. shellcheck v0.10.0 clean. Refs #230 --- .github/check-version.sh | 64 +++++++++++++++++++++++++++++++++++++ .github/workflows/build.yml | 17 ++++++++++ CHANGELOG.md | 4 +++ docs/testing.md | 4 +-- 4 files changed, 87 insertions(+), 2 deletions(-) create mode 100755 .github/check-version.sh diff --git a/.github/check-version.sh b/.github/check-version.sh new file mode 100755 index 00000000..9cb8fca6 --- /dev/null +++ b/.github/check-version.sh @@ -0,0 +1,64 @@ +#!/bin/sh +# +# check-version.sh — fail a pull request that changes the app or its build +# but not versionName in android/app/build.gradle. A new version must be +# MAJOR.MINOR.PATCH without leading zeros, greater than the base one, and +# have its section in CHANGELOG.md ("## — YYYY-MM-DD") that the +# base branch does not have yet. android/ counts as app or build (its unit +# tests in android/app/src/test do not); docs, screenshots and the +# workflows in .github/ need no new version. The format is checked only +# when the version changes, so the 2.xx versions before MAJOR.MINOR.PATCH +# stay valid until the next app change. +# +# Usage: .github/check-version.sh [BASE] (default origin/v2) +# + +set -eu + +base=${1:-origin/v2} +gradle=android/app/build.gradle + +ver() { sed -n 's/.*versionName "\(.*\)".*/\1/p' | head -n 1; } + +new=$(ver < "$gradle") +old=$(git show "$base:$gradle" | ver) + +changed=$(git diff --name-only "$base"...HEAD -- android ':(exclude)android/app/src/test') + +if [ "$new" = "$old" ]; then + if [ -n "$changed" ]; then + echo "::error::the app or its build changed, versionName is still $old:" \ + "bump PATCH (fix) or MINOR (feature) and add its CHANGELOG.md section" + echo "$changed" + exit 1 + fi + echo "version $new unchanged, no app or build changes" + exit 0 +fi + +if ! echo "$new" | grep -Eq '^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)$'; then + echo "::error::versionName \"$new\" is not MAJOR.MINOR.PATCH" + exit 1 +fi + +top=$(printf '%s\n%s\n' "$old" "$new" | sort -V | tail -n 1) +if [ "$top" != "$new" ]; then + echo "::error::versionName $new is not greater than $old" + exit 1 +fi + +# $new is digits and dots only (checked above): escape the dots, require a date. +re=$(printf '%s' "$new" | sed 's/\./\\./g') +if ! grep -Eq "^## $re — [0-9]{4}-[0-9]{2}-[0-9]{2}\$" CHANGELOG.md; then + echo "::error::CHANGELOG.md has no section \"## $new — YYYY-MM-DD\"" + exit 1 +fi + +# The section must come with this pull request, not be one the base +# branch already has (a version taken from there brings no notes). +if git show "$base:CHANGELOG.md" 2>/dev/null | grep -Eq "^## $re — "; then + echo "::error::the section \"## $new\" is already on $base: take a new version" + exit 1 +fi + +echo "version $old -> $new, CHANGELOG.md section found" diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6d9369a4..7215a7ef 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -18,6 +18,23 @@ concurrency: cancel-in-progress: ${{ github.event_name != 'workflow_dispatch' }} jobs: + # Pull requests: a change to the app or its build comes with a new versionName + # (MAJOR.MINOR.PATCH) and its CHANGELOG.md section (.github/check-version.sh, #230) + version: + if: github.event_name == 'pull_request' + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: App changes come with a new version + env: + # through the environment, not pasted into the script + BASE: ${{ github.base_ref }} + run: .github/check-version.sh "origin/$BASE" + # Unit tests and lint; also runs for pull requests from forks (no secrets needed) test: runs-on: ubuntu-latest diff --git a/CHANGELOG.md b/CHANGELOG.md index 915e7dc3..157b8299 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ newest `v2` and `basic` builds, and in the OpenIPC Telegram channel; there are n per version (#194). This file is the change history: one section per `v2` version, newest first, then the legacy `basic` line. +Versions after 2.17 are `MAJOR.MINOR.PATCH` (2.17 is followed by 2.17.1 or 2.18.0; see +`docs/testing.md`, "Versions and releases"); the headings below keep the numbers as they +were released. + ## 2.17 — 2026-10-17 - Turn in the camera settings (Auto, 0°, 90°, 180°, 270°), stored per slot; H.264/H.265 are diff --git a/docs/testing.md b/docs/testing.md index d1561c82..0f575138 100644 --- a/docs/testing.md +++ b/docs/testing.md @@ -47,8 +47,8 @@ CI is the reference: the project does not depend on local builds. ## Versions and releases -- `v2` is **2.xx** (from 2.00). Every pull request that changes the app bumps `android/app/build.gradle` as its last commit before the merge: `versionName` +0.01, `versionCode` +1. Docs-only and CI-only pull requests do not. -- `basic` keeps its 1.07.x line. +- Versions are **`MAJOR.MINOR.PATCH`** (`versionName` in `android/app/build.gradle`): PATCH for fixes and small changes, MINOR for a new feature, MAJOR for an incompatible change or a large update, only when the maintainer decides. Every pull request that changes the app or its build (`android/`, except the unit tests) bumps the version as its last commit before the merge: `versionName` by that rule and `versionCode` +1. Docs-only, test-only and CI-only pull requests do not. Numbers are not reserved for open pull requests: each one takes the next number when it is merged. CI checks this on every pull request (`.github/check-version.sh`): a new number must be canonical (no leading zeros), greater than the base one, and come with its own `CHANGELOG.md` section. +- Until 2.17 `v2` counted **2.xx** (+0.01 per pull request); 2.17 is followed by 2.17.1 or 2.18.0. `basic` keeps its 1.7.x line (1.07.1 is 1.7.1). - **`CHANGELOG.md`** is the change history: the version bump commit of a pull request that changes the app adds the version's section (`## — `, newest first) in the same pull request. - Development is continuous, so there is **no release per version** (#194). The [`latest`](https://github.com/OpenIPC/decoder/releases/tag/latest) release always holds the newest `v2` and `basic` builds. Every `v2` and `basic` build is also posted to the OpenIPC Telegram channel with its version and commit, and that is where their older builds can be found. Builds of other branches are only workflow artifacts of their runs (90 days). - **Test pre-releases**: to let a reporter test a branch, a pre-release named after the issue is made by hand from the branch's CI artifact, e.g. [`toys-187-test2`](https://github.com/OpenIPC/decoder/releases/tag/toys-187-test2) for #187. It is deleted when the test is over, or replaced by the next one. From b26d7bfd36c281dd827463e9ffe3bf0051a0d0d2 Mon Sep 17 00:00:00 2001 From: Compot Developer Date: Sat, 17 Oct 2026 19:26:56 +0000 Subject: [PATCH 2/2] ci: check-version.sh reads the one versionName assignment, 2.17.0 is 2.17, base from the merge commit Qodo on #232: - only an actual versionName assignment counts, and there must be one: a comment with a version before it or a second assignment fail; - a 2.xx version from before MAJOR.MINOR.PATCH compares as X.Y.0, so 2.17.0 is the same version as 2.17 and fails; - CI passes HEAD^1, the base side of the pull request's merge commit, so the old version and the changed files come from the same base even if v2 moves meanwhile; - the job runs for pull requests to v2 only (basic has its own workflow and app/build.gradle). CHANGELOG.md: the basic heading is 1.7.1 (released as 1.07.1). Tested: the 11 earlier cases, plus 2.17.0, a version-like comment, two assignments (all fail) and a merge commit checked with HEAD^1 (pass). shellcheck clean. Refs #230 --- .github/check-version.sh | 27 +++++++++++++++++++++------ .github/workflows/build.yml | 10 +++++----- CHANGELOG.md | 6 +++--- 3 files changed, 29 insertions(+), 14 deletions(-) diff --git a/.github/check-version.sh b/.github/check-version.sh index 9cb8fca6..cd6d8131 100755 --- a/.github/check-version.sh +++ b/.github/check-version.sh @@ -10,7 +10,8 @@ # when the version changes, so the 2.xx versions before MAJOR.MINOR.PATCH # stay valid until the next app change. # -# Usage: .github/check-version.sh [BASE] (default origin/v2) +# Usage: .github/check-version.sh [BASE] (default origin/v2; CI passes +# HEAD^1, the base side of the pull request's merge commit) # set -eu @@ -18,10 +19,19 @@ set -eu base=${1:-origin/v2} gradle=android/app/build.gradle -ver() { sed -n 's/.*versionName "\(.*\)".*/\1/p' | head -n 1; } +# The one versionName assignment (comments and other text do not count). +ver() { + v=$(sed -n 's/^[[:space:]]*versionName[[:space:]]*"\([^"]*\)"[[:space:]]*$/\1/p') + if [ "$(printf '%s\n' "$v" | grep -c .)" -ne 1 ]; then + echo "::error::$1:$gradle: expected one versionName assignment," \ + "found: $(printf '%s' "$v" | tr '\n' ' ')" >&2 + exit 1 + fi + printf '%s\n' "$v" +} -new=$(ver < "$gradle") -old=$(git show "$base:$gradle" | ver) +new=$(ver HEAD < "$gradle") +old=$(git show "$base:$gradle" | ver "$base") changed=$(git diff --name-only "$base"...HEAD -- android ':(exclude)android/app/src/test') @@ -41,8 +51,13 @@ if ! echo "$new" | grep -Eq '^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)$ exit 1 fi -top=$(printf '%s\n%s\n' "$old" "$new" | sort -V | tail -n 1) -if [ "$top" != "$new" ]; then +# A 2.xx version from before MAJOR.MINOR.PATCH is X.Y.0: 2.17.0 is 2.17. +case $old in +*.*.*) oldn=$old ;; +*) oldn=$old.0 ;; +esac +top=$(printf '%s\n%s\n' "$oldn" "$new" | sort -V | tail -n 1) +if [ "$new" = "$oldn" ] || [ "$top" != "$new" ]; then echo "::error::versionName $new is not greater than $old" exit 1 fi diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7215a7ef..42004ca3 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -21,7 +21,8 @@ jobs: # Pull requests: a change to the app or its build comes with a new versionName # (MAJOR.MINOR.PATCH) and its CHANGELOG.md section (.github/check-version.sh, #230) version: - if: github.event_name == 'pull_request' + # basic keeps its own workflow and version file (app/build.gradle) + if: github.event_name == 'pull_request' && github.base_ref == 'v2' runs-on: ubuntu-latest steps: - name: Checkout @@ -29,11 +30,10 @@ jobs: with: fetch-depth: 0 + # The checkout is the pull request's merge commit: its first parent is the + # base it was made from, so both versions come from the same base. - name: App changes come with a new version - env: - # through the environment, not pasted into the script - BASE: ${{ github.base_ref }} - run: .github/check-version.sh "origin/$BASE" + run: .github/check-version.sh HEAD^1 # Unit tests and lint; also runs for pull requests from forks (no secrets needed) test: diff --git a/CHANGELOG.md b/CHANGELOG.md index 157b8299..46a0f397 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -112,10 +112,10 @@ Versions 1.x of the `v2` line, up to 1.28 (2026-05-04) and the work merged until `basic` is the original app, `decoder.apk` in the `latest` release; it gets fixes only. -### 1.07.1 — 2026-10-12 +### 1.7.1 — 2026-10-12 -- Robust RTSP handshake, end-of-stream handling, thread lifecycle and SDP parsing (PR #41, - #36–#40). +- Released as 1.07.1 (written 1.7.1 since #230). Robust RTSP handshake, end-of-stream + handling, thread lifecycle and SDP parsing (PR #41, #36–#40). ### 1.07 — 2025-11-11