Skip to content

ci: versions are MAJOR.MINOR.PATCH, a new one with every app change (#230) - #232

Merged
compot-dev merged 2 commits into
v2from
ci/version-check
Oct 17, 2026
Merged

compot-dev merged 2 commits into
v2from
ci/version-check

Conversation

@compot-dev

Copy link
Copy Markdown
Collaborator

Part of #230 (the v2 side; basic 1.07.1 → 1.7.1 comes in a PR to basic).

What changes

  • .github/check-version.sh, run by a new version job on pull requests (checkout with fetch-depth: 0, base through env):
    • if android/ changed (except the unit tests in android/app/src/test), versionName must change too;
    • a new version must be MAJOR.MINOR.PATCH without leading zeros, greater than the base one (sort -V), and have a ## <version> — YYYY-MM-DD section in CHANGELOG.md that the base branch does not have yet;
    • the format is checked only when the version changes, so today's 2.17 stays valid until the next app change, which takes 2.17.1 (fix) or 2.18.0 (feature).
  • docs/testing.md, "Versions and releases": the MAJOR.MINOR.PATCH rule (PATCH, MINOR; MAJOR only when the maintainer decides) replaces "2.xx, +0.01"; numbers are no longer reserved for open pull requests, each takes the next one when it is merged; basic 1.07.1 is 1.7.1.
  • CHANGELOG.md: the header says where the scheme changes; old headings stay as released.

Note for #220: it was to take 2.18; with this rule it takes the next number when it is merged (a fix → 2.17.1, or the next free one), with its CHANGELOG.md section.

Tests

compot/cross on a scratch clone, 11 cases:

Case Expected Result
no change / docs only / unit tests only pass pass
app code or gradle.properties changed, no bump fail fail
2.17 → 2.18 (old style) fail fail
2.17 → 2.17.1 or 2.18.0 with a section pass pass
2.17.1 without a section / 2.16.9 / 2.017.0 fail fail

shellcheck v0.10.0 -S style: clean. This PR changes only .github/, docs and CHANGELOG.md, so its own version job passes without a bump.

…230)

.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 "## <version> — 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
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

PR Summary by Qodo

Enforce version bumps and changelog entries for Android PRs

⚙️ Configuration changes ✨ Enhancement 📝 Documentation 🕐 10-20 Minutes

Grey Divider

AI Description

• Add a pull-request CI check requiring app changes to include a new version and changelog entry.
• Adopt MAJOR.MINOR.PATCH for new versions while preserving previously released version numbers.
• Document version selection at merge time, without reserving numbers for open pull requests.
Diagram

graph TD
  A["PR checkout"] --> B["Compare base and PR"] --> C{"Version changed?"} -->|No| D{"Android changed?"} -->|No| G["Pass check"]
  C -->|Yes| E["Validate version"] --> H["Check changelog"] -->|Valid| G
  D -->|Yes| F["Fail check"]
  E -->|Invalid| F
  H -->|Invalid| F
Loading
High-Level Assessment

The focused PR check fits the repository’s existing manual version and changelog process. Automated release tooling would add complexity without addressing a need for per-version releases; retaining historical version numbers avoids rewriting release history.

Files changed (4) +87 / -2

Enhancement (1) +64 / -0
check-version.shAdd pull-request version and changelog validation +64/-0

Add pull-request version and changelog validation

• Compares the PR with its base branch and requires a version bump for Android changes other than unit tests. New versions must use canonical MAJOR.MINOR.PATCH, exceed the base version, and have a dated changelog section not already on the base branch. Existing 2.xx versions remain valid until changed.

.github/check-version.sh

Documentation (2) +6 / -2
CHANGELOG.mdExplain the version-scheme transition +4/-0

Explain the version-scheme transition

• Notes that versions after 2.17 use MAJOR.MINOR.PATCH and points readers to the release guidance. Previously released headings are unchanged.

CHANGELOG.md

testing.mdDocument version selection and merge-time numbering +2/-2

Document version selection and merge-time numbering

• Replaces the 2.xx increment rule with PATCH, MINOR, and maintainer-decided MAJOR guidance. Clarifies which PRs require a bump, that numbers are assigned at merge rather than reserved, and how the v2 and basic histories transition.

docs/testing.md

Other (1) +17 / -0
build.ymlRun the version check on pull requests +17/-0

Run the version check on pull requests

