diff --git a/.github/workflows/canary.yml b/.github/workflows/canary.yml index 86c7358ef0..ae0fc3a90d 100644 --- a/.github/workflows/canary.yml +++ b/.github/workflows/canary.yml @@ -1,31 +1,29 @@ -# Canary channels: single Release+LTO build per platform (Windows x64, -# universal macOS, Linux x64 through docker), for both the public and the -# private canary channel, signed, packed as v2 updates and published via -# a local Bot API server. +# 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 both canary channels (posts files, edits metadata). -# secrets.CANARY_PUBLIC_CHANNEL_ID -# Numeric -100... public channel id for the Bot API calls. -# 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_PUBLIC_CHANNEL_USERNAME -# Public channel username compiled into canary-public builds. -# vars.CANARY_METADATA_MSG_ID / vars.CANARY_PRIVATE_METADATA_MSG_ID -# Fixed ids of the pinned metadata messages in the two channels. +# Bot admin in this lane's channel (posts files, edits metadata). # secrets.AZURE_CLIENT_ID / secrets.AZURE_TENANT_ID -# Entra federated credential for OIDC az login (id-token: write). +# This lane's Entra federated credential for OIDC az login +# (id-token: write). # secrets.AZURE_KEYVAULT_NAME -# Key Vault holding the canary ES256 keys. -# vars.CANARY_SIGNING_KEY_ID / vars.CANARY_PRIVATE_SIGNING_KEY_ID -# Key Vault key names, must match the manifest ids -# ("cp-2026a" / "cx-2026a"). +# 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 @@ -39,6 +37,25 @@ # secrets.R2_SECRET_ACCESS_KEY / vars.R2_SYMBOLS_BUCKET # Cloudflare R2 bucket for breakpad symbols (upload placeholder). # +# 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. @@ -65,12 +82,11 @@ jobs: environment: canary outputs: + channel: ${{ steps.compute.outputs.channel }} base: ${{ steps.compute.outputs.base }} commit: ${{ steps.compute.outputs.commit }} - counter_public: ${{ steps.compute.outputs.counter_public }} - counter_private: ${{ steps.compute.outputs.counter_private }} - previous_public: ${{ steps.compute.outputs.previous_public }} - previous_private: ${{ steps.compute.outputs.previous_private }} + counter: ${{ steps.compute.outputs.counter }} + previous: ${{ steps.compute.outputs.previous }} publish: ${{ steps.compute.outputs.publish }} steps: @@ -81,13 +97,41 @@ jobs: # must survive force-pushes and rebases of the canary branch. fetch-depth: 0 - - name: Compute canary versions. + - 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 @@ -100,40 +144,33 @@ jobs: fi echo "publish=$PUBLISH" >> $GITHUB_OUTPUT - compute_counter() { # $1 = chat id, $2 = channel name, $3 = suffix - local COUNTER=1 - local PREVIOUS="" - if [ "$PUBLISH" = "true" ] && [ -n "$1" ]; then - local PINNED=$(curl -sf "https://api.telegram.org/bot$BOT_TOKEN/getChat?chat_id=$1" \ - | jq -r '.result.pinned_message.text // empty') - if [ -n "$PINNED" ]; then - local OLD_BASE=$(echo "$PINNED" | jq -r ".channels.\"$2\".base // 0") - local OLD_COUNTER=$(echo "$PINNED" | jq -r ".channels.\"$2\".counter // 0") - PREVIOUS=$(echo "$PINNED" | jq -r ".channels.\"$2\".commit // empty") - if [ "$OLD_BASE" = "$BASE" ]; then - COUNTER=$((OLD_COUNTER + 1)) - fi + 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 - echo "counter_$3=$COUNTER" >> $GITHUB_OUTPUT - echo "previous_$3=$PREVIOUS" >> $GITHUB_OUTPUT - echo "canary-$3: $BASE #$COUNTER" - } - compute_counter "$PUBLIC_CHANNEL" "canary-public" public - compute_counter "-100$PRIVATE_CHANNEL" "canary-private" private + 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 (${{ matrix.channel }}) + name: Windows x64 (${{ needs.version.outputs.channel }}) runs-on: depot-windows-latest-16 needs: version environment: canary - strategy: - matrix: - channel: [public, private] - # win-arm64 is phase 2: add an arch dimension 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. + # 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" @@ -163,14 +200,13 @@ jobs: - name: Read canary configuration. shell: bash run: | - if [ "${{ matrix.channel }}" = "public" ]; then + echo "CANARY_COUNTER=${{ needs.version.outputs.counter }}" >> $GITHUB_ENV + if [ "${{ needs.version.outputs.channel }}" = "public" ]; then echo "CANARY_TAG=canarypub" >> $GITHUB_ENV - echo "CANARY_COUNTER=${{ needs.version.outputs.counter_public }}" >> $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_COUNTER=${{ needs.version.outputs.counter_private }}" >> $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 @@ -330,7 +366,7 @@ jobs: ./Packer.exe -path Telegram.exe -path Updater.exe \ -target win64 \ -version ${{ needs.version.outputs.base }} \ - -channel canary-${{ matrix.channel }} \ + -channel canary-${{ needs.version.outputs.channel }} \ -counter $CANARY_COUNTER \ -keys-loc ../../Telegram/Resources/update \ -emit-signing-input signing-input.bin @@ -340,7 +376,7 @@ jobs: --output canary.sig \ --az-vault "${{ secrets.AZURE_KEYVAULT_NAME }}" \ --az-key "$CANARY_KEY_ID" - ./Packer.exe -channel canary-${{ matrix.channel }} \ + ./Packer.exe -channel canary-${{ needs.version.outputs.channel }} \ -keys-loc ../../Telegram/Resources/update \ -unsigned tv2-win64-$CANARY_TAG-${{ needs.version.outputs.base }}-$CANARY_COUNTER.unsigned \ -embed-signatures $CANARY_KEY_ID:canary.sig @@ -354,19 +390,15 @@ jobs: - uses: actions/upload-artifact@v7 name: Upload artifact. with: - name: canary-${{ matrix.channel }}-win64 + name: canary-win64 path: ${{ env.TBUILD }}\${{ env.REPO_NAME }}\out\Release\artifact\ macos: - name: macOS universal (${{ matrix.channel }}) + name: macOS universal (${{ needs.version.outputs.channel }}) runs-on: depot-macos-latest needs: version environment: canary - strategy: - matrix: - channel: [public, private] - env: PREPARE_PATH: "Telegram/build/prepare/prepare.py" @@ -382,14 +414,13 @@ jobs: - name: Read canary configuration. run: | - if [ "${{ matrix.channel }}" = "public" ]; then + echo "CANARY_COUNTER=${{ needs.version.outputs.counter }}" >> $GITHUB_ENV + if [ "${{ needs.version.outputs.channel }}" = "public" ]; then echo "CANARY_TAG=canarypub" >> $GITHUB_ENV - echo "CANARY_COUNTER=${{ needs.version.outputs.counter_public }}" >> $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_COUNTER=${{ needs.version.outputs.counter_private }}" >> $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 @@ -523,7 +554,7 @@ jobs: cd $REPO_NAME/out/Release ./Packer -path Telegram.app \ -version ${{ needs.version.outputs.base }} \ - -channel canary-${{ matrix.channel }} \ + -channel canary-${{ needs.version.outputs.channel }} \ -counter $CANARY_COUNTER \ -keys-loc ../../Telegram/Resources/update \ -emit-signing-input signing-input.bin @@ -533,7 +564,7 @@ jobs: --output canary.sig \ --az-vault "${{ secrets.AZURE_KEYVAULT_NAME }}" \ --az-key "$CANARY_KEY_ID" - ./Packer -channel canary-${{ matrix.channel }} \ + ./Packer -channel canary-${{ needs.version.outputs.channel }} \ -keys-loc ../../Telegram/Resources/update \ -unsigned tv2-mac-$CANARY_TAG-${{ needs.version.outputs.base }}-$CANARY_COUNTER.unsigned \ -embed-signatures $CANARY_KEY_ID:canary.sig @@ -547,19 +578,15 @@ jobs: - uses: actions/upload-artifact@v7 name: Upload artifact. with: - name: canary-${{ matrix.channel }}-mac + name: canary-mac path: ${{ env.REPO_NAME }}/out/Release/artifact/ linux: - name: Linux x64 (${{ matrix.channel }}) + name: Linux x64 (${{ needs.version.outputs.channel }}) runs-on: depot-ubuntu-latest-16 needs: version environment: canary - strategy: - matrix: - channel: [public, private] - env: IMAGE_TAG: tdesktop:centos_env @@ -571,14 +598,13 @@ jobs: - name: Read canary configuration. run: | - if [ "${{ matrix.channel }}" = "public" ]; then + echo "CANARY_COUNTER=${{ needs.version.outputs.counter }}" >> $GITHUB_ENV + if [ "${{ needs.version.outputs.channel }}" = "public" ]; then echo "CANARY_TAG=canarypub" >> $GITHUB_ENV - echo "CANARY_COUNTER=${{ needs.version.outputs.counter_public }}" >> $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_COUNTER=${{ needs.version.outputs.counter_private }}" >> $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 @@ -692,7 +718,7 @@ jobs: cd out/Release ./Packer -path Telegram -path Updater \ -version ${{ needs.version.outputs.base }} \ - -channel canary-${{ matrix.channel }} \ + -channel canary-${{ needs.version.outputs.channel }} \ -counter $CANARY_COUNTER \ -keys-loc ../../Telegram/Resources/update \ -emit-signing-input signing-input.bin @@ -702,7 +728,7 @@ jobs: --output canary.sig \ --az-vault "${{ secrets.AZURE_KEYVAULT_NAME }}" \ --az-key "$CANARY_KEY_ID" - ./Packer -channel canary-${{ matrix.channel }} \ + ./Packer -channel canary-${{ needs.version.outputs.channel }} \ -keys-loc ../../Telegram/Resources/update \ -unsigned tv2-linux-$CANARY_TAG-${{ needs.version.outputs.base }}-$CANARY_COUNTER.unsigned \ -embed-signatures $CANARY_KEY_ID:canary.sig @@ -716,11 +742,11 @@ jobs: - uses: actions/upload-artifact@v7 name: Upload artifact. with: - name: canary-${{ matrix.channel }}-linux + name: canary-linux path: out/Release/artifact/ publish: - name: Publish + name: Publish (${{ needs.version.outputs.channel }}) runs-on: ubuntu-latest needs: [version, windows, macos, linux] if: needs.version.outputs.publish == 'true' @@ -758,105 +784,102 @@ jobs: sudo apt-get update && sudo apt-get install -y osslsigncode FAILED=0 - for CHANNEL in public private; do - for EXE in Telegram.exe Updater.exe; do - if ! osslsigncode verify "artifacts/canary-$CHANNEL-win64/$EXE"; then - echo "::error::canary-$CHANNEL $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 artifacts/canary-$CHANNEL-mac/Telegram.app - if [ ! -d "artifacts/canary-$CHANNEL-mac/Telegram.app/Contents/_CodeSignature" ]; then - echo "::error::canary-$CHANNEL Telegram.app has no code signature." + 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 artifacts/canary-mac/Telegram.app + if [ ! -d "artifacts/canary-mac/Telegram.app/Contents/_CodeSignature" ]; then + echo "::error::Telegram.app has no code signature." + FAILED=1 + fi + exit $FAILED - - name: Publish both channels. + - 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 POSTS + for PLATFORM in win64 mac linux; do + FILE=$(ls artifacts/canary-$PLATFORM/tv2-* | head -1) + if [[ "$FILE" == *.unsigned ]]; then + echo "::error::$PLATFORM update is 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 + MANIFEST_B64=$(base64 -w0 Telegram/Resources/update/manifest.min.json) MANIFEST_SIG_B64=$(base64 -w0 Telegram/Resources/update/manifest.sig) - make_changelog() { # $1 = previous commit, $2 = counter - { - echo "Canary #$2 · ${{ needs.version.outputs.commit }}" - echo "" - if [ -n "$1" ] && git cat-file -e "$1^{commit}" 2>/dev/null; then - git log --no-merges --pretty=format:'• %s' "$1..HEAD" | head -20 - else - git log --no-merges --pretty=format:'• %s' -10 - fi - } | head -c 1000 - } - - publish_channel() { # $1=channel $2=chat_id $3=msg_id $4=counter $5=previous - local CAPTION=$(make_changelog "$5" "$4") - declare -A POSTS - for PLATFORM in win64 mac linux; do - local FILE=$(ls artifacts/canary-$1-$PLATFORM/tv2-* | head -1) - if [[ "$FILE" == *.unsigned ]]; then - echo "::error::canary-$1 $PLATFORM update is unsigned, refusing to publish." - return 1 - fi - local RESPONSE=$(curl -sf "$BOT_API/bot$BOT_TOKEN/sendDocument" \ - -F chat_id="$2" \ - -F document=@"$FILE" \ - -F caption="$CAPTION") - POSTS[$PLATFORM]=$(echo "$RESPONSE" | jq -r '.result.message_id') - echo "canary-$1 $PLATFORM -> post ${POSTS[$PLATFORM]}" - done - - # The macOS build is universal, both runtime platform keys - # point at the same post. - local 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 "$4" \ - --argjson win64 "${POSTS[win64]}" \ - --argjson mac "${POSTS[mac]}" \ - --argjson linux "${POSTS[linux]}" \ - "{ - format: 1, - manifest: \$manifest, - manifest_sig: \$manifest_sig, - channels: { - \"canary-$1\": { - base: \$base, - counter: \$counter, - commit: \$commit, - posts: { - win64: \$win64, - mac: \$mac, - armac: \$mac, - linux: \$linux - } + # The macOS build is universal, both runtime platform keys + # point at the same post. + 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 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: \$mac, + linux: \$linux } } - }") - curl -sf "$BOT_API/bot$BOT_TOKEN/editMessageText" \ - -F chat_id="$2" \ - -F message_id="$3" \ - --form-string text="$NEW" || { - echo "::error::Could not edit the canary-$1 metadata message $3." - return 1 } - } - - publish_channel public "$PUBLIC_CHANNEL" "$PUBLIC_MSG_ID" \ - "${{ needs.version.outputs.counter_public }}" \ - "${{ needs.version.outputs.previous_public }}" - publish_channel private "-100$PRIVATE_CHANNEL" "$PRIVATE_MSG_ID" \ - "${{ needs.version.outputs.counter_private }}" \ - "${{ needs.version.outputs.previous_private }}" + }") + 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 + }