diff --git a/.github/workflows/pnpm-update.yml b/.github/workflows/pnpm-update.yml index 6186f630b..c719a582f 100644 --- a/.github/workflows/pnpm-update.yml +++ b/.github/workflows/pnpm-update.yml @@ -2,7 +2,7 @@ name: Monthly pnpm Dependency Update on: schedule: - - cron: '0 2 1 * *' + - cron: '0 2 1 * *' # Runs at 02:00 UTC on the 1st of every month workflow_dispatch: jobs: @@ -19,16 +19,17 @@ jobs: run: | pnpm --no-save update pnpm audit --audit-level moderate + if [[ -n "$(git status --porcelain)" ]]; then git config --global user.email "cloud-sdk-js@github.com" git config --global user.name "cloud-sdk-js" - git checkout -b "bot/monthly-transitive-dependency-update-$(date +%Y-%m-%d)" + BRANCH_NAME="bot/monthly-transitive-dependency-update-$(date -u +%Y%m%d-%H%M%S)" + git checkout -b "$BRANCH_NAME" git add . git commit -m "chore: update pnpm transitive dependencies" - git push --set-upstream origin "bot/monthly-transitive-dependency-update-$(date +%Y-%m-%d)" + git push --set-upstream origin "$BRANCH_NAME" else echo "No changes to commit" - exit 0 fi - name: Create Pull Request @@ -38,11 +39,19 @@ jobs: github-token: ${{ secrets.GH_CLOUD_SDK_JS_ADMIN_WRITE_TOKEN }} script: | const { repo, owner } = context.repo; + const now = new Date(); + const pad = num => num.toString().padStart(2, '0'); + const formattedDate = `${now.getUTCFullYear()}${pad( + now.getUTCMonth() + 1 + )}${pad(now.getUTCDate())}-${pad(now.getUTCHours())}${pad( + now.getUTCMinutes() + )}${pad(now.getUTCSeconds())}`; + const branch = `bot/monthly-transitive-dependency-update-${formattedDate}`; const result = await github.rest.pulls.create({ title: 'chore: Monthly Transitive Dependency Update', owner, repo, - head: `bot/monthly-transitive-dependency-update-${new Date().toISOString().split('T')[0]}`, + head: branch, base: 'main', body: 'This is an automated PR to update pnpm transitive dependencies.' }); @@ -54,41 +63,75 @@ jobs: with: github-token: ${{ secrets.GH_CLOUD_SDK_JS_ADMIN_WRITE_TOKEN }} script: | + const retry = require('async-retry'); const { repo, owner } = context.repo; + const now = new Date(); + const pad = num => num.toString().padStart(2, '0'); + const formattedDate = `${now.getUTCFullYear()}${pad( + now.getUTCMonth() + 1 + )}${pad(now.getUTCDate())}-${pad(now.getUTCHours())}${pad( + now.getUTCMinutes() + )}${pad(now.getUTCSeconds())}`; + const branch = `bot/monthly-transitive-dependency-update-${formattedDate}`; + const pulls = await github.rest.pulls.list({ owner, repo, - head: `bot/monthly-transitive-dependency-update-${new Date().toISOString().split('T')[0]}`, + head: branch, base: 'main', state: 'open' }); - + if (pulls.data.length === 0) { console.log('No matching pull request found'); return; } - + const pr = pulls.data[0]; - - // Wait for checks to complete - await new Promise(resolve => setTimeout(resolve, 300000)); // Wait 5 minutes - - const { data: checks } = await github.rest.checks.listForRef({ - owner, - repo, - ref: pr.head.sha - }); - - const allChecksPassed = checks.check_runs.every(run => run.conclusion === 'success'); - - if (allChecksPassed) { + + const result = await retry( + async () => { + const { data: checks } = await github.rest.checks.listForRef({ + owner, + repo, + ref: pr.head.sha + }); + + const allCompleted = checks.check_runs.every(run => run.status === 'completed'); + const allAcceptable = checks.check_runs.every(run => + ['success', 'skipped', 'neutral'].includes(run.conclusion) + ); + + if (!allCompleted) { + throw new Error(`PR #${pr.number} still has pending checks. Retrying...`); + } + + if (!allAcceptable) { + console.log(`PR #${pr.number} has failed checks that prevent merging.`); + } + + return 'success'; + }, + { + retries: 5, + minTimeout: 2 * 60 * 1000, + maxTimeout: 2 * 60 * 1000, + onRetry: (error, attempt) => { + const timestamp = new Date().toISOString(); + console.log(`[${timestamp}] Attempt ${attempt} failed: ${error.message}. Retrying...`); + } + } + ); + + if (result === 'success') { await github.rest.pulls.merge({ owner, repo, pull_number: pr.number, merge_method: 'squash' }); - console.log(`Pull Request #${pr.number} merged successfully`); - } else { - console.log(`Not all checks passed for PR #${pr.number}`); + console.log(`PR #${pr.number} merged successfully.`); + } + else { + console.log(`PR #${pr.number} could not be merged due to failed checks.`); }