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 @@

- Build + Build Release License Go 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