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, or arm64
  • 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:

  1. Creating a shared TBuild folder and symlinking it into the workspace
  2. Detecting the Windows SDK version from docs/building-win.md
  3. Installing MSVC command-prompt tools via ilammy/msvc-dev-cmd
  4. 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:

  1. Installs Poetry to generate the Dockerfile dynamically
  2. Caches Docker build layers using .buildx-cache
  3. Builds the image via docker/build-push-action
  4. 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_env to 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.py ensures 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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →