Update WAProto #136 #136
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 |