Skip to content

Update WAProto #136 #136

Update WAProto #136

Update WAProto #136 #136

Workflow file for this run

name: Update WAProto
on:
schedule:
- cron: '0 3 * * *'
workflow_dispatch:
# Dynamic run name with run number
run-name: "Update WAProto #${{ github.run_number }}"
permissions:
contents: write
pull-requests: write
actions: write
jobs:
update-proto:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
- name: Install Node
uses: actions/setup-node@v4
with:
node-version: 20.x
- name: Enable Corepack and Set Yarn Version
run: |
corepack enable
corepack prepare yarn@4.x --activate
- name: Configure Git for HTTPS
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
# Force git to use HTTPS instead of SSH for GitHub repositories
git config --global url."https://github.com/".insteadOf "ssh://git@github.com/"
git config --global url."https://github.com/".insteadOf "git@github.com:"
# Configure git to use GITHUB_TOKEN for authentication
git config --global url."https://x-access-token:${GITHUB_TOKEN}@github.com/".insteadOf "https://github.com/"
- name: Install packages
run: |
yarn install --immutable
yarn --cwd proto-extract install --immutable
- name: Update WAProto.proto
id: wa_proto_info
run: |
yarn --cwd proto-extract start > wa-logs.txt
WA_VERSION=$(cat wa-logs.txt | perl -n -e'/Current version\: (.+)/ && print $1')
WA_JS_URL=$(cat wa-logs.txt | perl -n -e'/Found source JS URL\: (.+)/ && print $1')
echo "wa_version=$WA_VERSION" >> $GITHUB_OUTPUT
echo "wa_js_url=$WA_JS_URL" >> $GITHUB_OUTPUT
# Display version prominently
echo "πŸ“± WhatsApp Proto Version: v$WA_VERSION"
echo "πŸ”— Source JS URL: $WA_JS_URL"
- name: GenerateStatics
run: yarn gen:protobuf
# audit CI-03: `wa_version` comes from a regex over output produced by
# an external proto-extract run that fetches `web.whatsapp.com`. Pass
# it through an env var AND a numeric-only filter (`tr -cd '0-9.'`)
# so a hostile injection in the upstream output can't escape the JSON
# literal or the shell context. Empty input falls through to a hard
# fail rather than producing `{"version": []}`.
- name: Update baileys-version.json
env:
WA_VERSION: ${{steps.wa_proto_info.outputs.wa_version}}
run: |
SAFE_VERSION=$(printf '%s' "$WA_VERSION" | tr -cd '0-9.')
# Reject anything that isn't EXACTLY `N.N.N` β€” `tr -cd '0-9.'` strips
# non-numeric chars but leaves trailing/leading dots ("2.3000."
# would survive) and the resulting JSON literal would be malformed:
# `{"version": [2, 3000, ]}`. Tight regex makes baileys-version.json
# corruption impossible. (audit CI-03 followup, threads 8 + 10)
if ! printf '%s' "$SAFE_VERSION" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+$'; then
echo "::error::wa_version not a valid N.N.N triple after sanitisation: '$SAFE_VERSION' (raw='$WA_VERSION')"
exit 1
fi
WA_NUMBERS=$(printf '%s' "$SAFE_VERSION" | sed "s/\./, /g")
echo "{\"version\": [$WA_NUMBERS]}" > src/Defaults/baileys-version.json
# Confirm update
echo "βœ… Updated baileys-version.json to v$SAFE_VERSION"
cat src/Defaults/baileys-version.json
- name: Create Pull Request
id: create_pr
uses: peter-evans/create-pull-request@v5
with:
commit-message: 'chore: update proto/version to v${{steps.wa_proto_info.outputs.wa_version}}'
title: 'chore: update WhatsApp proto to v${{steps.wa_proto_info.outputs.wa_version}}'
branch: 'update-proto/stable'
delete-branch: true
labels: 'update-proto'
body: |
## πŸ“¦ Automated WhatsApp Proto Update
**Version:** `v${{steps.wa_proto_info.outputs.wa_version}}`
**Source JS URL:** ${{steps.wa_proto_info.outputs.wa_js_url}}
### Changes
- βœ… Updated `WAProto/*` (protobuf definitions)
- βœ… Updated `src/Defaults/baileys-version.json`
### Update Frequency
Daily at 03:00 UTC (00:00 BRT)
add-paths: |
WAProto/*
src/Defaults/baileys-version.json
- name: Enable Auto-merge
if: steps.create_pr.outputs.pull-request-number != ''
# audit CI-P1-B β€” `wa_version` was interpolated raw into the shell
# here (and in Summary below), bypassing the sanitisation that only
# happened inside the "Update baileys-version.json" step. Pass
# through env vars + filter so a hostile WhatsApp source response
# can't escape into command execution.
env:
GH_TOKEN: ${{ secrets.GH_PAT || secrets.GITHUB_TOKEN }}
PR_NUMBER_INPUT: ${{ steps.create_pr.outputs.pull-request-number }}
WA_VERSION_RAW: ${{ steps.wa_proto_info.outputs.wa_version }}
run: |
PR_NUMBER=$(printf '%s' "$PR_NUMBER_INPUT" | tr -cd '0-9')
WA_VERSION=$(printf '%s' "$WA_VERSION_RAW" | tr -cd '0-9.')
echo "πŸ”€ Enabling auto-merge for PR #$PR_NUMBER (v$WA_VERSION)..."
# Enable auto-merge with squash method
set +e
AUTO_MERGE_OUTPUT=$(gh pr merge "$PR_NUMBER" \
--repo "${{ github.repository }}" \
--squash \
--auto \
--delete-branch 2>&1)
AUTO_MERGE_EXIT=$?
set -e
if [ $AUTO_MERGE_EXIT -eq 0 ]; then
echo "βœ… Auto-merge enabled for PR #$PR_NUMBER (v$WA_VERSION)"
echo "$AUTO_MERGE_OUTPUT"
echo "⏳ PR will be merged automatically once all checks pass"
else
echo "::warning::Failed to enable auto-merge for PR #$PR_NUMBER (v$WA_VERSION)"
echo "::group::Auto-merge Error Output"
echo "$AUTO_MERGE_OUTPUT"
echo "::endgroup::"
# Fall back to waiting for checks and then merging
echo "πŸ”„ Falling back to wait-and-merge strategy..."
# Wait for checks to start
echo "⏳ Waiting 30 seconds for checks to start..."
sleep 30
# Wait for checks to complete (max 5 minutes)
echo "⏳ Waiting for checks to complete..."
WAIT_COUNT=0
MAX_WAIT=60 # 60 * 5 seconds = 5 minutes
while [ $WAIT_COUNT -lt $MAX_WAIT ]; do
set +e
CHECK_STATUS=$(gh pr checks "$PR_NUMBER" --repo "${{ github.repository }}" 2>&1)
CHECK_EXIT=$?
set -e
if [ $CHECK_EXIT -eq 0 ]; then
echo "πŸ“Š Current check status:"
echo "$CHECK_STATUS"
# Check if all checks passed
if echo "$CHECK_STATUS" | grep -q "All checks have passed"; then
echo "βœ… All checks passed!"
break
fi
# Check if any check failed
if echo "$CHECK_STATUS" | grep -qE "(fail|failure|error)"; then
echo "❌ Some checks failed, aborting merge"
exit 1
fi
fi
WAIT_COUNT=$((WAIT_COUNT + 1))
echo "⏳ Waiting... ($WAIT_COUNT/$MAX_WAIT)"
sleep 5
done
if [ $WAIT_COUNT -ge $MAX_WAIT ]; then
echo "::warning::Timeout waiting for checks to complete"
echo "::warning::PR #$PR_NUMBER requires manual merge: https://github.com/${{ github.repository }}/pull/$PR_NUMBER"
exit 0
fi
# Try to merge now that checks passed
echo "πŸ”€ Attempting to merge PR #$PR_NUMBER..."
set +e
MERGE_OUTPUT=$(gh pr merge "$PR_NUMBER" \
--repo "${{ github.repository }}" \
--squash \
--delete-branch \
--yes 2>&1)
MERGE_EXIT=$?
set -e
if [ $MERGE_EXIT -eq 0 ]; then
echo "βœ… PR #$PR_NUMBER (v$WA_VERSION) merged successfully"
echo "$MERGE_OUTPUT"
else
echo "::error::Failed to merge PR #$PR_NUMBER (v$WA_VERSION)"
echo "::group::Merge Error Output"
echo "$MERGE_OUTPUT"
echo "::endgroup::"
# Try with admin flag
echo "πŸ”§ Attempting merge with admin override..."
set +e
ADMIN_OUTPUT=$(gh pr merge "$PR_NUMBER" \
--repo "${{ github.repository }}" \
--squash \
--delete-branch \
--admin 2>&1)
ADMIN_EXIT=$?
set -e
if [ $ADMIN_EXIT -eq 0 ]; then
echo "βœ… PR #$PR_NUMBER (v$WA_VERSION) merged with admin override"
echo "$ADMIN_OUTPUT"
else
echo "::error::Failed to merge even with admin override"
echo "::group::Admin Merge Error Output"
echo "$ADMIN_OUTPUT"
echo "::endgroup::"
echo "::warning::Consider configuring a Personal Access Token (PAT) with full repo permissions as GH_PAT secret"
echo "::warning::PR #$PR_NUMBER requires manual merge: https://github.com/${{ github.repository }}/pull/$PR_NUMBER"
exit 0
fi
fi
fi
- name: Summary
if: always()
# audit CI-P1-B β€” `wa_js_url` had NEVER been sanitised anywhere. It
# came verbatim from a regex over `web.whatsapp.com`'s response. We
# accept only valid HTTPS URL characters here; everything else is
# stripped before the value reaches Markdown / shell.
env:
WA_VERSION_RAW: ${{ steps.wa_proto_info.outputs.wa_version }}
WA_JS_URL_RAW: ${{ steps.wa_proto_info.outputs.wa_js_url }}
PR_NUMBER_RAW: ${{ steps.create_pr.outputs.pull-request-number }}
run: |
echo "### πŸ“¦ WAProto Update" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
WA_VERSION=$(printf '%s' "$WA_VERSION_RAW" | tr -cd '0-9.')
# The `-` MUST be the last char in the class, otherwise `_-+`
# is parsed as the (invalid) range from `_` (0x5F) to `+` (0x2B)
# and GNU `tr` aborts with "reverse collating sequence order",
# breaking every Summary step run.
WA_JS_URL=$(printf '%s' "$WA_JS_URL_RAW" | tr -cd 'A-Za-z0-9:/?&=._+~%#-')
PR_NUMBER=$(printf '%s' "$PR_NUMBER_RAW" | tr -cd '0-9')
echo "**Version:** \`v$WA_VERSION\`" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
if [ -n "$PR_NUMBER" ]; then
echo "βœ… **PR #$PR_NUMBER created with auto-merge enabled**" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Changes:**" >> $GITHUB_STEP_SUMMARY
echo "- πŸ“¦ Updated WAProto/* (protobuf definitions)" >> $GITHUB_STEP_SUMMARY
echo "- πŸ“ Updated baileys-version.json" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Source:** [$WA_JS_URL]($WA_JS_URL)" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "πŸ”€ PR will merge automatically once checks pass" >> $GITHUB_STEP_SUMMARY
else
echo "ℹ️ No changes detected - already up to date" >> $GITHUB_STEP_SUMMARY
fi