mirror of
https://hubproxy.babadafafafafa.cn/https://github.com/telegramdesktop/tdesktop
synced 2026-09-20 08:03:45 +08:00
956 lines
39 KiB
YAML
956 lines
39 KiB
YAML
# Canary channel: single Release+LTO build per platform (Windows x64,
|
|
# universal macOS, Linux x64 through docker), signed, packed as v2
|
|
# updates and published via a local Bot API server.
|
|
#
|
|
# Each repository builds exactly ONE lane. The lane follows repository
|
|
# visibility (public repo -> canary-public, private repo ->
|
|
# canary-private) and can be overridden with the repository variable
|
|
# CANARY_CHANNEL ("public" or "private"); the private lane refuses to
|
|
# run from a public repository no matter what. A repository holds only
|
|
# its own lane's secrets.
|
|
#
|
|
# Infrastructure this workflow needs before its first real run, all under
|
|
# the 'canary' environment unless noted. Placeholders, do not invent values:
|
|
#
|
|
# Both repositories:
|
|
# vars.CANARY_CHANNEL
|
|
# Optional lane override, see above. Normally left unset.
|
|
# secrets.CANARY_API_ID / secrets.CANARY_API_HASH
|
|
# Production Telegram API credentials for the canary app builds.
|
|
# secrets.CANARY_BOT_TOKEN
|
|
# Bot admin in this lane's channel (posts files, edits metadata).
|
|
# secrets.AZURE_CLIENT_ID / secrets.AZURE_TENANT_ID
|
|
# This lane's Entra federated credential for OIDC az login
|
|
# (id-token: write).
|
|
# secrets.AZURE_KEYVAULT_NAME
|
|
# Key Vault holding this lane's canary ES256 key.
|
|
# secrets.SM_API_KEY / secrets.SM_CLIENT_CERT_FILE_B64 /
|
|
# secrets.SM_CLIENT_CERT_PASSWORD / secrets.SM_HOST /
|
|
# secrets.SM_KEYPAIR_ALIAS
|
|
# DigiCert KeyLocker (smctl) for Windows Authenticode.
|
|
# secrets.MACOS_CERTIFICATE_P12_B64 / secrets.MACOS_CERTIFICATE_PASSWORD /
|
|
# secrets.MACOS_KEYCHAIN_PASSWORD / secrets.MACOS_SIGN_IDENTITY
|
|
# Developer ID Application certificate for codesign.
|
|
# secrets.NOTARY_APPLE_ID / secrets.NOTARY_TEAM_ID / secrets.NOTARY_PASSWORD
|
|
# notarytool credentials.
|
|
# secrets.R2_ACCOUNT_ID / secrets.R2_ACCESS_KEY_ID /
|
|
# secrets.R2_SECRET_ACCESS_KEY / vars.R2_SYMBOLS_BUCKET
|
|
# Cloudflare R2 bucket for breakpad symbols (upload placeholder).
|
|
# vars.CANARY_BOT_API_IMAGE
|
|
# Digest-pinned Bot API server image built from a pinned
|
|
# tdlib/telegram-bot-api ref by canary-bot-api.yml, e.g.
|
|
# ghcr.io/<org>/telegram-bot-api@sha256:<digest>. Never point this
|
|
# at a third-party image: the container handles the bot token and
|
|
# every published update file.
|
|
#
|
|
# Public repository only:
|
|
# secrets.CANARY_PUBLIC_CHANNEL_ID
|
|
# Numeric -100... public channel id for the Bot API calls.
|
|
# vars.CANARY_PUBLIC_CHANNEL_USERNAME
|
|
# Public channel username compiled into canary-public builds.
|
|
# vars.CANARY_METADATA_MSG_ID
|
|
# Fixed id of the pinned metadata message in the public channel.
|
|
# vars.CANARY_SIGNING_KEY_ID
|
|
# Key Vault key name, must match the manifest id ("cp-2026a").
|
|
#
|
|
# Private repository only:
|
|
# secrets.CANARY_PRIVATE_CHANNEL_ID
|
|
# Bare numeric id of the private channel (no -100 prefix), also
|
|
# compiled into canary-private builds for discovery.
|
|
# vars.CANARY_PRIVATE_METADATA_MSG_ID
|
|
# Fixed id of the pinned metadata message in the private channel.
|
|
# vars.CANARY_PRIVATE_SIGNING_KEY_ID
|
|
# Key Vault key name, must match the manifest id ("cx-2026a").
|
|
#
|
|
# Publishing no-ops cleanly while CANARY_BOT_TOKEN is absent, so the
|
|
# workflow can run before the bots/channels/KeyLocker exist.
|
|
|
|
name: Canary.
|
|
|
|
on:
|
|
push:
|
|
branches:
|
|
- canary
|
|
|
|
concurrency:
|
|
group: canary-publish
|
|
cancel-in-progress: false
|
|
|
|
permissions:
|
|
id-token: write
|
|
contents: read
|
|
|
|
jobs:
|
|
|
|
version:
|
|
name: Version
|
|
runs-on: ubuntu-latest
|
|
environment: canary
|
|
|
|
outputs:
|
|
channel: ${{ steps.compute.outputs.channel }}
|
|
base: ${{ steps.compute.outputs.base }}
|
|
commit: ${{ steps.compute.outputs.commit }}
|
|
counter: ${{ steps.compute.outputs.counter }}
|
|
previous: ${{ steps.compute.outputs.previous }}
|
|
publish: ${{ steps.compute.outputs.publish }}
|
|
|
|
steps:
|
|
- name: Clone.
|
|
uses: actions/checkout@v7
|
|
with:
|
|
# Full history: the changelog walks commits and the pipeline
|
|
# must survive force-pushes and rebases of the canary branch.
|
|
fetch-depth: 0
|
|
|
|
- name: Compute canary version.
|
|
id: compute
|
|
env:
|
|
BOT_TOKEN: ${{ secrets.CANARY_BOT_TOKEN }}
|
|
PUBLIC_CHANNEL: ${{ secrets.CANARY_PUBLIC_CHANNEL_ID }}
|
|
PRIVATE_CHANNEL: ${{ secrets.CANARY_PRIVATE_CHANNEL_ID }}
|
|
CHANNEL_OVERRIDE: ${{ vars.CANARY_CHANNEL }}
|
|
REPO_IS_PRIVATE: ${{ github.event.repository.private }}
|
|
run: |
|
|
CHANNEL="$CHANNEL_OVERRIDE"
|
|
if [ -z "$CHANNEL" ]; then
|
|
if [ "$REPO_IS_PRIVATE" = "true" ]; then
|
|
CHANNEL=private
|
|
else
|
|
CHANNEL=public
|
|
fi
|
|
fi
|
|
case "$CHANNEL" in
|
|
public|private) ;;
|
|
*)
|
|
echo "::error::Bad CANARY_CHANNEL value '$CHANNEL'."
|
|
exit 1
|
|
;;
|
|
esac
|
|
if [ "$CHANNEL" = "private" ] && [ "$REPO_IS_PRIVATE" != "true" ]; then
|
|
echo "::error::The private canary lane only builds from the private repository."
|
|
exit 1
|
|
fi
|
|
echo "channel=$CHANNEL" >> $GITHUB_OUTPUT
|
|
if [ "$CHANNEL" = "public" ]; then
|
|
CHAT_ID="$PUBLIC_CHANNEL"
|
|
else
|
|
CHAT_ID="-100$PRIVATE_CHANNEL"
|
|
fi
|
|
|
|
while IFS=' ' read -r name value; do
|
|
[ "$name" = "AppVersion" ] && BASE="$value"
|
|
done < Telegram/build/version
|
|
echo "base=$BASE" >> $GITHUB_OUTPUT
|
|
echo "commit=${GITHUB_SHA::7}" >> $GITHUB_OUTPUT
|
|
|
|
PUBLISH=false
|
|
if [ -n "$BOT_TOKEN" ]; then
|
|
PUBLISH=true
|
|
fi
|
|
echo "publish=$PUBLISH" >> $GITHUB_OUTPUT
|
|
|
|
COUNTER=1
|
|
PREVIOUS=""
|
|
if [ "$PUBLISH" = "true" ] && [ -n "$CHAT_ID" ] && [ "$CHAT_ID" != "-100" ]; then
|
|
PINNED=$(curl -sf "https://api.telegram.org/bot$BOT_TOKEN/getChat?chat_id=$CHAT_ID" \
|
|
| jq -r '.result.pinned_message.text // empty')
|
|
if [ -n "$PINNED" ]; then
|
|
OLD_BASE=$(echo "$PINNED" | jq -r ".channels.\"canary-$CHANNEL\".base // 0")
|
|
OLD_COUNTER=$(echo "$PINNED" | jq -r ".channels.\"canary-$CHANNEL\".counter // 0")
|
|
PREVIOUS=$(echo "$PINNED" | jq -r ".channels.\"canary-$CHANNEL\".commit // empty")
|
|
if [ "$OLD_BASE" = "$BASE" ]; then
|
|
COUNTER=$((OLD_COUNTER + 1))
|
|
fi
|
|
fi
|
|
fi
|
|
echo "counter=$COUNTER" >> $GITHUB_OUTPUT
|
|
echo "previous=$PREVIOUS" >> $GITHUB_OUTPUT
|
|
echo "Canary lane: canary-$CHANNEL, version $BASE #$COUNTER (publish: $PUBLISH)"
|
|
|
|
windows:
|
|
name: Windows x64 (${{ needs.version.outputs.channel }})
|
|
runs-on: depot-windows-latest-16
|
|
needs: version
|
|
environment: canary
|
|
|
|
# win-arm64 is phase 2: add an arch matrix here together with the
|
|
# windows-11-arm runner and the VS ARM64 build tools steps from
|
|
# win.yml when the canary channels grow an arm feed.
|
|
|
|
env:
|
|
PREPARE_PATH: "Telegram/build/prepare/prepare.py"
|
|
|
|
defaults:
|
|
run:
|
|
shell: cmd
|
|
|
|
steps:
|
|
- name: Prepare directories.
|
|
run: |
|
|
mkdir %userprofile%\TBuild\Libraries
|
|
mklink /d %GITHUB_WORKSPACE%\TBuild %userprofile%\TBuild
|
|
echo TBUILD=%GITHUB_WORKSPACE%\TBuild>>%GITHUB_ENV%
|
|
echo LibrariesPath=%GITHUB_WORKSPACE%\TBuild\Libraries\win64>>%GITHUB_ENV%
|
|
|
|
- name: Get repository name.
|
|
shell: bash
|
|
run: echo "REPO_NAME=${GITHUB_REPOSITORY##*/}" >> $GITHUB_ENV
|
|
|
|
- name: Clone.
|
|
uses: actions/checkout@v7
|
|
with:
|
|
submodules: recursive
|
|
path: ${{ env.TBUILD }}\${{ env.REPO_NAME }}
|
|
|
|
- name: Read canary configuration.
|
|
shell: bash
|
|
run: |
|
|
echo "CANARY_COUNTER=${{ needs.version.outputs.counter }}" >> $GITHUB_ENV
|
|
if [ "${{ needs.version.outputs.channel }}" = "public" ]; then
|
|
echo "CANARY_TAG=canarypub" >> $GITHUB_ENV
|
|
echo "CANARY_KEY_ID=${{ vars.CANARY_SIGNING_KEY_ID }}" >> $GITHUB_ENV
|
|
echo "CANARY_DEFINES=-D TDESKTOP_UPDATE_CHANNEL=canary-public -D TDESKTOP_CANARY_PUBLIC_CHANNEL=${{ vars.CANARY_PUBLIC_CHANNEL_USERNAME }} -D TDESKTOP_CANARY_METADATA_MSG_ID=${{ vars.CANARY_METADATA_MSG_ID }}" >> $GITHUB_ENV
|
|
else
|
|
echo "CANARY_TAG=canarypriv" >> $GITHUB_ENV
|
|
echo "CANARY_KEY_ID=${{ vars.CANARY_PRIVATE_SIGNING_KEY_ID }}" >> $GITHUB_ENV
|
|
echo "CANARY_DEFINES=-D TDESKTOP_UPDATE_CHANNEL=canary-private -D TDESKTOP_CANARY_PRIVATE_CHANNEL_ID=${{ secrets.CANARY_PRIVATE_CHANNEL_ID }} -D TDESKTOP_CANARY_METADATA_MSG_ID=${{ vars.CANARY_PRIVATE_METADATA_MSG_ID }}" >> $GITHUB_ENV
|
|
fi
|
|
|
|
- name: First set up.
|
|
shell: bash
|
|
run: |
|
|
DOCPATH=$TBUILD/$REPO_NAME/docs/building-win.md
|
|
SDK="$(grep "SDK version" $DOCPATH | sed -r 's/.*\*\*(.*)\*\* SDK version.*/\1/')"
|
|
echo "SDK=$SDK" >> $GITHUB_ENV
|
|
|
|
sed -i '/CMAKE_${lang}_FLAGS_DEBUG_INIT/s/${_Zi}//' "$PROGRAMFILES"/CMake/share/cmake*/Modules/Platform/Windows-MSVC.cmake
|
|
|
|
echo "$(sha256sum $TBUILD/$REPO_NAME/$PREPARE_PATH | awk '{ print $1 }')" >> CACHE_KEY.txt
|
|
echo "$SDK" >> CACHE_KEY.txt
|
|
echo "CACHE_KEY=$(sha256sum CACHE_KEY.txt | awk '{ print $1 }')" >> $GITHUB_ENV
|
|
|
|
echo "Configurate git for cherry-picks."
|
|
git config --global user.email "you@example.com"
|
|
git config --global user.name "Sample"
|
|
|
|
- uses: Eden-CI/msvc-dev-cmd@master
|
|
name: Native Tools Command Prompt.
|
|
with:
|
|
arch: x64
|
|
sdk: ${{ env.SDK }}
|
|
toolset: '14.44'
|
|
|
|
- name: NuGet sources.
|
|
run: |
|
|
nuget sources Disable -Name "Microsoft Visual Studio Offline Packages"
|
|
nuget sources Add -Source https://api.nuget.org/v3/index.json & exit 0
|
|
|
|
- name: ThirdParty cache.
|
|
uses: actions/cache@v6
|
|
with:
|
|
path: ${{ env.TBUILD }}\ThirdParty
|
|
key: ${{ runner.OS }}-${{ runner.arch }}-third-party-${{ env.CACHE_KEY }}
|
|
restore-keys: ${{ runner.OS }}-${{ runner.arch }}-third-party-
|
|
|
|
- name: Libraries cache.
|
|
uses: actions/cache@v6
|
|
with:
|
|
path: |
|
|
${{ env.LibrariesPath }}\*
|
|
!${{ env.LibrariesPath }}\cache_keys
|
|
!${{ env.LibrariesPath }}\[qQ]t[_-]*
|
|
${{ env.LibrariesPath }}\cache_keys\*
|
|
!${{ env.LibrariesPath }}\cache_keys\[qQ]t[_-]*
|
|
key: ${{ runner.OS }}-x64-libs-v2rel-${{ env.CACHE_KEY }}
|
|
restore-keys: ${{ runner.OS }}-x64-libs-v2rel-
|
|
|
|
- name: Qt cache.
|
|
uses: actions/cache@v6
|
|
with:
|
|
path: |
|
|
${{ env.LibrariesPath }}\[qQ]t[_-]*
|
|
${{ env.LibrariesPath }}\cache_keys\[qQ]t[_-]*
|
|
key: ${{ runner.OS }}-x64-qtrel-${{ env.CACHE_KEY }}
|
|
restore-keys: ${{ runner.OS }}-x64-qtrel-
|
|
|
|
- name: Libraries.
|
|
run: |
|
|
%TBUILD%\%REPO_NAME%\Telegram\build\prepare\win.bat silent
|
|
|
|
- name: Generate a stub DesktopPrivate.
|
|
shell: bash
|
|
run: |
|
|
# The Packer target includes packer_private.h at build time, but
|
|
# v2 canary packing never uses the v1 RSA keys, so random junk
|
|
# is enough (same approach as the nightly Release builds).
|
|
mkdir -p $TBUILD/DesktopPrivate
|
|
random_key() {
|
|
printf -- '-----BEGIN RSA PRIVATE KEY-----\\n%s\\n-----END RSA PRIVATE KEY-----\\n' \
|
|
"$(head -c 96 /dev/urandom | base64 | tr -d '\n')"
|
|
}
|
|
printf 'const char *PrivateKey = "%s";\nconst char *PrivateBetaKey = "%s";\n' \
|
|
"$(random_key)" "$(random_key)" > $TBUILD/DesktopPrivate/packer_private.h
|
|
printf 'static const char *AlphaPrivateKey = "%s";\n' \
|
|
"$(random_key)" > $TBUILD/DesktopPrivate/alpha_private.h
|
|
|
|
- name: Free up some disk space.
|
|
shell: bash
|
|
run: find $LibrariesPath '(' '(' ! '(' -name '*.lib' -o -name '*.a' -o -name '*.exe' -o -name '*.h' -o -name '*.hpp' -o -name '*.inc' -o -name '*.cmake' -o -name '*.pc' -o -path '*/include/*' -o -path '*/objects-*' -o -path '*/cache_keys/*' -o -path '*/patches/*' -o -path '*/nv-codec-headers/*' ')' -type f ')' -o -empty ')' -delete
|
|
|
|
- name: Telegram Desktop build.
|
|
run: |
|
|
cd %TBUILD%\%REPO_NAME%\Telegram
|
|
|
|
call configure.bat ^
|
|
x64 ^
|
|
-D TDESKTOP_API_ID=${{ secrets.CANARY_API_ID }} ^
|
|
-D TDESKTOP_API_HASH=${{ secrets.CANARY_API_HASH }} ^
|
|
-D CMAKE_CONFIGURATION_TYPES=Release ^
|
|
-D CMAKE_MSVC_DEBUG_INFORMATION_FORMAT= ^
|
|
-D DESKTOP_APP_SPECIAL_TARGET=win64 ^
|
|
-D DESKTOP_APP_ENABLE_LTO=ON ^
|
|
-D DESKTOP_APP_DISABLE_AUTOUPDATE=OFF ^
|
|
-D DESKTOP_APP_DISABLE_CRASH_REPORTS=OFF ^
|
|
-D TDESKTOP_CANARY_COUNTER=%CANARY_COUNTER% ^
|
|
-D TDESKTOP_CANARY_COMMIT=${{ needs.version.outputs.commit }} ^
|
|
%CANARY_DEFINES%
|
|
|
|
cmake --build ..\out --config Release --parallel
|
|
|
|
- name: Dump debug symbols.
|
|
shell: bash
|
|
run: |
|
|
# Pre-strip (PDBs are separate on Windows anyway): breakpad
|
|
# layout MODULE/DEBUG_ID/MODULE.sym for the crash server.
|
|
cd $TBUILD/$REPO_NAME/out/Release
|
|
DUMP=$TBUILD/Libraries/win64/breakpad/src/tools/windows/dump_syms/Release/dump_syms.exe
|
|
mkdir -p symbols
|
|
for MODULE in Telegram Updater; do
|
|
"$DUMP" $MODULE.pdb > $MODULE.sym
|
|
DEBUG_ID=$(head -n 1 $MODULE.sym | awk '{ print $4 }')
|
|
mkdir -p symbols/$MODULE.pdb/$DEBUG_ID
|
|
mv $MODULE.sym symbols/$MODULE.pdb/$DEBUG_ID/
|
|
done
|
|
# TODO(canary-infra): upload out/Release/symbols/ to R2, e.g.
|
|
# aws s3 sync symbols/ s3://$R2_SYMBOLS_BUCKET/ \
|
|
# --endpoint-url https://$R2_ACCOUNT_ID.r2.cloudflarestorage.com
|
|
|
|
- name: Sign binaries.
|
|
shell: bash
|
|
env:
|
|
SM_API_KEY: ${{ secrets.SM_API_KEY }}
|
|
SM_CLIENT_CERT_FILE_B64: ${{ secrets.SM_CLIENT_CERT_FILE_B64 }}
|
|
SM_CLIENT_CERT_PASSWORD: ${{ secrets.SM_CLIENT_CERT_PASSWORD }}
|
|
SM_HOST: ${{ secrets.SM_HOST }}
|
|
SM_KEYPAIR_ALIAS: ${{ secrets.SM_KEYPAIR_ALIAS }}
|
|
run: |
|
|
cd $TBUILD/$REPO_NAME/out/Release
|
|
if [ -z "$SM_API_KEY" ]; then
|
|
echo "::warning::KeyLocker secrets absent, leaving binaries unsigned."
|
|
exit 0
|
|
fi
|
|
# TODO(canary-infra): install the DigiCert KeyLocker tools once
|
|
# the account exists. The signing itself is:
|
|
echo "$SM_CLIENT_CERT_FILE_B64" | base64 -d > /tmp/keylocker.p12
|
|
export SM_CLIENT_CERT_FILE=/tmp/keylocker.p12
|
|
smctl sign --keypair-alias "$SM_KEYPAIR_ALIAS" --input Telegram.exe
|
|
smctl sign --keypair-alias "$SM_KEYPAIR_ALIAS" --input Updater.exe
|
|
|
|
- name: Azure login for update signing.
|
|
if: needs.version.outputs.publish == 'true'
|
|
uses: azure/login@v2
|
|
with:
|
|
client-id: ${{ secrets.AZURE_CLIENT_ID }}
|
|
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
|
|
allow-no-subscriptions: true
|
|
|
|
- name: Pack v2 update.
|
|
shell: bash
|
|
run: |
|
|
cd $TBUILD/$REPO_NAME/out/Release
|
|
./Packer.exe -path Telegram.exe -path Updater.exe \
|
|
-target win64 \
|
|
-version ${{ needs.version.outputs.base }} \
|
|
-channel canary-${{ needs.version.outputs.channel }} \
|
|
-counter $CANARY_COUNTER \
|
|
-keys-loc ../../Telegram/Resources/update \
|
|
-emit-signing-input signing-input.bin
|
|
if [ "${{ needs.version.outputs.publish }}" = "true" ]; then
|
|
python3 ../../Telegram/build/sign_update.py \
|
|
--input signing-input.bin \
|
|
--output canary.sig \
|
|
--az-vault "${{ secrets.AZURE_KEYVAULT_NAME }}" \
|
|
--az-key "$CANARY_KEY_ID"
|
|
./Packer.exe -channel canary-${{ needs.version.outputs.channel }} \
|
|
-keys-loc ../../Telegram/Resources/update \
|
|
-unsigned update-win-x64-$CANARY_TAG-${{ needs.version.outputs.base }}-$CANARY_COUNTER.unsigned \
|
|
-embed-signatures $CANARY_KEY_ID:canary.sig
|
|
else
|
|
echo "::warning::No publish secrets, keeping the unsigned envelope only."
|
|
fi
|
|
mkdir artifact
|
|
mv update-win-x64-$CANARY_TAG-* artifact/
|
|
mv Telegram.exe Updater.exe artifact/
|
|
|
|
- uses: actions/upload-artifact@v7
|
|
name: Upload artifact.
|
|
with:
|
|
name: canary-win64
|
|
path: ${{ env.TBUILD }}\${{ env.REPO_NAME }}\out\Release\artifact\
|
|
|
|
macos:
|
|
name: macOS universal (${{ needs.version.outputs.channel }})
|
|
runs-on: depot-macos-latest
|
|
needs: version
|
|
environment: canary
|
|
|
|
env:
|
|
PREPARE_PATH: "Telegram/build/prepare/prepare.py"
|
|
|
|
steps:
|
|
- name: Get repository name.
|
|
run: echo "REPO_NAME=${GITHUB_REPOSITORY##*/}" >> $GITHUB_ENV
|
|
|
|
- name: Clone.
|
|
uses: actions/checkout@v7
|
|
with:
|
|
submodules: recursive
|
|
path: ${{ env.REPO_NAME }}
|
|
|
|
- name: Read canary configuration.
|
|
run: |
|
|
echo "CANARY_COUNTER=${{ needs.version.outputs.counter }}" >> $GITHUB_ENV
|
|
if [ "${{ needs.version.outputs.channel }}" = "public" ]; then
|
|
echo "CANARY_TAG=canarypub" >> $GITHUB_ENV
|
|
echo "CANARY_KEY_ID=${{ vars.CANARY_SIGNING_KEY_ID }}" >> $GITHUB_ENV
|
|
echo "CANARY_DEFINES=-D TDESKTOP_UPDATE_CHANNEL=canary-public -D TDESKTOP_CANARY_PUBLIC_CHANNEL=${{ vars.CANARY_PUBLIC_CHANNEL_USERNAME }} -D TDESKTOP_CANARY_METADATA_MSG_ID=${{ vars.CANARY_METADATA_MSG_ID }}" >> $GITHUB_ENV
|
|
else
|
|
echo "CANARY_TAG=canarypriv" >> $GITHUB_ENV
|
|
echo "CANARY_KEY_ID=${{ vars.CANARY_PRIVATE_SIGNING_KEY_ID }}" >> $GITHUB_ENV
|
|
echo "CANARY_DEFINES=-D TDESKTOP_UPDATE_CHANNEL=canary-private -D TDESKTOP_CANARY_PRIVATE_CHANNEL_ID=${{ secrets.CANARY_PRIVATE_CHANNEL_ID }} -D TDESKTOP_CANARY_METADATA_MSG_ID=${{ vars.CANARY_PRIVATE_METADATA_MSG_ID }}" >> $GITHUB_ENV
|
|
fi
|
|
|
|
- name: First set up.
|
|
run: |
|
|
sudo chown -R `whoami`:admin /usr/local/share
|
|
|
|
brew update
|
|
brew upgrade || true
|
|
brew install automake libtool meson nasm ninja pkg-config
|
|
|
|
sudo mdutil -a -i off
|
|
|
|
sudo xcode-select -s /Applications/Xcode.app/Contents/Developer
|
|
|
|
- name: Libraries cache.
|
|
uses: actions/cache@v6
|
|
with:
|
|
path: |
|
|
Libraries
|
|
ThirdParty
|
|
key: ${{ runner.OS }}-libsrel-${{ hashFiles(format('{0}/{1}', env.REPO_NAME, env.PREPARE_PATH)) }}
|
|
restore-keys: ${{ runner.OS }}-libsrel-
|
|
|
|
- name: Libraries.
|
|
run: |
|
|
./$REPO_NAME/Telegram/build/prepare/mac.sh silent
|
|
|
|
- name: Generate a stub DesktopPrivate.
|
|
run: |
|
|
mkdir -p DesktopPrivate
|
|
random_key() {
|
|
printf -- '-----BEGIN RSA PRIVATE KEY-----\\n%s\\n-----END RSA PRIVATE KEY-----\\n' \
|
|
"$(head -c 96 /dev/urandom | base64 | tr -d '\n')"
|
|
}
|
|
printf 'const char *PrivateKey = "%s";\nconst char *PrivateBetaKey = "%s";\n' \
|
|
"$(random_key)" "$(random_key)" > DesktopPrivate/packer_private.h
|
|
printf 'static const char *AlphaPrivateKey = "%s";\n' \
|
|
"$(random_key)" > DesktopPrivate/alpha_private.h
|
|
|
|
- name: Free up some disk space.
|
|
run: find Libraries '(' '(' ! '(' -name '*.a' -o -name '*.h' -o -name '*.hpp' -o -name '*.inc' -o -name '*.cmake' -o -path '*/include/*' -o -path '*/objects-*' -o -path '*/cache_keys/*' -o -path '*/patches/*' -o -perm +111 ')' -type f ')' -o -empty ')' -delete
|
|
|
|
- name: Telegram Desktop build.
|
|
run: |
|
|
cd $REPO_NAME/Telegram
|
|
|
|
./configure.sh \
|
|
-D CMAKE_CONFIGURATION_TYPES=Release \
|
|
-D CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED=NO \
|
|
-D CMAKE_POLICY_DEFAULT_CMP0069=NEW \
|
|
-D CMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE=ON \
|
|
-D CMAKE_OSX_ARCHITECTURES="x86_64;arm64" \
|
|
-D TDESKTOP_API_ID=${{ secrets.CANARY_API_ID }} \
|
|
-D TDESKTOP_API_HASH=${{ secrets.CANARY_API_HASH }} \
|
|
-D DESKTOP_APP_SPECIAL_TARGET=mac \
|
|
-D DESKTOP_APP_DISABLE_AUTOUPDATE=OFF \
|
|
-D DESKTOP_APP_DISABLE_CRASH_REPORTS=OFF \
|
|
-D TDESKTOP_CANARY_COUNTER=$CANARY_COUNTER \
|
|
-D TDESKTOP_CANARY_COMMIT=${{ needs.version.outputs.commit }} \
|
|
$CANARY_DEFINES
|
|
|
|
cmake --build ../out --config Release --parallel
|
|
|
|
- name: Dump debug symbols.
|
|
run: |
|
|
cd $REPO_NAME/out/Release
|
|
DUMP=../../../Libraries/breakpad/src/tools/mac/dump_syms/build/Release/dump_syms
|
|
mkdir -p symbols
|
|
for ARCH in x86_64 arm64; do
|
|
for MODULE in Telegram Updater; do
|
|
BINARY=Telegram.app/Contents/MacOS/Telegram
|
|
if [ "$MODULE" = "Updater" ]; then
|
|
BINARY=Telegram.app/Contents/Frameworks/Updater
|
|
fi
|
|
"$DUMP" -a $ARCH "$BINARY" > $MODULE.sym 2>/dev/null
|
|
DEBUG_ID=$(head -n 1 $MODULE.sym | awk '{ print $4 }')
|
|
mkdir -p symbols/$MODULE/$DEBUG_ID
|
|
mv $MODULE.sym symbols/$MODULE/$DEBUG_ID/
|
|
done
|
|
done
|
|
# TODO(canary-infra): upload symbols/ to R2 (see the Windows job).
|
|
|
|
- name: Prepare per-arch bundles.
|
|
run: |
|
|
# One universal compile, then per-arch update bundles exactly
|
|
# like build.sh: copy the bundle and lipo -thin the Mach-O
|
|
# files. The universal app itself becomes the installer.
|
|
cd $REPO_NAME/out/Release
|
|
BINARIES="MacOS/Telegram Frameworks/Updater Helpers/crashpad_handler"
|
|
for ARCH in x86_64 arm64; do
|
|
rm -rf Telegram.$ARCH.app
|
|
cp -R Telegram.app Telegram.$ARCH.app
|
|
for BINARY in $BINARIES; do
|
|
lipo -thin $ARCH Telegram.app/Contents/$BINARY \
|
|
-output Telegram.$ARCH.app/Contents/$BINARY
|
|
strip Telegram.$ARCH.app/Contents/$BINARY
|
|
done
|
|
done
|
|
for BINARY in $BINARIES; do
|
|
strip Telegram.app/Contents/$BINARY
|
|
done
|
|
|
|
- name: Sign and notarize.
|
|
env:
|
|
CERTIFICATE_P12_B64: ${{ secrets.MACOS_CERTIFICATE_P12_B64 }}
|
|
CERTIFICATE_PASSWORD: ${{ secrets.MACOS_CERTIFICATE_PASSWORD }}
|
|
KEYCHAIN_PASSWORD: ${{ secrets.MACOS_KEYCHAIN_PASSWORD }}
|
|
SIGN_IDENTITY: ${{ secrets.MACOS_SIGN_IDENTITY }}
|
|
NOTARY_APPLE_ID: ${{ secrets.NOTARY_APPLE_ID }}
|
|
NOTARY_TEAM_ID: ${{ secrets.NOTARY_TEAM_ID }}
|
|
NOTARY_PASSWORD: ${{ secrets.NOTARY_PASSWORD }}
|
|
run: |
|
|
cd $REPO_NAME/out/Release
|
|
if [ -z "$CERTIFICATE_P12_B64" ]; then
|
|
echo "::warning::No signing certificate, leaving the apps unsigned."
|
|
exit 0
|
|
fi
|
|
echo "$CERTIFICATE_P12_B64" | base64 -d > /tmp/certificate.p12
|
|
security create-keychain -p "$KEYCHAIN_PASSWORD" build.keychain
|
|
security default-keychain -s build.keychain
|
|
security unlock-keychain -p "$KEYCHAIN_PASSWORD" build.keychain
|
|
security import /tmp/certificate.p12 -k build.keychain \
|
|
-P "$CERTIFICATE_PASSWORD" -T /usr/bin/codesign
|
|
security set-key-partition-list -S apple-tool:,apple:,codesign: \
|
|
-s -k "$KEYCHAIN_PASSWORD" build.keychain
|
|
|
|
for BUNDLE in Telegram.x86_64.app Telegram.arm64.app Telegram.app; do
|
|
codesign --force --deep --timestamp --options runtime \
|
|
--sign "$SIGN_IDENTITY" \
|
|
--entitlements ../../Telegram/Telegram/Telegram.entitlements \
|
|
"$BUNDLE"
|
|
codesign --verify --deep --strict "$BUNDLE"
|
|
ditto -c -k --keepParent "$BUNDLE" notarize.zip
|
|
xcrun notarytool submit notarize.zip --wait \
|
|
--apple-id "$NOTARY_APPLE_ID" \
|
|
--team-id "$NOTARY_TEAM_ID" \
|
|
--password "$NOTARY_PASSWORD"
|
|
xcrun stapler staple "$BUNDLE"
|
|
rm notarize.zip
|
|
done
|
|
|
|
- name: Azure login for update signing.
|
|
if: needs.version.outputs.publish == 'true'
|
|
uses: azure/login@v2
|
|
with:
|
|
client-id: ${{ secrets.AZURE_CLIENT_ID }}
|
|
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
|
|
allow-no-subscriptions: true
|
|
|
|
- name: Pack v2 updates.
|
|
run: |
|
|
cd $REPO_NAME/out/Release
|
|
BASE=${{ needs.version.outputs.base }}
|
|
for ARCH in x86_64 arm64; do
|
|
SHORT=x64
|
|
if [ "$ARCH" = "arm64" ]; then SHORT=arm; fi
|
|
|
|
# The thinned bundle is packed under the canonical app name,
|
|
# so the file paths inside the update match the install.
|
|
rm -rf update_pack
|
|
mkdir update_pack
|
|
cp -R Telegram.$ARCH.app update_pack/Telegram.app
|
|
cp Packer update_pack/
|
|
cd update_pack
|
|
./Packer -path Telegram.app \
|
|
-arch $ARCH \
|
|
-version $BASE \
|
|
-channel canary-${{ needs.version.outputs.channel }} \
|
|
-counter $CANARY_COUNTER \
|
|
-keys-loc ../../../Telegram/Resources/update \
|
|
-emit-signing-input signing-input.bin
|
|
if [ "${{ needs.version.outputs.publish }}" = "true" ]; then
|
|
python3 ../../../Telegram/build/sign_update.py \
|
|
--input signing-input.bin \
|
|
--output canary.sig \
|
|
--az-vault "${{ secrets.AZURE_KEYVAULT_NAME }}" \
|
|
--az-key "$CANARY_KEY_ID"
|
|
./Packer -channel canary-${{ needs.version.outputs.channel }} \
|
|
-keys-loc ../../../Telegram/Resources/update \
|
|
-unsigned update-mac-$SHORT-$CANARY_TAG-$BASE-$CANARY_COUNTER.unsigned \
|
|
-embed-signatures $CANARY_KEY_ID:canary.sig
|
|
else
|
|
echo "::warning::No publish secrets, keeping the unsigned envelope only."
|
|
fi
|
|
mv update-mac-$SHORT-$CANARY_TAG-* ../
|
|
cd ..
|
|
rm -rf update_pack
|
|
done
|
|
|
|
INSTALLER=install-mac-universal-$CANARY_TAG-$BASE-$CANARY_COUNTER.zip
|
|
ditto -c -k --keepParent Telegram.app "$INSTALLER"
|
|
|
|
mkdir artifact
|
|
mv update-mac-*-$CANARY_TAG-* artifact/
|
|
mv "$INSTALLER" artifact/
|
|
|
|
- uses: actions/upload-artifact@v7
|
|
name: Upload artifact.
|
|
with:
|
|
name: canary-mac
|
|
path: ${{ env.REPO_NAME }}/out/Release/artifact/
|
|
|
|
linux:
|
|
name: Linux x64 (${{ needs.version.outputs.channel }})
|
|
runs-on: depot-ubuntu-latest-16
|
|
needs: version
|
|
environment: canary
|
|
|
|
env:
|
|
IMAGE_TAG: tdesktop:centos_env
|
|
|
|
steps:
|
|
- name: Clone.
|
|
uses: actions/checkout@v7
|
|
with:
|
|
submodules: recursive
|
|
|
|
- name: Read canary configuration.
|
|
run: |
|
|
echo "CANARY_COUNTER=${{ needs.version.outputs.counter }}" >> $GITHUB_ENV
|
|
if [ "${{ needs.version.outputs.channel }}" = "public" ]; then
|
|
echo "CANARY_TAG=canarypub" >> $GITHUB_ENV
|
|
echo "CANARY_KEY_ID=${{ vars.CANARY_SIGNING_KEY_ID }}" >> $GITHUB_ENV
|
|
echo "CANARY_DEFINES=-D TDESKTOP_UPDATE_CHANNEL=canary-public -D TDESKTOP_CANARY_PUBLIC_CHANNEL=${{ vars.CANARY_PUBLIC_CHANNEL_USERNAME }} -D TDESKTOP_CANARY_METADATA_MSG_ID=${{ vars.CANARY_METADATA_MSG_ID }}" >> $GITHUB_ENV
|
|
else
|
|
echo "CANARY_TAG=canarypriv" >> $GITHUB_ENV
|
|
echo "CANARY_KEY_ID=${{ vars.CANARY_PRIVATE_SIGNING_KEY_ID }}" >> $GITHUB_ENV
|
|
echo "CANARY_DEFINES=-D TDESKTOP_UPDATE_CHANNEL=canary-private -D TDESKTOP_CANARY_PRIVATE_CHANNEL_ID=${{ secrets.CANARY_PRIVATE_CHANNEL_ID }} -D TDESKTOP_CANARY_METADATA_MSG_ID=${{ vars.CANARY_PRIVATE_METADATA_MSG_ID }}" >> $GITHUB_ENV
|
|
fi
|
|
|
|
- name: First set up.
|
|
run: |
|
|
sudo apt update
|
|
curl -sSL https://install.python-poetry.org | python3 -
|
|
cd Telegram/build/docker/centos_env
|
|
poetry install
|
|
DOCKERFILE=$(DEBUG= poetry run gen_dockerfile)
|
|
echo "$DOCKERFILE" > Dockerfile
|
|
rm -rf __pycache__
|
|
|
|
- name: Free up some disk space.
|
|
uses: jlumbroso/free-disk-space@54081f138730dfa15788a46383842cd2f914a1be
|
|
with:
|
|
tool-cache: true
|
|
|
|
- name: Set up Docker Buildx.
|
|
id: setup-buildx
|
|
uses: docker/setup-buildx-action@v4
|
|
|
|
- name: Libraries cache.
|
|
id: cache-libs
|
|
uses: actions/cache@v6
|
|
with:
|
|
path: |
|
|
${{ runner.temp }}/.buildx-cache
|
|
${{ runner.temp }}/.mount-cache
|
|
key: ${{ runner.OS }}-libsrel-${{ hashFiles('Telegram/build/docker/centos_env/**') }}
|
|
restore-keys: ${{ runner.OS }}-libsrel-
|
|
|
|
- name: Restore Docker cache mounts.
|
|
uses: reproducible-containers/buildkit-cache-dance@5422eac04292c961a382e0f584ea0f03ad9da723
|
|
with:
|
|
builder: ${{ steps.setup-buildx.outputs.name }}
|
|
cache-dir: ${{ runner.temp }}/.mount-cache
|
|
dockerfile: Telegram/build/docker/centos_env/Dockerfile
|
|
skip-extraction: ${{ steps.cache-libs.outputs.cache-hit }}
|
|
|
|
- name: Libraries.
|
|
uses: docker/build-push-action@v7
|
|
with:
|
|
context: Telegram/build/docker/centos_env
|
|
load: true
|
|
tags: ${{ env.IMAGE_TAG }}
|
|
cache-from: type=local,src=${{ runner.temp }}/.buildx-cache
|
|
cache-to: type=local,dest=${{ runner.temp }}/.buildx-cache-new,mode=max
|
|
|
|
- name: Move cache.
|
|
run: |
|
|
rm -rf ${{ runner.temp }}/.buildx-cache
|
|
mv ${{ runner.temp }}/.buildx-cache{-new,}
|
|
|
|
- name: Generate a stub DesktopPrivate.
|
|
run: |
|
|
mkdir -p ../DesktopPrivate
|
|
random_key() {
|
|
printf -- '-----BEGIN RSA PRIVATE KEY-----\\n%s\\n-----END RSA PRIVATE KEY-----\\n' \
|
|
"$(head -c 96 /dev/urandom | base64 | tr -d '\n')"
|
|
}
|
|
printf 'const char *PrivateKey = "%s";\nconst char *PrivateBetaKey = "%s";\n' \
|
|
"$(random_key)" "$(random_key)" > ../DesktopPrivate/packer_private.h
|
|
printf 'static const char *AlphaPrivateKey = "%s";\n' \
|
|
"$(random_key)" > ../DesktopPrivate/alpha_private.h
|
|
|
|
- name: Telegram Desktop build.
|
|
run: |
|
|
docker run --rm \
|
|
-u $(id -u) \
|
|
-v $PWD:/usr/src/tdesktop \
|
|
-v $PWD/../DesktopPrivate:/usr/src/DesktopPrivate \
|
|
-e CONFIG=Release \
|
|
$IMAGE_TAG \
|
|
/usr/src/tdesktop/Telegram/build/docker/centos_env/build.sh \
|
|
-D CMAKE_CONFIGURATION_TYPES=Release \
|
|
-D CMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE=ON \
|
|
-D TDESKTOP_API_ID=${{ secrets.CANARY_API_ID }} \
|
|
-D TDESKTOP_API_HASH=${{ secrets.CANARY_API_HASH }} \
|
|
-D DESKTOP_APP_SPECIAL_TARGET=linux \
|
|
-D DESKTOP_APP_DISABLE_AUTOUPDATE=OFF \
|
|
-D DESKTOP_APP_DISABLE_CRASH_REPORTS=OFF \
|
|
-D TDESKTOP_CANARY_COUNTER=$CANARY_COUNTER \
|
|
-D TDESKTOP_CANARY_COMMIT=${{ needs.version.outputs.commit }} \
|
|
$CANARY_DEFINES
|
|
|
|
- name: Dump debug symbols.
|
|
run: |
|
|
cd out/Release
|
|
mkdir -p symbols
|
|
for MODULE in Telegram Updater; do
|
|
./dump_syms $MODULE > $MODULE.sym
|
|
DEBUG_ID=$(head -n 1 $MODULE.sym | awk '{ print $4 }')
|
|
mkdir -p symbols/$MODULE/$DEBUG_ID
|
|
mv $MODULE.sym symbols/$MODULE/$DEBUG_ID/
|
|
done
|
|
# TODO(canary-infra): upload symbols/ to R2 (see the Windows job).
|
|
../../Telegram/build/minidebug.sh Telegram
|
|
|
|
- name: Azure login for update signing.
|
|
if: needs.version.outputs.publish == 'true'
|
|
uses: azure/login@v2
|
|
with:
|
|
client-id: ${{ secrets.AZURE_CLIENT_ID }}
|
|
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
|
|
allow-no-subscriptions: true
|
|
|
|
- name: Pack v2 update.
|
|
run: |
|
|
cd out/Release
|
|
./Packer -path Telegram -path Updater \
|
|
-version ${{ needs.version.outputs.base }} \
|
|
-channel canary-${{ needs.version.outputs.channel }} \
|
|
-counter $CANARY_COUNTER \
|
|
-keys-loc ../../Telegram/Resources/update \
|
|
-emit-signing-input signing-input.bin
|
|
if [ "${{ needs.version.outputs.publish }}" = "true" ]; then
|
|
python3 ../../Telegram/build/sign_update.py \
|
|
--input signing-input.bin \
|
|
--output canary.sig \
|
|
--az-vault "${{ secrets.AZURE_KEYVAULT_NAME }}" \
|
|
--az-key "$CANARY_KEY_ID"
|
|
./Packer -channel canary-${{ needs.version.outputs.channel }} \
|
|
-keys-loc ../../Telegram/Resources/update \
|
|
-unsigned update-linux-x64-$CANARY_TAG-${{ needs.version.outputs.base }}-$CANARY_COUNTER.unsigned \
|
|
-embed-signatures $CANARY_KEY_ID:canary.sig
|
|
else
|
|
echo "::warning::No publish secrets, keeping the unsigned envelope only."
|
|
fi
|
|
mkdir artifact
|
|
mv update-linux-x64-$CANARY_TAG-* artifact/
|
|
mv Telegram Updater artifact/
|
|
|
|
- uses: actions/upload-artifact@v7
|
|
name: Upload artifact.
|
|
with:
|
|
name: canary-linux
|
|
path: out/Release/artifact/
|
|
|
|
publish:
|
|
name: Publish (${{ needs.version.outputs.channel }})
|
|
runs-on: ubuntu-latest
|
|
needs: [version, windows, macos, linux]
|
|
if: needs.version.outputs.publish == 'true'
|
|
environment: canary
|
|
|
|
services:
|
|
# Built from a pinned tdlib/telegram-bot-api ref by the
|
|
# canary-bot-api.yml workflow and referenced by digest: this
|
|
# container handles the bot token and the published files, so no
|
|
# third-party image is acceptable here.
|
|
telegram-bot-api:
|
|
image: ${{ vars.CANARY_BOT_API_IMAGE }}
|
|
env:
|
|
TELEGRAM_API_ID: ${{ secrets.CANARY_API_ID }}
|
|
TELEGRAM_API_HASH: ${{ secrets.CANARY_API_HASH }}
|
|
TELEGRAM_LOCAL: 1
|
|
ports:
|
|
- 8081:8081
|
|
|
|
env:
|
|
BOT_API: http://localhost:8081
|
|
BOT_TOKEN: ${{ secrets.CANARY_BOT_TOKEN }}
|
|
|
|
steps:
|
|
- name: Clone.
|
|
uses: actions/checkout@v7
|
|
with:
|
|
fetch-depth: 0
|
|
|
|
- name: Download artifacts.
|
|
uses: actions/download-artifact@v7
|
|
with:
|
|
path: artifacts
|
|
|
|
- name: Verify platform signatures.
|
|
run: |
|
|
# Publishing unsigned binaries is never allowed: this is a hard
|
|
# gate, not a warning. The per-arch update bundles were verified
|
|
# right after signing in the macOS job; here the installer app
|
|
# is re-checked as the publish-side witness.
|
|
sudo apt-get update && sudo apt-get install -y osslsigncode
|
|
FAILED=0
|
|
|
|
for EXE in Telegram.exe Updater.exe; do
|
|
if ! osslsigncode verify "artifacts/canary-win64/$EXE"; then
|
|
echo "::error::$EXE is not Authenticode-signed."
|
|
FAILED=1
|
|
fi
|
|
done
|
|
|
|
# TODO(canary-infra): pin an apple-codesign (rcodesign) release
|
|
# for full macOS signature+staple verification on Linux:
|
|
# rcodesign verify /tmp/macapp/Telegram.app
|
|
unzip -q artifacts/canary-mac/install-mac-universal-*.zip -d /tmp/macapp
|
|
if [ ! -d "/tmp/macapp/Telegram.app/Contents/_CodeSignature" ]; then
|
|
echo "::error::The installer Telegram.app has no code signature."
|
|
FAILED=1
|
|
fi
|
|
|
|
exit $FAILED
|
|
|
|
- name: Publish the channel.
|
|
env:
|
|
CHANNEL: ${{ needs.version.outputs.channel }}
|
|
PUBLIC_CHANNEL: ${{ secrets.CANARY_PUBLIC_CHANNEL_ID }}
|
|
PRIVATE_CHANNEL: ${{ secrets.CANARY_PRIVATE_CHANNEL_ID }}
|
|
PUBLIC_MSG_ID: ${{ vars.CANARY_METADATA_MSG_ID }}
|
|
PRIVATE_MSG_ID: ${{ vars.CANARY_PRIVATE_METADATA_MSG_ID }}
|
|
run: |
|
|
if [ "$CHANNEL" = "public" ]; then
|
|
CHAT_ID="$PUBLIC_CHANNEL"
|
|
MSG_ID="$PUBLIC_MSG_ID"
|
|
else
|
|
CHAT_ID="-100$PRIVATE_CHANNEL"
|
|
MSG_ID="$PRIVATE_MSG_ID"
|
|
fi
|
|
COUNTER="${{ needs.version.outputs.counter }}"
|
|
PREVIOUS="${{ needs.version.outputs.previous }}"
|
|
|
|
CAPTION=$({
|
|
echo "Canary #$COUNTER · ${{ needs.version.outputs.commit }}"
|
|
echo ""
|
|
if [ -n "$PREVIOUS" ] && git cat-file -e "$PREVIOUS^{commit}" 2>/dev/null; then
|
|
git log --no-merges --pretty=format:'• %s' "$PREVIOUS..HEAD" | head -20
|
|
else
|
|
git log --no-merges --pretty=format:'• %s' -10
|
|
fi
|
|
} | head -c 1000)
|
|
|
|
declare -A FILES
|
|
FILES[win64]=$(ls artifacts/canary-win64/update-win-x64-* | head -1)
|
|
FILES[mac]=$(ls artifacts/canary-mac/update-mac-x64-* | head -1)
|
|
FILES[armac]=$(ls artifacts/canary-mac/update-mac-arm-* | head -1)
|
|
FILES[linux]=$(ls artifacts/canary-linux/update-linux-x64-* | head -1)
|
|
|
|
declare -A POSTS
|
|
for PLATFORM in win64 mac armac linux; do
|
|
FILE=${FILES[$PLATFORM]}
|
|
if [ -z "$FILE" ] || [[ "$FILE" == *.unsigned ]]; then
|
|
echo "::error::$PLATFORM update is missing or unsigned, refusing to publish."
|
|
exit 1
|
|
fi
|
|
RESPONSE=$(curl -sf "$BOT_API/bot$BOT_TOKEN/sendDocument" \
|
|
-F chat_id="$CHAT_ID" \
|
|
-F document=@"$FILE" \
|
|
-F caption="$CAPTION")
|
|
POSTS[$PLATFORM]=$(echo "$RESPONSE" | jq -r '.result.message_id')
|
|
echo "$PLATFORM -> post ${POSTS[$PLATFORM]}"
|
|
done
|
|
|
|
# The universal installer is for first installs, posted as a
|
|
# plain document and not referenced from the metadata.
|
|
INSTALLER=$(ls artifacts/canary-mac/install-mac-universal-* | head -1)
|
|
curl -sf "$BOT_API/bot$BOT_TOKEN/sendDocument" \
|
|
-F chat_id="$CHAT_ID" \
|
|
-F document=@"$INSTALLER" \
|
|
-F caption="macOS installer, $CAPTION" > /dev/null
|
|
|
|
MANIFEST_B64=$(base64 -w0 Telegram/Resources/update/manifest.min.json)
|
|
MANIFEST_SIG_B64=$(base64 -w0 Telegram/Resources/update/manifest.sig)
|
|
|
|
NEW=$(jq -n \
|
|
--arg manifest "$MANIFEST_B64" \
|
|
--arg manifest_sig "$MANIFEST_SIG_B64" \
|
|
--arg commit "${{ needs.version.outputs.commit }}" \
|
|
--argjson base "${{ needs.version.outputs.base }}" \
|
|
--argjson counter "$COUNTER" \
|
|
--argjson win64 "${POSTS[win64]}" \
|
|
--argjson mac "${POSTS[mac]}" \
|
|
--argjson armac "${POSTS[armac]}" \
|
|
--argjson linux "${POSTS[linux]}" \
|
|
"{
|
|
format: 1,
|
|
manifest: \$manifest,
|
|
manifest_sig: \$manifest_sig,
|
|
channels: {
|
|
\"canary-$CHANNEL\": {
|
|
base: \$base,
|
|
counter: \$counter,
|
|
commit: \$commit,
|
|
posts: {
|
|
win64: \$win64,
|
|
mac: \$mac,
|
|
armac: \$armac,
|
|
linux: \$linux
|
|
}
|
|
}
|
|
}
|
|
}")
|
|
curl -sf "$BOT_API/bot$BOT_TOKEN/editMessageText" \
|
|
-F chat_id="$CHAT_ID" \
|
|
-F message_id="$MSG_ID" \
|
|
--form-string text="$NEW" || {
|
|
echo "::error::Could not edit the metadata message $MSG_ID."
|
|
exit 1
|
|
}
|