662bb41cc2
Fixes GitHub Actions failing with "Permission denied (publickey)" when installing libsignal package from GitHub. ## Problem Workflow was failing (runs #22, #23) when Yarn tried to install: `libsignal: "git+https://github.com/whiskeysockets/libsignal-node"` Error: Yarn was converting HTTPS URL to SSH (git@github.com), but runner has no SSH key configured. ## Root Causes 1. Git config order issue: Line 48 was overwriting line 46's SSH -> HTTPS rule 2. Stale cache: node_modules cache contained SSH references 3. No Yarn-specific config to prevent SSH fallback ## Solution ### 1. Improved Git Configuration - Added comments explaining order importance - Separated SSH conversion from authentication - Added Yarn-specific config to prefer HTTPS ### 2. Cache Key Update - Changed cache key from `yarn-` to `yarn-https-v2-` - This busts old cache with SSH references - Added `.yarn/cache` to cached paths ### 3. Fallback Retry Logic - If immutable install fails (due to SSH refs), retry without immutable mode - Clear node_modules before retry - Logs helpful error messages ## Testing Before: Runs #22, #23 failed at "Install packages" (16s, 21s) After: Should succeed with proper HTTPS cloning ## Related - Issue: libsignal package using git+https:// URL - Affects: Daily WhatsApp version update workflow - Impact: Workflow was broken for 2 days https://claude.ai/code/session_01SoNUGBEWbJwWWws3F2fuzh
228 lines
8.6 KiB
YAML
228 lines
8.6 KiB
YAML
name: Update WhatsApp Version
|
||
|
||
on:
|
||
schedule:
|
||
# Run daily at 06:00 UTC (when WhatsApp typically deploys updates)
|
||
- cron: '0 6 * * *'
|
||
workflow_dispatch:
|
||
inputs:
|
||
force:
|
||
description: 'Force create PR even if version unchanged (useful for re-triggering)'
|
||
required: false
|
||
default: 'false'
|
||
type: boolean
|
||
|
||
permissions:
|
||
contents: write
|
||
pull-requests: write
|
||
# Note: Auto-merge may require additional permissions depending on repository settings.
|
||
# If auto-merge fails, consider using a Personal Access Token (PAT) or GitHub App token
|
||
# with 'pull-requests: write' and 'contents: write' scopes.
|
||
|
||
jobs:
|
||
update-version:
|
||
runs-on: ubuntu-latest
|
||
timeout-minutes: 10
|
||
|
||
steps:
|
||
- uses: actions/checkout@v4
|
||
|
||
- name: Setup Node and Corepack
|
||
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
|
||
# IMPORTANT: Order matters! More specific rules first, then general ones
|
||
git config --global url."https://github.com/".insteadOf "ssh://git@github.com/"
|
||
git config --global url."https://github.com/".insteadOf "git@github.com:"
|
||
|
||
# Configure authentication (last so it doesn't interfere with SSH -> HTTPS conversion)
|
||
git config --global url."https://x-access-token:${GITHUB_TOKEN}@github.com/".insteadOf "https://github.com/"
|
||
|
||
# Also configure for Yarn/NPM to prevent SSH fallback
|
||
echo "Configuring Yarn to prefer HTTPS..."
|
||
yarn config set --home enableImmutableInstalls false
|
||
yarn config set --home preferAggregateCacheInfo true
|
||
|
||
- name: Restore Yarn Cache
|
||
uses: actions/cache@v4
|
||
id: yarn-cache
|
||
with:
|
||
path: |
|
||
node_modules
|
||
.yarn/cache
|
||
.yarn/install-state.gz
|
||
# Include git config in cache key to bust cache when git rules change
|
||
key: ${{ runner.os }}-yarn-https-v2-${{ hashFiles('**/yarn.lock') }}
|
||
restore-keys: |
|
||
${{ runner.os }}-yarn-https-v2-
|
||
|
||
- name: Install packages
|
||
run: |
|
||
# Try install with immutable mode first
|
||
if ! yarn install --immutable; then
|
||
echo "⚠️ Immutable install failed. This might be due to SSH references in cache."
|
||
echo "Clearing node_modules and retrying without immutable mode..."
|
||
rm -rf node_modules
|
||
yarn install
|
||
fi
|
||
|
||
- name: Update WhatsApp Web Version
|
||
id: update_version
|
||
run: |
|
||
# Run the update script, capture exit code
|
||
# Exit codes: 0=success, 1=error, 2=fetch failed (fallback used)
|
||
set +e
|
||
yarn update:version
|
||
EXIT_CODE=$?
|
||
set -e
|
||
|
||
echo "exit_code=$EXIT_CODE" >> $GITHUB_OUTPUT
|
||
|
||
# Only fail on fatal errors (exit code 1)
|
||
if [ $EXIT_CODE -eq 1 ]; then
|
||
echo "::error::Script failed with fatal error"
|
||
exit 1
|
||
fi
|
||
|
||
# Exit code 2 means fetch failed but fallback was used - this is a warning
|
||
if [ $EXIT_CODE -eq 2 ]; then
|
||
echo "::warning::Could not fetch latest version from WhatsApp servers"
|
||
fi
|
||
|
||
- name: Check for changes
|
||
id: check_changes
|
||
run: |
|
||
FORCE="${{ inputs.force }}"
|
||
|
||
if git diff --quiet; then
|
||
echo "has_changes=false" >> $GITHUB_OUTPUT
|
||
if [ "$FORCE" == "true" ]; then
|
||
echo "force_mode=true" >> $GITHUB_OUTPUT
|
||
echo "::notice::Force mode enabled - will create PR even without changes"
|
||
else
|
||
echo "force_mode=false" >> $GITHUB_OUTPUT
|
||
fi
|
||
else
|
||
echo "has_changes=true" >> $GITHUB_OUTPUT
|
||
echo "force_mode=false" >> $GITHUB_OUTPUT
|
||
fi
|
||
|
||
- name: Create Pull Request
|
||
if: steps.check_changes.outputs.has_changes == 'true' || steps.check_changes.outputs.force_mode == 'true'
|
||
env:
|
||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||
run: |
|
||
BRANCH_NAME="update-version/stable"
|
||
FORCE="${{ inputs.force }}"
|
||
|
||
# Configure git
|
||
git config user.name "github-actions[bot]"
|
||
git config user.email "github-actions[bot]@users.noreply.github.com"
|
||
|
||
# Check if branch exists and delete it
|
||
git push origin --delete "$BRANCH_NAME" 2>/dev/null || true
|
||
|
||
# Create new branch
|
||
git checkout -b "$BRANCH_NAME"
|
||
|
||
# Only add the single source of truth file
|
||
git add src/Defaults/baileys-version.json
|
||
|
||
# Create commit (allow empty if force mode)
|
||
if [ "$FORCE" == "true" ] && git diff --cached --quiet; then
|
||
git commit --allow-empty -m "chore: force WhatsApp Web version check"
|
||
else
|
||
git commit -m "chore: update WhatsApp Web version"
|
||
fi
|
||
|
||
git push origin "$BRANCH_NAME"
|
||
|
||
# Create PR using GitHub CLI
|
||
PR_BODY="Automated WhatsApp Web version update.
|
||
|
||
This PR updates the WhatsApp Web client revision to the latest version fetched from \`web.whatsapp.com\`.
|
||
|
||
**Single source of truth:**
|
||
- \`src/Defaults/baileys-version.json\` (other files import from here)
|
||
|
||
**Update frequency:** Daily at 06:00 UTC"
|
||
|
||
if [ "$FORCE" == "true" ]; then
|
||
PR_BODY="$PR_BODY
|
||
|
||
> **Note:** This PR was created with force mode enabled."
|
||
fi
|
||
|
||
# Create PR with JSON output for reliable success detection
|
||
PR_RESULT=$(gh pr create \
|
||
--title "chore: update WhatsApp Web version" \
|
||
--body "$PR_BODY" \
|
||
--base master \
|
||
--head "$BRANCH_NAME" \
|
||
--json url,number 2>&1) || PR_CREATE_FAILED=true
|
||
|
||
# Check if PR was created successfully by parsing JSON
|
||
if [ -z "$PR_CREATE_FAILED" ] && echo "$PR_RESULT" | jq -e '.url' > /dev/null 2>&1; then
|
||
PR_URL=$(echo "$PR_RESULT" | jq -r '.url')
|
||
PR_NUMBER=$(echo "$PR_RESULT" | jq -r '.number')
|
||
echo "PR created successfully: $PR_URL (PR #$PR_NUMBER)"
|
||
|
||
# Auto-merge the PR (squash merge)
|
||
# Note: This requires branch protection rules to be satisfied
|
||
# If checks haven't completed yet, auto-merge will queue the merge
|
||
echo "Attempting to enable auto-merge..."
|
||
if gh pr merge "$BRANCH_NAME" --squash --auto --delete-branch; then
|
||
echo "✅ Auto-merge enabled - PR will merge automatically when checks pass"
|
||
else
|
||
echo "⚠️ Auto-merge not available - PR #$PR_NUMBER created for manual review"
|
||
echo "This may happen if:"
|
||
echo " - Required status checks haven't completed yet"
|
||
echo " - Branch protection rules require manual approval"
|
||
echo " - Insufficient permissions (see workflow permissions comment)"
|
||
fi
|
||
else
|
||
# PR creation failed - could be duplicate or other error
|
||
echo "⚠️ Could not create PR. Checking if PR already exists..."
|
||
EXISTING_PR=$(gh pr list --head "$BRANCH_NAME" --json number,url --jq '.[0]')
|
||
if [ -n "$EXISTING_PR" ]; then
|
||
EXISTING_URL=$(echo "$EXISTING_PR" | jq -r '.url')
|
||
EXISTING_NUMBER=$(echo "$EXISTING_PR" | jq -r '.number')
|
||
echo "PR already exists: $EXISTING_URL (PR #$EXISTING_NUMBER)"
|
||
else
|
||
echo "❌ PR creation failed: $PR_RESULT"
|
||
fi
|
||
fi
|
||
|
||
- name: Summary
|
||
run: |
|
||
echo "### WhatsApp Version Update" >> $GITHUB_STEP_SUMMARY
|
||
echo "" >> $GITHUB_STEP_SUMMARY
|
||
|
||
EXIT_CODE="${{ steps.update_version.outputs.exit_code }}"
|
||
HAS_CHANGES="${{ steps.check_changes.outputs.has_changes }}"
|
||
FORCE_MODE="${{ steps.check_changes.outputs.force_mode }}"
|
||
|
||
if [ "$EXIT_CODE" == "2" ]; then
|
||
echo "⚠️ Warning: Could not fetch latest version from WhatsApp servers" >> $GITHUB_STEP_SUMMARY
|
||
echo "" >> $GITHUB_STEP_SUMMARY
|
||
fi
|
||
|
||
if [ "$HAS_CHANGES" == "true" ]; then
|
||
echo "✅ New version detected and PR created" >> $GITHUB_STEP_SUMMARY
|
||
elif [ "$FORCE_MODE" == "true" ]; then
|
||
echo "🔄 Force mode: PR created (no version change)" >> $GITHUB_STEP_SUMMARY
|
||
else
|
||
echo "ℹ️ Already up to date" >> $GITHUB_STEP_SUMMARY
|
||
fi
|