name: Check for outdated GitHub Actions on: schedule: - cron: '37 20 * * 3' workflow_dispatch: jobs: check-actions: name: Check for GHA updates runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: '20' - name: Install actions-up run: npm install -g actions-up - name: Run actions-up check id: actions-check run: | echo "## GitHub Actions Update Check" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY # Initialize variables HAS_UPDATES=false UPDATE_COUNT=0 # Run actions-up and capture output echo "Running actions-up to check for updates..." actions-up --dry-run > actions-up-raw.txt 2>&1 || true # Parse the output to detect updates if grep -q "→" actions-up-raw.txt; then HAS_UPDATES=true # Count the number of updates (lines with arrows) UPDATE_COUNT=$(grep -c "→" actions-up-raw.txt || echo "0") fi # Create formatted output if [ "$HAS_UPDATES" = true ]; then echo "Found $UPDATE_COUNT GitHub Actions with available updates" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "
" >> $GITHUB_STEP_SUMMARY echo "Click to see details" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo '```' >> $GITHUB_STEP_SUMMARY cat actions-up-raw.txt >> $GITHUB_STEP_SUMMARY echo '```' >> $GITHUB_STEP_SUMMARY echo "
" >> $GITHUB_STEP_SUMMARY # Create detailed markdown report with better formatting { echo "## GitHub Actions Update Report" echo "" echo "### Summary" echo "- **Updates available:** $UPDATE_COUNT" echo "" # See the raw output above for details. echo "### How to Update" echo "" echo "You have several options to update these actions:" echo "" echo "#### Option 1: Automatic Update (Recommended)" echo '```bash' echo "# Run this command locally in your repository" echo "npx actions-up" echo '```' echo "" echo "#### Option 2: Manual Update" echo "1. Review each update in the table above" echo "2. For breaking changes, click the Release Notes link to review changes" echo "3. Edit the workflow files and update the version numbers" echo "4. Test the changes in your CI/CD pipeline" echo "" echo "---" echo "" echo "
" echo "Raw actions-up output" echo "" echo '```' cat actions-up-raw.txt echo '```' echo "
" } > actions-up-report.md echo "has-updates=true" >> $GITHUB_OUTPUT echo "update-count=$UPDATE_COUNT" >> $GITHUB_OUTPUT else echo "All GitHub Actions are up to date!" >> $GITHUB_STEP_SUMMARY { echo "## GitHub Actions Update Report" echo "" echo "### All GitHub Actions in this repository are up to date!" echo "" echo "No action required. Your workflow files are using the latest versions of all GitHub Actions." } > actions-up-report.md echo "has-updates=false" >> $GITHUB_OUTPUT echo "update-count=0" >> $GITHUB_OUTPUT fi - name: Comment PR with updates if: github.event_name == 'pull_request' uses: actions/github-script@v7 with: script: | const fs = require('fs'); const report = fs.readFileSync('actions-up-report.md', 'utf8'); const hasUpdates = '${{ steps.actions-check.outputs.has-updates }}' === 'true'; const updateCount = '${{ steps.actions-check.outputs.update-count }}'; // Check if we already commented const comments = await github.rest.issues.listComments({ owner: context.repo.owner, repo: context.repo.repo, issue_number: context.issue.number }); const botComment = comments.data.find(comment => comment.user.type === 'Bot' && comment.body.includes('GitHub Actions Update Report') ); const commentBody = `${report} --- *Generated by [actions-up](https://github.com/azat-io/actions-up) | Last check: ${new Date().toISOString()}*`; // Only comment if there are updates or if we previously commented if (hasUpdates || botComment) { if (botComment) { // Update existing comment await github.rest.issues.updateComment({ owner: context.repo.owner, repo: context.repo.repo, comment_id: botComment.id, body: commentBody }); console.log('Updated existing comment'); } else { // Create new comment only if there are updates await github.rest.issues.createComment({ owner: context.repo.owner, repo: context.repo.repo, issue_number: context.issue.number, body: commentBody }); console.log('Created new comment'); } } else { console.log('No updates found and no previous comment exists - skipping comment'); } // Add or update PR labels based on status const labels = await github.rest.issues.listLabelsOnIssue({ owner: context.repo.owner, repo: context.repo.repo, issue_number: context.issue.number }); const hasOutdatedLabel = labels.data.some(label => label.name === 'outdated-actions'); if (hasUpdates && !hasOutdatedLabel) { // Add label if updates are found try { await github.rest.issues.addLabels({ owner: context.repo.owner, repo: context.repo.repo, issue_number: context.issue.number, labels: ['outdated-actions'] }); console.log('Added outdated-actions label'); } catch (error) { console.log('Could not add label (might not exist in repo):', error.message); } } else if (!hasUpdates && hasOutdatedLabel) { // Remove label if no updates try { await github.rest.issues.removeLabel({ owner: context.repo.owner, repo: context.repo.repo, issue_number: context.issue.number, name: 'outdated-actions' }); console.log('Removed outdated-actions label'); } catch (error) { console.log('Could not remove label:', error.message); } } - name: Fail if outdated actions found if: steps.actions-check.outputs.has-updates == 'true' run: | echo "::error:: Found ${{ steps.actions-check.outputs.update-count }} outdated GitHub Actions. Please update them before merging." echo "" echo "You can update them by running: npx actions-up" echo "Or manually update the versions in your workflow files." exit 1