Skip to content

Commit 9f1879a

Browse files
committed
feat: initialize telegram-cli project
0 parents  commit 9f1879a

94 files changed

Lines changed: 27440 additions & 0 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
name: Setup Build Environment
2+
description: Install system dependencies for building
3+
runs:
4+
using: composite
5+
steps:
6+
- name: Install Linux dependencies
7+
if: runner.os == 'Linux'
8+
shell: bash
9+
run: |
10+
sudo apt-get update
11+
sudo apt-get install -y libsqlite3-dev
12+
13+
- name: Install macOS cross-build toolchains
14+
if: runner.os == 'macOS'
15+
shell: bash
16+
run: |
17+
set -euo pipefail
18+
19+
if ! command -v zig >/dev/null 2>&1; then
20+
brew install zig
21+
fi
22+
23+
if ! command -v cargo-zigbuild >/dev/null 2>&1; then
24+
cargo install cargo-zigbuild --locked
25+
fi
26+
27+
llvm_mingw_version="20260324"
28+
archive="llvm-mingw-${llvm_mingw_version}-ucrt-macos-universal.tar.xz"
29+
archive_path="$RUNNER_TEMP/$archive"
30+
tool_root="$RUNNER_TEMP/llvm-mingw-${llvm_mingw_version}-ucrt-macos-universal"
31+
32+
if [ ! -d "$tool_root" ]; then
33+
curl -L "https://github.com/mstorsjo/llvm-mingw/releases/download/${llvm_mingw_version}/${archive}" -o "$archive_path"
34+
tar -xf "$archive_path" -C "$RUNNER_TEMP"
35+
fi
36+
37+
echo "$tool_root/bin" >> "$GITHUB_PATH"
38+
{
39+
echo "CC_x86_64_pc_windows_gnullvm=$tool_root/bin/x86_64-w64-mingw32-clang"
40+
echo "CXX_x86_64_pc_windows_gnullvm=$tool_root/bin/x86_64-w64-mingw32-clang++"
41+
echo "CARGO_TARGET_X86_64_PC_WINDOWS_GNULLVM_LINKER=$tool_root/bin/x86_64-w64-mingw32-clang"
42+
echo "AR_x86_64_pc_windows_gnullvm=$tool_root/bin/llvm-ar"
43+
echo "RANLIB_x86_64_pc_windows_gnullvm=$tool_root/bin/llvm-ranlib"
44+
echo "CC_aarch64_pc_windows_gnullvm=$tool_root/bin/aarch64-w64-mingw32-clang"
45+
echo "CXX_aarch64_pc_windows_gnullvm=$tool_root/bin/aarch64-w64-mingw32-clang++"
46+
echo "CARGO_TARGET_AARCH64_PC_WINDOWS_GNULLVM_LINKER=$tool_root/bin/aarch64-w64-mingw32-clang"
47+
echo "AR_aarch64_pc_windows_gnullvm=$tool_root/bin/llvm-ar"
48+
echo "RANLIB_aarch64_pc_windows_gnullvm=$tool_root/bin/llvm-ranlib"
49+
} >> "$GITHUB_ENV"
50+
51+
- name: Install Windows gnullvm toolchain
52+
if: runner.os == 'Windows' && contains(env.TARGET, 'windows-gnullvm')
53+
shell: pwsh
54+
run: |
55+
$llvmMingwVersion = "20260324"
56+
$archive = switch ($env:TARGET) {
57+
"x86_64-pc-windows-gnullvm" { "llvm-mingw-$llvmMingwVersion-ucrt-x86_64.zip" }
58+
"aarch64-pc-windows-gnullvm" { "llvm-mingw-$llvmMingwVersion-ucrt-aarch64.zip" }
59+
default { throw "Unsupported Windows gnullvm target: $env:TARGET" }
60+
}
61+
$uri = "https://github.com/mstorsjo/llvm-mingw/releases/download/$llvmMingwVersion/$archive"
62+
$archivePath = Join-Path $env:RUNNER_TEMP $archive
63+
$installRoot = Join-Path $env:RUNNER_TEMP "llvm-mingw"
64+
Invoke-WebRequest -Uri $uri -OutFile $archivePath
65+
Expand-Archive -LiteralPath $archivePath -DestinationPath $installRoot -Force
66+
$toolRoot = Get-ChildItem -Path $installRoot -Directory | Select-Object -First 1
67+
"$($toolRoot.FullName)\bin" | Out-File -FilePath $env:GITHUB_PATH -Append -Encoding utf8
68+
69+
if ($env:TARGET -eq "x86_64-pc-windows-gnullvm") {
70+
"CC_x86_64_pc_windows_gnullvm=$($toolRoot.FullName)\bin\x86_64-w64-mingw32-clang.exe" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8
71+
"CXX_x86_64_pc_windows_gnullvm=$($toolRoot.FullName)\bin\x86_64-w64-mingw32-clang++.exe" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8
72+
"CARGO_TARGET_X86_64_PC_WINDOWS_GNULLVM_LINKER=$($toolRoot.FullName)\bin\x86_64-w64-mingw32-clang.exe" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8
73+
"AR_x86_64_pc_windows_gnullvm=$($toolRoot.FullName)\bin\llvm-ar.exe" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8
74+
"RANLIB_x86_64_pc_windows_gnullvm=$($toolRoot.FullName)\bin\llvm-ranlib.exe" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8
75+
} else {
76+
"CC_aarch64_pc_windows_gnullvm=$($toolRoot.FullName)\bin\aarch64-w64-mingw32-clang.exe" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8
77+
"CXX_aarch64_pc_windows_gnullvm=$($toolRoot.FullName)\bin\aarch64-w64-mingw32-clang++.exe" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8
78+
"CARGO_TARGET_AARCH64_PC_WINDOWS_GNULLVM_LINKER=$($toolRoot.FullName)\bin\aarch64-w64-mingw32-clang.exe" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8
79+
"AR_aarch64_pc_windows_gnullvm=$($toolRoot.FullName)\bin\llvm-ar.exe" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8
80+
"RANLIB_aarch64_pc_windows_gnullvm=$($toolRoot.FullName)\bin\llvm-ranlib.exe" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8
81+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
#!/usr/bin/env bun
2+
import { createHash } from "node:crypto";
3+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
4+
import { execFileSync } from "node:child_process";
5+
6+
const target = process.env.TARGET;
7+
const version = process.env.VERSION;
8+
9+
if (!target || !version) {
10+
console.error("Missing TARGET or VERSION environment variable");
11+
process.exit(1);
12+
}
13+
14+
const binaryName = "telegram-agent-cli";
15+
const artifactsRoot = ".work/artifacts";
16+
const binaryFileName = target.includes("windows")
17+
? `${binaryName}.exe`
18+
: binaryName;
19+
const archiveFormat = target.includes("windows") ? "zip" : "tar.gz";
20+
const archiveName = `${binaryName}-${version}-${target}.${archiveFormat}`;
21+
22+
mkdirSync(artifactsRoot, { recursive: true });
23+
24+
const builtBinary = `target/${target}/release/${binaryFileName}`;
25+
if (!existsSync(builtBinary)) {
26+
console.error(`Binary not found: ${builtBinary}`);
27+
process.exit(1);
28+
}
29+
30+
if (archiveFormat === "zip") {
31+
if (process.platform === "win32") {
32+
execFileSync("powershell", [
33+
"-NoProfile",
34+
"-Command",
35+
`Compress-Archive -Path '${builtBinary}' -DestinationPath '${process.cwd()}/${artifactsRoot}/${archiveName}' -Force`,
36+
]);
37+
} else {
38+
execFileSync("zip", ["-j", `${artifactsRoot}/${archiveName}`, builtBinary]);
39+
}
40+
} else {
41+
execFileSync("tar", [
42+
"-czf",
43+
`${artifactsRoot}/${archiveName}`,
44+
"-C",
45+
`target/${target}/release`,
46+
binaryFileName,
47+
]);
48+
}
49+
50+
const archivePath = `${artifactsRoot}/${archiveName}`;
51+
const sha256 = createHash("sha256")
52+
.update(readFileSync(archivePath))
53+
.digest("hex");
54+
writeFileSync(`${archivePath}.sha256`, `${sha256} ${archiveName}\n`);
55+
56+
console.log(`Built: ${archiveName}`);

.github/workflows/build.yml

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
name: Build Artifacts
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
version:
7+
description: Release version to stamp into the built artifacts
8+
required: true
9+
type: string
10+
11+
permissions:
12+
contents: read
13+
14+
env:
15+
CARGO_TERM_COLOR: always
16+
RUST_BACKTRACE: 1
17+
18+
jobs:
19+
build:
20+
runs-on: macos-14
21+
env:
22+
VERSION: ${{ inputs.version }}
23+
steps:
24+
- name: Checkout
25+
uses: actions/checkout@v6
26+
27+
- name: Setup Node.js
28+
uses: actions/setup-node@v6
29+
with:
30+
node-version: 22
31+
32+
- name: Setup Rust
33+
uses: dtolnay/rust-toolchain@stable
34+
with:
35+
targets: aarch64-apple-darwin,x86_64-apple-darwin,aarch64-unknown-linux-gnu,x86_64-unknown-linux-gnu,aarch64-pc-windows-gnullvm,x86_64-pc-windows-gnullvm
36+
37+
- uses: Swatinem/rust-cache@v2
38+
39+
- uses: ./.github/actions/setup-build-env
40+
41+
- name: Install dependencies
42+
run: npm ci --omit=optional
43+
44+
- name: Stamp release version
45+
run: node ./npm/prepare-release.cjs "$VERSION"
46+
47+
- name: Build release artifacts
48+
run: node ./scripts/release/build-release-artifacts.mjs --version "$VERSION"
49+
50+
- uses: actions/upload-artifact@v4
51+
with:
52+
name: telegram-agent-cli-dist-${{ inputs.version }}
53+
path: dist/*
54+
retention-days: 1

.github/workflows/release.yml

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
name: Release
2+
3+
on:
4+
push:
5+
branches: [main]
6+
7+
permissions:
8+
contents: write
9+
id-token: write
10+
issues: write
11+
pull-requests: write
12+
13+
concurrency:
14+
group: release-${{ github.ref }}
15+
cancel-in-progress: true
16+
17+
env:
18+
CARGO_TERM_COLOR: always
19+
RUST_BACKTRACE: 1
20+
21+
jobs:
22+
release:
23+
runs-on: macos-14
24+
steps:
25+
- name: Checkout
26+
uses: actions/checkout@v6
27+
with:
28+
fetch-depth: 0
29+
30+
- name: Setup Node.js
31+
uses: actions/setup-node@v6
32+
with:
33+
node-version: 22
34+
registry-url: https://registry.npmjs.org
35+
36+
- name: Setup Rust
37+
uses: dtolnay/rust-toolchain@stable
38+
with:
39+
targets: aarch64-apple-darwin,x86_64-apple-darwin,aarch64-unknown-linux-gnu,x86_64-unknown-linux-gnu,aarch64-pc-windows-gnullvm,x86_64-pc-windows-gnullvm
40+
41+
- uses: Swatinem/rust-cache@v2
42+
43+
- uses: ./.github/actions/setup-build-env
44+
45+
- name: Install dependencies
46+
run: npm ci --omit=optional
47+
48+
- name: Quality gates
49+
run: |
50+
cargo fmt --check --all
51+
cargo clippy -- -D warnings
52+
cargo test
53+
54+
- name: Release
55+
run: npm run release:ci
56+
env:
57+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
58+
GIT_AUTHOR_NAME: github-actions[bot]
59+
GIT_AUTHOR_EMAIL: github-actions[bot]@users.noreply.github.com
60+
GIT_COMMITTER_NAME: github-actions[bot]
61+
GIT_COMMITTER_EMAIL: github-actions[bot]@users.noreply.github.com

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
/target
2+
/.work
3+
/node_modules
4+
/dist

.releaserc.json

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
{
2+
"branches": ["main"],
3+
"tagFormat": "v${version}",
4+
"plugins": [
5+
[
6+
"@semantic-release/commit-analyzer",
7+
{
8+
"preset": "conventionalcommits",
9+
"releaseRules": [
10+
{ "type": "feat", "release": "minor" },
11+
{ "type": "fix", "release": "patch" },
12+
{ "type": "perf", "release": "patch" },
13+
{ "type": "refactor", "release": "patch" },
14+
{ "type": "docs", "release": "patch" },
15+
{ "type": "style", "release": "patch" },
16+
{ "type": "test", "release": "patch" },
17+
{ "type": "build", "release": "patch" },
18+
{ "type": "ci", "release": "patch" },
19+
{ "type": "revert", "release": "patch" },
20+
{ "type": "chore", "scope": "deps", "release": "patch" },
21+
{ "type": "chore", "scope": "release", "release": false },
22+
{ "breaking": true, "release": "major" }
23+
]
24+
}
25+
],
26+
[
27+
"@semantic-release/release-notes-generator",
28+
{
29+
"preset": "conventionalcommits"
30+
}
31+
],
32+
[
33+
"@semantic-release/changelog",
34+
{
35+
"changelogFile": "CHANGELOG.md"
36+
}
37+
],
38+
[
39+
"@semantic-release/exec",
40+
{
41+
"prepareCmd": "node ./npm/prepare-release.cjs ${nextRelease.version} && node ./scripts/release/build-release-artifacts.mjs --version ${nextRelease.version}"
42+
}
43+
],
44+
[
45+
"@semantic-release/git",
46+
{
47+
"assets": [
48+
"CHANGELOG.md",
49+
"package.json",
50+
"package-lock.json",
51+
"npm/packages/*/package.json",
52+
"Cargo.toml",
53+
"Cargo.lock"
54+
],
55+
"message": "chore(release): ${nextRelease.version}\n\n${nextRelease.notes}"
56+
}
57+
],
58+
[
59+
"@semantic-release/exec",
60+
{
61+
"publishCmd": "node ./scripts/release/write-release-evidence-from-dist.mjs --version ${nextRelease.version} --git-tag ${nextRelease.gitTag} --dist ./dist && node ./scripts/release/verify-npm-package-set.mjs --version ${nextRelease.version} --git-tag ${nextRelease.gitTag} --require-release-evidence --release-evidence ./.work/release/github-release/release-evidence.json --staged-dist ./dist/npm"
62+
}
63+
],
64+
[
65+
"@semantic-release/github",
66+
{
67+
"assets": [
68+
"dist/*.tar.gz",
69+
"dist/*.zip",
70+
"dist/*.sha256",
71+
".work/release/github-release/release-evidence.json",
72+
".release-manifest.json"
73+
]
74+
}
75+
],
76+
[
77+
"@semantic-release/exec",
78+
{
79+
"publishCmd": "node ./scripts/release/publish-npm-package-set.mjs --publish --version ${nextRelease.version} --git-tag ${nextRelease.gitTag} --release-evidence ./.work/release/github-release/release-evidence.json --staged-dist ./dist/npm"
80+
}
81+
]
82+
]
83+
}

0 commit comments

Comments
 (0)