fix(regenerate): tolerate orphaned ACC baseline SHA in module detection #3
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Validate learner branches | |
| # Validation gate for the ACC start-of-module-N delta store. Runs on any PR that | |
| # touches the delta store / course-build tooling, and is reusable (workflow_call) | |
| # so the dispatch receiver can gate a regen PR on the same checks. | |
| on: | |
| pull_request: | |
| paths: | |
| - 'course-build/**' | |
| - '.github/workflows/validate-branches.yml' | |
| workflow_dispatch: | |
| inputs: | |
| dispatch_id: | |
| description: 'Staging namespace to validate (regen/<id>/...)' | |
| required: false | |
| default: 'ci-manual' | |
| ref: | |
| description: 'Git ref (branch/SHA) to validate' | |
| required: false | |
| default: '' | |
| workflow_call: | |
| inputs: | |
| dispatch_id: | |
| description: 'Staging namespace to validate' | |
| required: false | |
| type: string | |
| default: 'ci-call' | |
| ref: | |
| description: 'Git ref (branch/SHA) to validate. Defaults to the caller ref.' | |
| required: false | |
| type: string | |
| default: '' | |
| permissions: | |
| contents: read | |
| concurrency: | |
| group: validate-branches-${{ github.ref }}-${{ inputs.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| # Fast, deterministic checks: deltas apply cleanly onto acc-base, each cumulative | |
| # tree matches manifest.expectedTreeSha, expected .github assets present, ancestry | |
| # linear. Also emits the buildable start-branch matrix for the heavy job. | |
| verify-deltas: | |
| runs-on: ubuntu-latest | |
| outputs: | |
| branches: ${{ steps.matrix.outputs.branches }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 # need full history + base commit for git am | |
| ref: ${{ inputs.ref || github.ref }} | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: '22' | |
| - name: Ensure base commit present | |
| run: git fetch --no-tags origin "$(node -e "console.log(require('./course-build/manifest.json').base.sha)")" || true | |
| - name: Deterministic delta check (trees, assets, ancestry) | |
| run: node course-build/scripts/build-branches.mjs --check | |
| - name: Self-test (classification + path detection) | |
| run: node course-build/scripts/selftest.mjs | |
| - name: Compute buildable start-branch matrix | |
| id: matrix | |
| run: | | |
| branches=$(node -e "const m=require('./course-build/manifest.json');const b=m.modules.filter(x=>x.status==='backfilled'&&(x.patches||[]).length).map(x=>x.startBranch);process.stdout.write(JSON.stringify(b))") | |
| echo "branches=$branches" >> "$GITHUB_OUTPUT" | |
| echo "Buildable: $branches" | |
| # Secret scan of the delta store and everything the built branches would contain. | |
| secret-scan: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| ref: ${{ inputs.ref || github.ref }} | |
| - name: gitleaks (delta store + course-build) | |
| uses: gitleaks/gitleaks-action@v2 | |
| env: | |
| GITLEAKS_ENABLE_UPLOAD_ARTIFACT: 'false' | |
| GITLEAKS_ENABLE_SUMMARY: 'true' | |
| # Heavy gate: build each buildable learner branch from deltas and run the suites | |
| # that exist in that cumulative state (web / .NET / Java / Python / Playwright), | |
| # plus the no-uncommitted-files-after-setup assertion. | |
| build-and-test: | |
| needs: verify-deltas | |
| if: needs.verify-deltas.outputs.branches != '[]' | |
| runs-on: ubuntu-latest | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| start_branch: ${{ fromJSON(needs.verify-deltas.outputs.branches) }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| ref: ${{ inputs.ref || github.ref }} | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: '22' | |
| - uses: actions/setup-dotnet@v4 | |
| with: | |
| dotnet-version: '10.0' | |
| - uses: actions/setup-python@v5 | |
| with: | |
| python-version: '3.12' | |
| - uses: actions/setup-java@v4 | |
| with: | |
| distribution: 'temurin' | |
| java-version: '21' | |
| - name: Ensure base commit present | |
| run: git fetch --no-tags origin "$(node -e "console.log(require('./course-build/manifest.json').base.sha)")" || true | |
| - name: Configure git identity (for git am) | |
| run: | | |
| git config user.name "acc-course-bot" | |
| git config user.email "acc-course-bot@users.noreply.github.com" | |
| - name: Build + validate ${{ matrix.start_branch }} | |
| run: bash course-build/scripts/validate-branch.sh "${{ matrix.start_branch }}" | |
| env: | |
| DISPATCH_ID: ci-${{ github.run_id }} | |
| # Aggregate result used as the required status check / workflow_call output. | |
| summary: | |
| needs: [verify-deltas, secret-scan, build-and-test] | |
| if: always() | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Fail if any gate failed | |
| run: | | |
| echo "verify-deltas: ${{ needs.verify-deltas.result }}" | |
| echo "secret-scan: ${{ needs.secret-scan.result }}" | |
| echo "build-and-test:${{ needs.build-and-test.result }}" | |
| test "${{ needs.verify-deltas.result }}" = "success" | |
| test "${{ needs.secret-scan.result }}" = "success" | |
| test "${{ needs.build-and-test.result }}" = "success" |