• Adds a pull-request-only version job with full Git history and passes the target branch to the checker. Existing test and build jobs remain separate.

.github/workflows/build.yml

@qodo-free-for-open-source-projects

qodo-free-for-open-source-projects Bot commented Oct 17, 2026 •

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (1) 📘 Rule violations (0) 📎 Requirement gaps (1) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)

Grey Divider


Action required

1. Historical release notes rename 1.07.1 📎 Requirement gap ⚙ Maintainability
Description
CHANGELOG.md replaces the historical 1.07.1 heading with 1.7.1 while rewriting its entry text.
Readers scanning headings see a number other than the published version, even though the
introduction says headings retain released numbers and the entry text identifies the release as
1.07.1.
Code

CHANGELOG.md[R115-118]

+### 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).
Evidence
The diff replaces ### 1.07.1 — 2026-10-12 with ### 1.7.1 — 2026-10-12. The new introduction says
headings retain their released numbers, and the entry itself says the build was released as
1.07.1, confirming that the changed heading no longer shows the published number.

Canonical MAJOR.MINOR.PATCH app versions
CHANGELOG.md[115-118]
CHANGELOG.md[10-12]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The historical `1.07.1` changelog heading was changed to its canonical `1.7.1` spelling, contradicting the introduction's statement that headings retain released numbers.
## Fix Focus Areas
- CHANGELOG.md[10-12]
- CHANGELOG.md[115-118]
## Recommended Fix
Restore the heading to `### 1.07.1 — 2026-10-12`. Keep the explanation of the canonical `1.7.1` spelling in the entry text or changelog introduction without renaming the released heading.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Retargeted pull requests skip version checks 🐞 Bug ≡ Correctness
Description
The new version job is conditional on github.base_ref == 'v2', but the workflow uses the default
pull-request activity types, which do not include edited. If an existing pull request is
retargeted from another branch to v2, the base-branch edit does not run the job, so its current
app changes remain unchecked until another qualifying event occurs.
Code

.github/workflows/build.yml[25]

+    if: github.event_name == 'pull_request' && github.base_ref == 'v2'
Evidence
The workflow declares pull_request without activity types, while the added job runs only when the
event's base branch is v2. A base-branch edit is an edited activity, which is not among the
default pull-request triggers.

.github/workflows/build.yml[1-5]
.github/workflows/build.yml[23-36]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Retargeting a pull request to v2 does not trigger the version check because the workflow does not subscribe to pull-request edits.
## Fix Focus Areas
- .github/workflows/build.yml[1-5]
- .github/workflows/build.yml[23-36]
## Recommended Fix
Specify pull_request activity types that include edited alongside opened, synchronize, and reopened, so retargeting reruns the base-dependent version job.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Basic changes can skip version checks ✓ Resolved
Description
The version job runs for every pull request, but check-version.sh always reads
android/app/build.gradle and only detects changes under android/. On the basic branch, the
version file is app/build.gradle, so the job either fails before checking or misses app/ changes
and accepts an unchanged version.
Code

.github/check-version.sh[R18-19]

+base=${1:-origin/v2}
+gradle=android/app/build.gradle
Evidence
The workflow runs the new version check for every pull request, while the script hard-codes the v2
Gradle path and android/ diff scope. Repository documentation identifies app/build.gradle as the
basic version source, so basic code or build changes cannot be enforced by this implementation.

Enforce version changes in pull-request CI on v2 and basic
.github/check-version.sh[18-27]
.github/workflows/build.yml[23-36]
docs/testing.md[50-51]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The pull-request version job is unconditional, but the script hard-codes the v2 Gradle path and Android change scope, so `basic` pull requests are not checked against `app/build.gradle` and `app/` changes.
## Fix Focus Areas
- .github/check-version.sh[18-27]
- .github/workflows/build.yml[23-36]
## Recommended Fix
Select the Gradle version file and changed-path scope from the base branch, or provide separate branch-aware checks, so v2 compares `android/app/build.gradle` and `android/` while basic compares `app/build.gradle` and `app/`. Ensure each check uses the respective base branch and retains the unit-test exclusion where applicable.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View action required (2)
4. An unchanged release version can pass ✓ Resolved
Description
sort -V treats 2.17.0 as greater than the current 2.17, so the greater-than check accepts it
as a new version. An app-change PR can therefore use 2.17.0 with a matching changelog heading even
though the documented successors to 2.17 are 2.17.1 and 2.18.0.
Code

