# ROBOTS ON PAYROLL / THE VAULT
# What this is: a GitHub Actions workflow that posts a weekly npm audit and npm outdated report to one recurring issue.
# How to use it: download this file and give it to your AI (Claude, ChatGPT,
# Cursor, Lovable chat) as a reference. Say: "Use this as my playbook for
# setting up my dependency patrol."
# Latest version + full guide: https://robotsonpayroll.com/resources/github-actions-runbooks
#
# dependency-patrol.yml
# Weekly dependency report: npm audit + npm outdated, posted as a single
# GitHub issue every Monday. One recurring issue, updated in place, so your
# tracker doesn't fill up with 52 stale reports a year.
#
# Optional add-on at the bottom: auto-PR for patch/minor updates.
#
# SECRETS REQUIRED: none. Uses the built-in GITHUB_TOKEN with
# least-privilege permissions declared per job.

name: Dependency patrol

on:
  schedule:
    - cron: "23 6 * * 1" # Mondays 06:23 UTC (odd minute dodges cron rush)
  workflow_dispatch: {}

jobs:
  report:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      issues: write # only what this job needs: read code, write one issue

    steps:
      - uses: actions/checkout@v7

      - uses: actions/setup-node@v6
        with:
          node-version: 22
          cache: npm

      - run: npm ci

      # Both commands exit non-zero when they find anything, which would
      # fail the job before we can post. `|| true` captures output either way.
      - name: Collect audit and outdated reports
        run: |
          {
            echo "## npm audit (prod deps)"
            echo '```'
            npm audit --omit=dev 2>&1 || true
            echo '```'
            echo ""
            echo "## npm outdated"
            echo '```'
            npm outdated 2>&1 || true
            echo '```'
            echo ""
            echo "_Generated $(date -u +%Y-%m-%d) by dependency-patrol. Triage rule: fix criticals this week, highs this month, park the rest._"
          } > report.md

      # github-script gives you an authenticated Octokit client inline.
      # Find the existing report issue by label; update it, or create it.
      - name: Post or update the report issue
        uses: actions/github-script@v8
        with:
          script: |
            const fs = require('fs');
            const body = fs.readFileSync('report.md', 'utf8');
            const title = 'Weekly dependency report';
            const label = 'dependency-patrol';

            // Ensure the label exists (ignore "already exists" errors)
            await github.rest.issues.createLabel({
              ...context.repo, name: label, color: '1d76db',
            }).catch(() => {});

            const { data: issues } = await github.rest.issues.listForRepo({
              ...context.repo, labels: label, state: 'open', per_page: 1,
            });

            if (issues.length > 0) {
              await github.rest.issues.update({
                ...context.repo, issue_number: issues[0].number, title, body,
              });
              core.info(`Updated issue #${issues[0].number}`);
            } else {
              const { data: issue } = await github.rest.issues.create({
                ...context.repo, title, body, labels: [label],
              });
              core.info(`Created issue #${issue.number}`);
            }

  # ---- OPTIONAL: auto-PR patch + minor updates ----
  # Semver honesty check: "minor" updates break things too, just less often.
  # This PR runs your tests via your normal PR checks; merge only when green.
  # Delete this whole job if you'd rather update by hand.
  auto-update:
    runs-on: ubuntu-latest
    needs: report
    permissions:
      contents: write # push the update branch
      pull-requests: write # open the PR
    steps:
      - uses: actions/checkout@v7

      - uses: actions/setup-node@v6
        with:
          node-version: 22
          cache: npm

      - run: npm ci

      # `npm update` respects the semver ranges in package.json (the default
      # caret ^ range = minor + patch only). It will not jump majors.
      - name: Apply minor and patch updates
        run: npm update

      # Only opens a PR if npm update actually changed the lockfile.
      # NOTE: peter-evans/create-pull-request is a third-party action.
      # For supply-chain safety, pin it to a full commit SHA:
      #   uses: peter-evans/create-pull-request@<full-sha> # v7
      # (grab the SHA from the action's releases page).
      - name: Open PR if anything changed
        uses: peter-evans/create-pull-request@v7
        with:
          branch: deps/weekly-minor-updates
          title: "chore(deps): weekly minor and patch updates"
          commit-message: "chore(deps): weekly minor and patch updates"
          body: |
            Automated `npm update` from dependency-patrol.
            Minor + patch bumps only (respects package.json semver ranges).
            Merge when checks are green; close if anything looks off.
          labels: dependencies
          delete-branch: true

# NOTE: PRs opened with the default GITHUB_TOKEN do NOT trigger your other
# workflows (GitHub prevents recursion). If your CI doesn't run on this PR,
# close and reopen it by hand to kick the checks, or use a fine-grained PAT
# stored as a secret and passed via the `token:` input.
