From d9f20f8abf4ee2a7418fd32afbac792df65075e2 Mon Sep 17 00:00:00 2001
From: fdciabdul
Date: Mon, 3 Aug 2026 22:54:11 +0700
Subject: [PATCH 1/3] CI: split into ci.yml (test+build) and release.yml
(cross-platform auto release)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- ci.yml: vet/gofmt/test plus build matrix for linux, darwin, windows
(amd64/arm64) and android/arm64 — all cross-compiled, CGO_ENABLED=0
- release.yml: on v* tags, build all three binaries (tele-tui,
telegram-mcp, telegram-api) per platform, package tar.gz/zip with
README+LICENSE, sha256 checksums, publish via softprops/action-gh-release
- Removes old build.yml (per-OS runners, tele-tui only)
- README: prebuilt binaries section
---
.github/workflows/build.yml | 59 -----------------------
.github/workflows/ci.yml | 67 ++++++++++++++++++++++++++
.github/workflows/release.yml | 90 +++++++++++++++++++++++++++++++++++
README.md | 6 +++
4 files changed, 163 insertions(+), 59 deletions(-)
delete mode 100644 .github/workflows/build.yml
create mode 100644 .github/workflows/ci.yml
create mode 100644 .github/workflows/release.yml
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
deleted file mode 100644
index 97b603e..0000000
--- a/.github/workflows/build.yml
+++ /dev/null
@@ -1,59 +0,0 @@
-name: Build
-
-on:
- push:
- branches: [main]
- tags: ['v*']
- pull_request:
- branches: [main]
-
-jobs:
- build:
- name: ${{ matrix.os }}
- runs-on: ${{ matrix.os }}
- strategy:
- fail-fast: false
- matrix:
- os: [ubuntu-latest, windows-latest, macos-latest]
-
- steps:
- - uses: actions/checkout@v4
- - uses: actions/setup-go@v5
- with:
- go-version: '1.25'
-
- - name: Build
- run: go build -trimpath -ldflags="-s -w" -o ${{ matrix.os == 'windows-latest' && 'bin/tele-tui.exe' || 'bin/tele-tui' }} ./cmd/teletui
- env:
- CGO_ENABLED: 0
-
- - uses: actions/upload-artifact@v4
- with:
- name: tele-tui-${{ matrix.os == 'ubuntu-latest' && 'linux' || matrix.os == 'windows-latest' && 'windows' || 'macos' }}-amd64
- path: bin/
-
- release:
- name: Release
- needs: [build]
- if: startsWith(github.ref, 'refs/tags/v')
- runs-on: ubuntu-latest
- permissions:
- contents: write
-
- steps:
- - uses: actions/download-artifact@v4
- with:
- path: artifacts
-
- - name: Package
- run: |
- mkdir release
- cp artifacts/tele-tui-linux-amd64/tele-tui release/tele-tui-linux-amd64
- cp artifacts/tele-tui-macos-amd64/tele-tui release/tele-tui-macos-amd64
- chmod +x release/tele-tui-linux-amd64 release/tele-tui-macos-amd64
- cp artifacts/tele-tui-windows-amd64/tele-tui.exe release/tele-tui-windows-amd64.exe
-
- - uses: softprops/action-gh-release@v2
- with:
- files: release/*
- generate_release_notes: true
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 0000000..46d23be
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,67 @@
+name: CI
+
+on:
+ push:
+ branches: [main, dev]
+ pull_request:
+ branches: [main, dev]
+
+jobs:
+ test:
+ name: Test & Lint
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - uses: actions/setup-go@v5
+ with:
+ go-version: '1.25'
+ cache: true
+
+ - name: Vet
+ run: go vet ./...
+
+ - name: Format check
+ run: test -z "$(gofmt -l .)"
+
+ - name: Test
+ run: go test ./...
+
+ build:
+ name: Build ${{ matrix.target.goos }}/${{ matrix.target.goarch }}
+ runs-on: ubuntu-latest
+ strategy:
+ fail-fast: false
+ matrix:
+ target:
+ - { goos: linux, goarch: amd64 }
+ - { goos: linux, goarch: arm64 }
+ - { goos: darwin, goarch: amd64 }
+ - { goos: darwin, goarch: arm64 }
+ - { goos: windows, goarch: amd64 }
+ - { goos: android, goarch: arm64 }
+
+ steps:
+ - uses: actions/checkout@v4
+ - uses: actions/setup-go@v5
+ with:
+ go-version: '1.25'
+ cache: true
+
+ - name: Build all binaries
+ env:
+ GOOS: ${{ matrix.target.goos }}
+ GOARCH: ${{ matrix.target.goarch }}
+ CGO_ENABLED: 0
+ run: |
+ set -e
+ EXT=""; [ "$GOOS" = "windows" ] && EXT=".exe"
+ mkdir -p dist
+ go build -trimpath -ldflags="-s -w" -o "dist/tele-tui${EXT}" ./cmd/teletui
+ go build -trimpath -ldflags="-s -w" -o "dist/telegram-mcp${EXT}" ./cmd/telegram-mcp
+ go build -trimpath -ldflags="-s -w" -o "dist/telegram-api${EXT}" ./cmd/telegram-api
+
+ - uses: actions/upload-artifact@v4
+ with:
+ name: telegram-cli-${{ matrix.target.goos }}-${{ matrix.target.goarch }}
+ path: dist/
+ retention-days: 7
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
new file mode 100644
index 0000000..6a03917
--- /dev/null
+++ b/.github/workflows/release.yml
@@ -0,0 +1,90 @@
+name: Release
+
+on:
+ push:
+ tags: ['v*']
+ workflow_dispatch:
+
+permissions:
+ contents: write
+
+jobs:
+ build:
+ name: Build ${{ matrix.target.goos }}/${{ matrix.target.goarch }}
+ runs-on: ubuntu-latest
+ strategy:
+ fail-fast: false
+ matrix:
+ target:
+ - { goos: linux, goarch: amd64 }
+ - { goos: linux, goarch: arm64 }
+ - { goos: darwin, goarch: amd64 }
+ - { goos: darwin, goarch: arm64 }
+ - { goos: windows, goarch: amd64 }
+ - { goos: android, goarch: arm64 }
+
+ steps:
+ - uses: actions/checkout@v4
+ - uses: actions/setup-go@v5
+ with:
+ go-version: '1.25'
+ cache: true
+
+ - name: Build all binaries
+ env:
+ GOOS: ${{ matrix.target.goos }}
+ GOARCH: ${{ matrix.target.goarch }}
+ CGO_ENABLED: 0
+ run: |
+ set -e
+ EXT=""; [ "$GOOS" = "windows" ] && EXT=".exe"
+ mkdir -p dist
+ go build -trimpath -ldflags="-s -w" -o "dist/tele-tui${EXT}" ./cmd/teletui
+ go build -trimpath -ldflags="-s -w" -o "dist/telegram-mcp${EXT}" ./cmd/telegram-mcp
+ go build -trimpath -ldflags="-s -w" -o "dist/telegram-api${EXT}" ./cmd/telegram-api
+
+ - name: Package
+ env:
+ GOOS: ${{ matrix.target.goos }}
+ GOARCH: ${{ matrix.target.goarch }}
+ run: |
+ set -e
+ PKG="telegram-cli_${GITHUB_REF_NAME}_${GOOS}_${GOARCH}"
+ mkdir -p "stage/${PKG}"
+ cp dist/* "stage/${PKG}/"
+ cp README.md LICENSE "stage/${PKG}/"
+ mkdir -p release
+ cd stage
+ if [ "$GOOS" = "windows" ]; then
+ zip -r "../release/${PKG}.zip" "${PKG}"
+ else
+ tar -czf "../release/${PKG}.tar.gz" "${PKG}"
+ fi
+
+ - uses: actions/upload-artifact@v4
+ with:
+ name: package-${{ matrix.target.goos }}-${{ matrix.target.goarch }}
+ path: release/
+ retention-days: 7
+
+ publish:
+ name: Publish GitHub release
+ needs: [build]
+ if: startsWith(github.ref, 'refs/tags/v')
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/download-artifact@v4
+ with:
+ pattern: package-*
+ path: packages
+ merge-multiple: true
+
+ - name: Generate checksums
+ run: |
+ cd packages
+ sha256sum *.tar.gz *.zip > checksums.txt
+
+ - uses: softprops/action-gh-release@v2
+ with:
+ files: packages/*
+ generate_release_notes: true
diff --git a/README.md b/README.md
index fb4d9bc..ac6b8c3 100644
--- a/README.md
+++ b/README.md
@@ -60,6 +60,12 @@
## Quick Start
+### Prebuilt binaries
+
+Download the latest release for your platform from [Releases](https://github.com/imtaqin/telegram-cli/releases) — Linux, macOS, Windows, and Android/Termux (arm64). Each archive contains all three binaries: `tele-tui`, `telegram-mcp`, `telegram-api`. Releases are built automatically from tags (`v*`).
+
+### Build from source
+
```bash
# Clone
git clone https://github.com/imtaqin/telegram-cli.git
From 34923420a55132c62e424cf02f4bed14381943c9 Mon Sep 17 00:00:00 2001
From: fdciabdul
Date: Mon, 3 Aug 2026 22:54:46 +0700
Subject: [PATCH 2/3] README: point build badge at ci.yml
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index ac6b8c3..368f908 100644
--- a/README.md
+++ b/README.md
@@ -9,7 +9,7 @@
-
+
From c0ea67b997e1df503c405c3e152db4f4f1a8990c Mon Sep 17 00:00:00 2001
From: fdciabdul
Date: Mon, 3 Aug 2026 22:59:16 +0700
Subject: [PATCH 3/3] release.yml: fully automatic tagging + release on every
push to main
- version job computes the next tag (patch bump by default, #minor /
#major in the commit message to override; manual v* tag pushes still
supported) with collision guard
- softprops/action-gh-release creates the tag on release, so no manual
tagging or PAT is needed
- serialized via concurrency group
---
.github/workflows/release.yml | 58 +++++++++++++++++++++++++++++++++--
README.md | 2 +-
2 files changed, 56 insertions(+), 4 deletions(-)
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 6a03917..ac20270 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -1,16 +1,63 @@
name: Release
+# Fully automatic: every push to main bumps the patch version, creates a
+# tag, builds all platforms, and publishes a GitHub release.
+# Put "#minor" or "#major" in the commit message to bump those instead.
+# Pushing a v* tag manually also works (uses that tag as-is).
on:
push:
+ branches: [main]
tags: ['v*']
workflow_dispatch:
permissions:
contents: write
+concurrency:
+ group: release
+ cancel-in-progress: false
+
jobs:
+ version:
+ name: Determine version
+ runs-on: ubuntu-latest
+ outputs:
+ tag: ${{ steps.ver.outputs.tag }}
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+
+ - id: ver
+ env:
+ COMMIT_MSG: ${{ github.event.head_commit.message }}
+ run: |
+ set -e
+ if [[ "$GITHUB_REF" == refs/tags/v* ]]; then
+ TAG="$GITHUB_REF_NAME"
+ else
+ LATEST=$(git tag -l 'v*' --sort=-v:refname | head -n1)
+ LATEST=${LATEST:-v0.0.0}
+ IFS=. read -r MAJOR MINOR PATCH <<< "${LATEST#v}"
+ if grep -qi '#major' <<< "$COMMIT_MSG"; then
+ MAJOR=$((MAJOR+1)); MINOR=0; PATCH=0
+ elif grep -qi '#minor' <<< "$COMMIT_MSG"; then
+ MINOR=$((MINOR+1)); PATCH=0
+ else
+ PATCH=$((PATCH+1))
+ fi
+ TAG="v${MAJOR}.${MINOR}.${PATCH}"
+ if git rev-parse -q --verify "refs/tags/${TAG}" >/dev/null; then
+ PATCH=$((PATCH+1))
+ TAG="v${MAJOR}.${MINOR}.${PATCH}"
+ fi
+ fi
+ echo "tag=${TAG}" >> "$GITHUB_OUTPUT"
+ echo "Releasing ${TAG}"
+
build:
name: Build ${{ matrix.target.goos }}/${{ matrix.target.goarch }}
+ needs: [version]
runs-on: ubuntu-latest
strategy:
fail-fast: false
@@ -47,9 +94,10 @@ jobs:
env:
GOOS: ${{ matrix.target.goos }}
GOARCH: ${{ matrix.target.goarch }}
+ VERSION: ${{ needs.version.outputs.tag }}
run: |
set -e
- PKG="telegram-cli_${GITHUB_REF_NAME}_${GOOS}_${GOARCH}"
+ PKG="telegram-cli_${VERSION}_${GOOS}_${GOARCH}"
mkdir -p "stage/${PKG}"
cp dist/* "stage/${PKG}/"
cp README.md LICENSE "stage/${PKG}/"
@@ -69,8 +117,7 @@ jobs:
publish:
name: Publish GitHub release
- needs: [build]
- if: startsWith(github.ref, 'refs/tags/v')
+ needs: [version, build]
runs-on: ubuntu-latest
steps:
- uses: actions/download-artifact@v4
@@ -84,7 +131,12 @@ jobs:
cd packages
sha256sum *.tar.gz *.zip > checksums.txt
+ # softprops/action-gh-release creates the tag (pointing at this
+ # commit) when it does not exist yet — this is what makes the
+ # whole flow tagless on the pusher's side.
- uses: softprops/action-gh-release@v2
with:
+ tag_name: ${{ needs.version.outputs.tag }}
+ name: ${{ needs.version.outputs.tag }}
files: packages/*
generate_release_notes: true
diff --git a/README.md b/README.md
index 368f908..41beada 100644
--- a/README.md
+++ b/README.md
@@ -62,7 +62,7 @@
### Prebuilt binaries
-Download the latest release for your platform from [Releases](https://github.com/imtaqin/telegram-cli/releases) — Linux, macOS, Windows, and Android/Termux (arm64). Each archive contains all three binaries: `tele-tui`, `telegram-mcp`, `telegram-api`. Releases are built automatically from tags (`v*`).
+Download the latest release for your platform from [Releases](https://github.com/imtaqin/telegram-cli/releases) — Linux, macOS, Windows, and Android/Termux (arm64). Each archive contains all three binaries: `tele-tui`, `telegram-mcp`, `telegram-api`. Releases are fully automatic: every push to `main` bumps the patch version, tags, builds, and publishes (use `#minor` / `#major` in a commit message to bump those instead).
### Build from source