.github/check-version.sh[R44-46]

+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"
Evidence
The current Gradle version is 2.17; the new-version pattern permits 2.17.0, and the check uses
version-sort ordering rather than the documented successor rule. A matching new changelog heading
satisfies the remaining check.

android/app/build.gradle[20-27]
.github/check-version.sh[39-55]
CHANGELOG.md[10-14]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The comparison accepts `2.17.0` after the existing `2.17`, although the first valid successors are `2.17.1` and `2.18.0`.
## Fix Focus Areas
- .github/check-version.sh[39-48]
## Recommended Fix
Normalize the legacy two-component base version to a patch-zero version for comparison, then compare numeric components strictly so a new patch-zero version does not count as an increase.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


5. A comment can hide an unchanged app version ✓ Resolved
Description
ver() takes the first line containing versionName "...", including a Gradle comment, instead of
reading the effective assignment. If a PR adds a preceding comment such as `// Next: versionName
"2.18.0" but leaves the assignment at 2.17`, a matching changelog heading lets the version job
pass despite the unchanged app version.
Code

.github/check-version.sh[21]

+ver() { sed -n 's/.*versionName "\(.*\)".*/\1/p' | head -n 1; }
Evidence
The extractor scans matching text and takes its first line; all later comparisons and changelog
checks use that extracted value. The current effective assignment is lower in the Gradle file, so a
preceding comment can supply the value checked by CI without changing the value assigned to the app.

.github/check-version.sh[21-24]
.github/check-version.sh[28-64]
android/app/build.gradle[20-27]
.github/workflows/build.yml[27-36]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The version extractor accepts a comment before the real Gradle assignment as the app version, allowing an unchanged or invalid effective version to pass.
## Fix Focus Areas
- .github/check-version.sh[21-24]
## Recommended Fix
Extract an actual `versionName` assignment rather than arbitrary matching text, and reject ambiguous or missing assignments. Add a case with a version-like comment preceding the assignment.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

6. Base updates can block docs-only PRs ✓ Resolved
Description
old is read from the fetched base ref while new is read from the checked-out pull-request merge
commit, so they can represent different base revisions if the base moves between merge-ref creation
and checkout. If that update bumps the base version, a docs-only PR with no Android changes enters
the version-change path and fails the greater-than check instead of taking the unchanged-version
exit.
Code

.github/check-version.sh[R23-26]

+new=$(ver < "$gradle")
+old=$(git show "$base:$gradle" | ver)
+
+changed=$(git diff --name-only "$base"...HEAD -- android ':(exclude)android/app/src/test')
Evidence
The workflow checks out the PR revision and passes a separately fetched origin/$BASE to the
script. The script compares versions before considering whether the changed-path list is empty
whenever those versions differ.

.github/workflows/build.yml[27-36]
.github/check-version.sh[23-46]
docs/testing.md[48-52]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The fetched base ref can advance beyond the base incorporated into the checked-out PR merge commit, causing a docs-only PR to fail version comparison.
## Fix Focus Areas
- .github/check-version.sh[23-28]
- .github/workflows/build.yml[27-36]
## Recommended Fix
Use the same base revision for the checkout's version comparison and changed-file calculation, rather than reading the independently moving remote-tracking ref.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Tip of the day
💡 Did you know, you can see how risky a PR is at a glance with blast radius labels

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread .github/check-version.sh
Comment thread .github/check-version.sh Outdated
Comment thread .github/check-version.sh Outdated
Comment thread .github/check-version.sh Outdated
…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
@compot-dev

Copy link
Copy Markdown
Collaborator Author

