Unidata/MetPy

View on GitHub
.github/workflows/nightly-builds.yml

Summary

Maintainability
Test Coverage
name: Nightly Checks

on:
  schedule:
  # Runs at 09Z (3am MDT)
    - cron: "0 9 * * 2"

  # Allow a manual run
  workflow_dispatch:

  # Run if we modify the workflow
  push:
    branches:
      - main
    paths:
      - .github/workflows/nightly-builds.yml
      - .github/workflows/unstable-builds.yml
  pull_request:
    paths:
      - .github/workflows/nightly-builds.yml
      - .github/workflows/unstable-builds.yml

jobs:
  Builds:
    uses: ./.github/workflows/unstable-builds.yml

  Report:
    name: Report
    needs: Builds
    if: failure() || github.event_name == 'pull_request'
    runs-on: ubuntu-latest
    permissions:
      issues: write

    steps:
      - name: Download logs
        uses: actions/download-artifact@v4
        with:
          path: /tmp/workspace/logs

      - name: Grab log files
        run: |
          cp /tmp/workspace/logs/log-*/*.log . || true
          touch tests-nightly.log build.log linkchecker.log

      - name: Report failures
        uses: actions/github-script@v7
        with:
          script: |
            const fs = require('fs');
            const title = "Nightly build is failing";
            const workflow_url = `https://github.com/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}`;
            body = `The [Nightly workflow](${workflow_url}) is failing.\n`;

            if ('${{ needs.Builds.outputs.tests_result }}' === 'failure') {
              const test_log = fs.readFileSync('tests-nightly.log', 'utf8').substring(0, 21000);
              body += `The tests failed.\nLog:\n<details><pre>${test_log}</pre></details>`;
            }
            if ('${{ needs.Builds.outputs.docs_result }}' === 'failure') {
              const build_log = fs.readFileSync('build.log', 'utf8').substring(0, 21000);
              const linkchecker = fs.readFileSync('linkchecker.log', 'utf8').substring(0, 21000);
              body += `The documentation build failed.\nLog:\n<details><pre>${build_log}</pre></details>`;
              body += `\nLinkchecker output:\n<details><pre>${linkchecker}</pre></details>`;
            }

            // See if we have an existing issue
            const items = await github.rest.issues.listForRepo({
              owner: context.repo.owner,
              repo: context.repo.repo,
              state: 'open',
              creator: 'github-actions[bot]'
            });
            const existing = items.data.filter(i => i.title === title);

            params = {
              owner: context.repo.owner,
              repo: context.repo.repo,
              body: body,
              title: title,
              labels: ['Type: Maintenance']
            };
            
            // On PRs, avoid actually issuing an API request, since we don't have permission
            if ( context.eventName === 'pull_request' ) {
              github.hook.wrap('request', (request, options) => { return {}; })
            }
            
            if (existing.length === 0) {
                console.log('Creating new issue.')
                github.rest.issues.create(params)
            } else {
                params.issue_number = existing[0].number;
                console.log(`Updating existing issue: ${params.issue_number}`)
                github.rest.issues.update(params)
            }