name: Check Stage Health
description: Fail fast if any job in the current workflow run has already failed. Auto-skips for scheduled runs.

inputs:
  github-token:
    description: 'GitHub token for API calls'
    required: false
    default: ${{ github.token }}

runs:
  using: composite
  steps:
    - name: Check stage health
      uses: actions/github-script@v7
      env:
        SKIP_STAGE_HEALTH_CHECK: ${{ env.SKIP_STAGE_HEALTH_CHECK }}
      with:
        github-token: ${{ inputs.github-token }}
        script: |
          // Skip when explicitly requested via env var (e.g. release branch cut)
          if (process.env.SKIP_STAGE_HEALTH_CHECK === 'true') {
            core.info('Skipping health check (SKIP_STAGE_HEALTH_CHECK=true)');
            return;
          }

          // Skip for scheduled runs — they should collect all failures, not fast-fail
          if (context.eventName === 'schedule') {
            core.info('Skipping health check for scheduled run');
            return;
          }

          const jobs = await github.paginate(github.rest.actions.listJobsForWorkflowRun, {
            owner: context.repo.owner,
            repo: context.repo.repo,
            run_id: context.runId,
            per_page: 100,
          });
          // Find jobs that failed from a real error, not from fast-fail cascade
          const rootCauseFailures = jobs.filter(j => {
            if (j.status !== 'completed' || j.conclusion !== 'failure') return false;
            // If the failing step is the health check, it's a cascade — skip it
            const failedStep = (j.steps || []).find(s => s.conclusion === 'failure');
            if (failedStep && (failedStep.name.includes('check-stage-health') || failedStep.name.includes('Check stage health'))) {
              return false;
            }
            return true;
          });
          if (rootCauseFailures.length > 0) {
            core.setFailed(`Fast-fail: skipping — root cause job(s): ${rootCauseFailures.map(j => j.name).join(', ')}`);
          }