Qodo findings, all four addressed in b26d7bf:

  1. Basic changes can skip version checks: the version job now runs only for pull requests to v2 (github.base_ref == 'v2'). basic keeps its own workflow (push only, no pull-request trigger) and its version in app/build.gradle; its canonical number is chore(basic): versionName 1.07.1 is written 1.7.1 (#230) #233.
  2. An unchanged release version can pass: fixed. A 2.xx base version compares as X.Y.0, so 2.17 → 2.17.0 fails as "not greater"; 2.17.1 and 2.18.0 pass.
  3. A comment can hide an unchanged app version: fixed. Only a line that is a versionName "…" assignment counts, and there must be exactly one; a version-like comment before it no longer supplies the value (the unchanged real version then fails the check), two assignments fail.
  4. Base updates can block docs-only PRs: fixed. CI passes HEAD^1, the base side of the checked-out merge commit, so the old version and the changed files come from the same base.

Tested in compot/cross on a scratch clone: the 11 earlier cases plus 2.17.0, a version-like comment, two assignments (fail) and a merge commit checked with HEAD^1 (pass); 15/15. shellcheck clean. Also: the basic heading in CHANGELOG.md is now 1.7.1 (released as 1.07.1).

@compot-dev

Copy link
Copy Markdown
Collaborator Author

/review

@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Qodo findings, all four addressed in b26d7bf:

  1. Basic changes can skip version checks: the version job now runs only for pull requests to v2 (github.base_ref == 'v2'). basic keeps its own workflow (push only, no pull-request trigger) and its version in app/build.gradle; its canonical number is chore(basic): versionName 1.07.1 is written 1.7.1 (#230) #233.
  2. An unchanged release version can pass: fixed. A 2.xx base version compares as X.Y.0, so 2.17 → 2.17.0 fails as "not greater"; 2.17.1 and 2.18.0 pass.
  3. A comment can hide an unchanged app version: fixed. Only a line that is a versionName "…" assignment counts, and there must be exactly one; a version-like comment before it no longer supplies the value (the unchanged real version then fails the check), two assignments fail.
  4. Base updates can block docs-only PRs: fixed. CI passes HEAD^1, the base side of the checked-out merge commit, so the old version and the changed files come from the same base.

Tested in compot/cross on a scratch clone: the 11 earlier cases plus 2.17.0, a version-like comment, two assignments (fail) and a merge commit checked with HEAD^1 (pass); 15/15. shellcheck clean. Also: the basic heading in CHANGELOG.md is now 1.7.1 (released as 1.07.1).

Thanks for the detailed resolution. Based on the supplied changes, commit b26d7bf addresses all four findings:

  • finding 1: limits the check to v2, while basic retains its separate workflow and versioning.
  • finding 2: normalizes legacy 2.xx versions to patch-zero before comparison.
  • finding 3: extracts exactly one real versionName assignment and ignores comments.
  • finding 4: compares against HEAD^1, keeping the base version and diff scope consistent.

The reported 15/15 validation results and clean ShellCheck run provide good coverage. I can’t independently verify the commit or close findings from this acknowledgement alone.

Comment thread CHANGELOG.md
Comment on lines +115 to +118
### 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).

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. Historical release notes rename 1.07.1 📎 Requirement gap ⚙ Maintainability

CHANGELOG.md replaces the historical 1.07.1 heading with 1.7.1 while rewriting its entry text.
Readers scanning headings see a number other than the published version, even though the
introduction says headings retain released numbers and the entry text identifies the release as
1.07.1.
Agent Prompt
## Issue description
The historical `1.07.1` changelog heading was changed to its canonical `1.7.1` spelling, contradicting the introduction's statement that headings retain released numbers.

## Fix Focus Areas
- CHANGELOG.md[10-12]
- CHANGELOG.md[115-118]

## Recommended Fix
Restore the heading to `### 1.07.1 — 2026-10-12`. Keep the explanation of the canonical `1.7.1` spelling in the entry text or changelog introduction without renaming the released heading.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

# (MAJOR.MINOR.PATCH) and its CHANGELOG.md section (.github/check-version.sh, #230)
version:
# basic keeps its own workflow and version file (app/build.gradle)
if: github.event_name == 'pull_request' && github.base_ref == 'v2'

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

2. Retargeted pull requests skip version checks 🐞 Bug ≡ Correctness

The new version job is conditional on github.base_ref == 'v2', but the workflow uses the default
pull-request activity types, which do not include edited. If an existing pull request is
retargeted from another branch to v2, the base-branch edit does not run the job, so its current
app changes remain unchecked until another qualifying event occurs.
Agent Prompt
## Issue description
Retargeting a pull request to v2 does not trigger the version check because the workflow does not subscribe to pull-request edits.

## Fix Focus Areas
- .github/workflows/build.yml[1-5]
- .github/workflows/build.yml[23-36]

## Recommended Fix
Specify pull_request activity types that include edited alongside opened, synchronize, and reopened, so retargeting reruns the base-dependent version job.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit b26d7bf

@compot-dev
compot-dev merged commit 0f0c2a9 into v2 Oct 17, 2026
6 checks passed
@compot-dev
compot-dev deleted the ci/version-check branch October 17, 2026 19:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant