How Telegram Desktop Configures Automated Builds in Its CI/CD Pipeline: A Complete Guide to GitHub Actions
Telegram Desktop uses GitHub Actions with platform-specific workflow files (win.yml, linux.yml, mac.yml) to automate builds for Windows, Linux, and macOS, leveraging matrix strategies, aggressive caching of third-party dependencies, and artifact upload steps for every push and pull request.
The telegramdesktop/tdesktop repository maintains a sophisticated continuous integration system that produces debug builds across all major desktop platforms automatically. Understanding how these automated builds are configured in the CI/CD pipeline reveals a pattern of matrix-driven workflows, path-optimized triggers, and reusable caching layers that minimize build times while ensuring code quality.
Windows CI/CD Pipeline Configuration
The Windows automation is defined in .github/workflows/win.yml and represents the most complex build matrix in the system.
Build Matrix and Triggers
The workflow triggers on every push and pull_request event, deliberately ignoring documentation, Markdown files, and legal text to prevent unnecessary builds. The matrix strategy varies three critical dimensions:
- Architecture:
x64_x86,x64, orarm64 - Qt Version: Empty string (default) or
qt6 - CMake Generator: Default or
"Ninja Multi-Config"
Optional compile-time defines allow testing of conditional compilation flags without modifying source code.
Environment Setup and Caching
The workflow executes on windows-latest or windows-11-arm runners with Visual Studio 2022. Key preparation steps include:
- Creating a shared
TBuildfolder and symlinking it into the workspace - Detecting the Windows SDK version from
docs/building-win.md - Installing MSVC command-prompt tools via ilammy/msvc-dev-cmd
- Restoring cached ThirdParty, Libraries, and Qt directories using
actions/cache
The cache key incorporates a SHA256 hash of prepare.py combined with the OS and architecture, ensuring that dependency script changes invalidate the cache appropriately.
Build Execution and Artifact Generation
The actual compilation follows a strict sequence:
# Excerpt from win.yml logic
- name: Prepare dependencies
run: Telegram\build\prepare\win.bat skip-release silent ${{ matrix.qt }}
- name: Configure CMake
run: configure.bat ${{ matrix.generator }} ${{ matrix.arch }} ${{ matrix.qt }} ...
- name: Build
run: cmake --build ..\out --config Debug --parallel
After cmake completes, the workflow collects Telegram.exe and Updater.exe, placing them in an artifact/ directory for upload via actions/upload-artifact.
Linux Automated Build Configuration
Linux builds use .github/workflows/linux.yml with a containerized approach to ensure reproducible Rocky Linux 8 environments.
Docker-Based Build Environment
Unlike Windows, the Linux pipeline builds and runs a custom Docker image defined in Telegram/build/docker/centos_env. The workflow:
- Installs Poetry to generate the Dockerfile dynamically
- Caches Docker build layers using
.buildx-cache - Builds the image via
docker/build-push-action - Mounts the repository into the container with
CONFIG=Debug
Inside the container, the entrypoint script Telegram/build/docker/centos_env/build.sh executes the compilation with debug-oriented flags.
CMake Configuration and Compilation
The Linux build script passes explicit CMake configuration flags optimized for CI debugging:
cmake -D CMAKE_CONFIGURATION_TYPES=Debug \
-D CMAKE_C_FLAGS_DEBUG="-O0 -fuse-ld=lld" \
-D DESKTOP_APP_DISABLE_X11_INTEGRATION=${{ matrix.defines }} \
...
After verifying the binary at out/Debug/Telegram, the workflow packages both Telegram and Updater into the artifact/ folder for upload.
macOS CI Pipeline Setup
The macOS configuration in .github/workflows/mac.yml targets macos-latest runners with a simpler matrix (currently only varying empty defines).
The preparation phase installs toolchain dependencies via Homebrew:
- name: Install dependencies
run: brew install automake meson nasm ninja pkg-config
After disabling Spotlight to prevent indexing overhead, the workflow caches the Libraries and ThirdParty directories before running Telegram/build/prepare/mac.sh skip-release silent. The build then executes through ./configure.sh with debug-specific flags like -D CMAKE_COMPILE_WARNING_AS_ERROR=ON, followed by cmake --build ../out --config Debug --parallel.
The resulting Telegram.app bundle and Updater binary are moved to artifact/ and uploaded.
Common CI/CD Architecture Patterns
Across all three platforms, the Telegram Desktop automated builds share architectural principles that optimize for speed and reliability.
Path-Based Trigger Optimization
All workflows implement identical path-ignore rules that skip builds when only documentation, Markdown, or workflow files themselves change. This prevents wasting runner minutes on non-code modifications.
Matrix-Driven Variations
The Windows pipeline exploits the most complex matrix to test multiple architectures and Qt versions simultaneously. Linux uses the matrix primarily for compile-time feature flags like DESKTOP_APP_DISABLE_X11_INTEGRATION. macOS maintains an extensible single-configuration setup ready for future expansion.
Preparation Script Abstraction
Each platform invokes a thin wrapper—win.bat, mac.sh, or the Docker build.sh—that delegates to the central Telegram/build/prepare/prepare.py script. This abstraction allows the CI to handle platform-specific path conventions while maintaining a single source of truth for dependency resolution.
Artifact Publication Strategy
Every workflow concludes by uploading debug binaries via actions/upload-artifact, making them instantly accessible from the GitHub Actions run page without requiring repository write permissions.
Accessing and Using Build Artifacts
Developers can interact with the CI system programmatically for testing or release preparation.
Triggering Manual Builds
To initiate a build from a feature branch without pushing code, use the workflow_dispatch event or repository dispatch:
name: Manual Build Trigger
on:
workflow_dispatch:
inputs:
platform:
description: 'Target platform'
required: true
default: 'windows'
type: choice
options:
- windows
- linux
- macos
Since the existing workflows react to push events, triggering a dummy commit or using peter-evans/repository-dispatch@v2 routes the request to the appropriate platform workflow.
Downloading Artifacts via CLI
Retrieve the latest Windows build artifacts using the GitHub CLI:
# List recent runs and extract the database ID
RUN_ID=$(gh run list --workflow win.yml -L 1 --json databaseId -q '.[0].databaseId')
# Download the Qt6 build artifact
gh run download $RUN_ID --name "Telegram x64 qt6"
Inspecting Cache Keys
To debug cache hits or misses, reference the CACHE_KEY environment variable generated early in each workflow:
- name: Display cache key
run: echo "Current cache key: ${{ env.CACHE_KEY }}"
This key combines the sha256sum of prepare.py with platform identifiers, ensuring that dependency updates automatically invalidate stale caches.
Summary
- Telegram Desktop automates builds across Windows, Linux, and macOS using dedicated workflow files in
.github/workflows/(win.yml, linux.yml, mac.yml). - The Windows pipeline employs a complex build matrix testing x64, x86, ARM64, and multiple Qt versions using Visual Studio 2022.
- Linux builds run inside a Docker container built from
Telegram/build/docker/centos_envto ensure Rocky Linux 8 compatibility. - macOS builds rely on Homebrew toolchains and Xcode-free compilation with aggressive caching of third-party libraries.
- All platforms use path-based triggers to skip builds on documentation changes, matrix strategies for multi-configuration testing, and actions/upload-artifact to publish debug binaries.
- Centralized preparation logic in
Telegram/build/prepare/prepare.pyensures consistent dependency management across different operating systems.
Frequently Asked Questions
How does Telegram Desktop prevent unnecessary CI builds on documentation changes?
The workflow files in .github/workflows/win.yml, linux.yml, and mac.yml all specify paths-ignore filters that exclude Markdown files, documentation directories, license text, and the workflow files themselves from the push and pull_request triggers. This ensures that editing README files or legal notices does not consume runner resources.
What caching strategy does the Windows CI use to speed up builds?
The Windows workflow caches the ThirdParty, Libraries, and Qt directories using actions/cache. The cache key incorporates a SHA256 hash of Telegram/build/prepare/prepare.py combined with the OS type and architecture. If the preparation script changes—indicating new dependencies—the cache automatically invalidates and rebuilds.
How can I download the debug binaries produced by the automated builds?
Each workflow uploads artifacts via actions/upload-artifact at the end of the build process. You can download these directly from the GitHub Actions run page in the browser, or use the GitHub CLI with commands like gh run download <run-id> --name "Telegram x64 qt6" to fetch specific matrix variants programmatically.
Why does the Linux pipeline use Docker while Windows and macOS use native runners?
The Linux workflow targets a specific Rocky Linux 8 environment to maintain binary compatibility with older glibc versions, ensuring the resulting executables run on a wide range of Linux distributions. The Docker image defined in Telegram/build/docker/centos_env provides this controlled environment, whereas Windows and macOS builds target specific OS versions natively available through GitHub-hosted runners.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →