diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4e350d3d..8cc7d9da 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -119,14 +119,74 @@ jobs: tag_name: latest files: ${{ steps.vars.outputs.name }}.apk + # v2: every version gets a release of its own (#157), at the commit that was built, with + # the APK and the merged PRs since the previous v2.* release. A push without a version + # bump (docs, CI) only updates "latest" above. Not marked Latest: the README links + # releases/tag/latest + - name: Versioned release + if: github.ref_name == 'v2' + env: + GH_TOKEN: ${{ github.token }} + run: | + VER=$(sed -n 's/.*versionName "\(.*\)".*/\1/p' android/app/build.gradle) + TAG="v${VER}" + if [ -z "$VER" ]; then echo "No versionName found"; exit 1; fi + APK="decoder-v2-${VER}.apk" + cp decoder-v2.apk "$APK" + # An existing release is complete only with its APK (Qodo on #158) + has_apk() { + gh release view "$TAG" --json assets -q '.assets[].name' 2>/dev/null | grep -qx "$APK" + } + # Only the build of the tagged commit may add the missing APK (Qodo on #158) + repair_apk() { + TAGGED=$(gh api "repos/${{ github.repository }}/commits/$TAG" -q .sha) + if [ "$TAGGED" = "$(git rev-parse HEAD)" ]; then + gh release upload "$TAG" "$APK" --clobber + else + echo "::warning::$TAG has no $APK and points to ${TAGGED:0:7}, not this build" + fi + } + if gh release view "$TAG" >/dev/null 2>&1; then + if has_apk; then + echo "Release $TAG exists: only latest was updated" + else + repair_apk + fi + exit 0 + fi + # The previous version by number, not by date: a manual build of an older commit may + # publish after a newer one (Qodo on #158) + # A failed lookup fails the step rather than publishing first-release notes + TAGS=$(gh api --paginate "repos/${{ github.repository }}/releases?per_page=100" \ + -q '.[].tag_name') + PREV=$(printf '%s\n' "$TAGS" | grep '^v2\.' | sed 's/^v//' | { cat; echo "$VER"; } \ + | sort -V -u | grep -B1 -x "$VER" | grep -v -x "$VER" || true) + if [ -n "$PREV" ]; then + NOTES=(--generate-notes --notes-start-tag "v$PREV") + else + NOTES=(--notes "First release of the 2.xx line (v2 branch). Earlier changes: https://github.com/${{ github.repository }}/commits/v2") + fi + if ! gh release create "$TAG" "$APK" --target "$(git rev-parse HEAD)" \ + --title "OpenIPC Decoder ${VER}" --latest=false "${NOTES[@]}"; then + # Another build of the same version created it meanwhile, or the upload failed: + # the release must exist and carry the APK, else the step fails + gh release view "$TAG" >/dev/null + has_apk || repair_apk + fi + - name: Telegram if: github.ref_name == 'basic' || github.ref_name == 'v2' run: | + # basic keeps its Gradle files at the top level; read only the one that exists + # (a missing file would fail the step under pipefail, Qodo on #158) + GRADLE=android/app/build.gradle + [ -f "$GRADLE" ] || GRADLE=app/build.gradle + VER=$(sed -n 's/.*versionName "\(.*\)".*/\1/p' "$GRADLE" | head -1) GIT_HASH=$(git rev-parse --short HEAD) GIT_BRANCH="${{ github.ref_name }}" TAG_NAME="${{ github.ref_type == 'tag' && github.ref_name || '' }}" TIME=$(date -u '+%Y-%m-%d %H:%M:%S UTC') - TG_MSG="Commit: ${GIT_HASH}\nBranch: ${GIT_BRANCH}\nTag: ${TAG_NAME}\nTime: ${TIME}\n\n" + TG_MSG="Version: ${VER}\nCommit: ${GIT_HASH}\nBranch: ${GIT_BRANCH}\nTag: ${TAG_NAME}\nTime: ${TIME}\n\n" TG_ICON="\xE2\x9C\x85 GitHub Actions" TG_HEADER=$(echo -e ${TG_MSG}${TG_ICON}) TG_TOKEN=${{secrets.TELEGRAM_TOKEN_BOT_OPENIPC}} diff --git a/LABORATORY.md b/LABORATORY.md index 60ddd2e0..041633bd 100644 --- a/LABORATORY.md +++ b/LABORATORY.md @@ -205,6 +205,7 @@ $ADB shell getprop ro.product.model # AG-216 ### Builds - `v2` / `basic`: `gh release download latest -R OpenIPC/decoder -p decoder-v2.apk -p decoder.apk` +- A given 2.xx version: `gh release download v2.01 -R OpenIPC/decoder` (`decoder-v2-2.01.apk`). CI creates the release `v` on the first v2 build of each version (#157). - Branches: `build.yml` builds signed APKs only on **push** runs (not `pull_request`); artifact name is `decoder-`: ```sh B=feat/rtsp-multicast diff --git a/README.md b/README.md index 4700ac87..21cf5b8f 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,8 @@ Ready-to-install builds are in the [**latest** release](https://github.com/OpenI | `decoder-v2.apk` | **Current version**, recommended | | `decoder.apk` | Legacy version from the `basic` branch | +Each 2.xx version also has a release of its own — [`v2.01`](https://github.com/OpenIPC/decoder/releases/tag/v2.01) and later, on the [releases page](https://github.com/OpenIPC/decoder/releases) — with that version's APK and the changes since the previous one. + A beta channel is available on [Google Play](https://play.google.com/apps/internaltest/4701231141824898735). To join it, send your e-mail through the [OpenIPC Telegram channels](https://openipc.org/our-channels). ## Features diff --git a/README.ru.md b/README.ru.md index 6921d4f6..9b52f265 100644 --- a/README.ru.md +++ b/README.ru.md @@ -24,6 +24,8 @@ | `decoder-v2.apk` | **Текущая версия**, рекомендуется | | `decoder.apk` | Старая версия из ветки `basic` | +У каждой версии 2.xx есть и свой релиз — [`v2.01`](https://github.com/OpenIPC/decoder/releases/tag/v2.01) и далее, на [странице релизов](https://github.com/OpenIPC/decoder/releases) — с APK этой версии и списком изменений после предыдущей. + Есть бета-канал в [Google Play](https://play.google.com/apps/internaltest/4701231141824898735). Чтобы попасть в него, пришлите свой e-mail через [Telegram-каналы OpenIPC](https://openipc.org/our-channels). ## Возможности diff --git a/README.zh-CN.md b/README.zh-CN.md index 63903723..fe88c83a 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -24,6 +24,8 @@ | `decoder-v2.apk` | **当前版本**,推荐使用 | | `decoder.apk` | `basic` 分支的旧版本 | +每个 2.xx 版本另有独立的发布 — [`v2.01`](https://github.com/OpenIPC/decoder/releases/tag/v2.01) 及之后的版本,见[发布页面](https://github.com/OpenIPC/decoder/releases) — 包含该版本的 APK 以及相对上一版本的更改。 + [Google Play](https://play.google.com/apps/internaltest/4701231141824898735) 上提供测试渠道。如需加入,请通过 [OpenIPC Telegram 频道](https://openipc.org/our-channels)发送您的电子邮箱。 ## 功能