Skip to content

Commit ef3a006

Browse files
committed
feat: complete adaptive workflow and control-plane fixes
1 parent 83e2adb commit ef3a006

118 files changed

Lines changed: 6472 additions & 663 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.github/workflows/ci.yml‎

Lines changed: 124 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,46 +4,109 @@ on:
44
push:
55
branches: [main]
66
pull_request:
7+
schedule:
8+
- cron: "17 3 * * *"
79
workflow_dispatch:
10+
inputs:
11+
validation_scope:
12+
description: Validation scope
13+
required: true
14+
default: affected
15+
type: choice
16+
options:
17+
- affected
18+
- full
819

920
permissions:
1021
contents: read
1122

1223
jobs:
13-
supported-control-plane:
14-
name: Control plane (${{ matrix.os }}, Node ${{ matrix.node }})
24+
plan:
25+
name: Plan affected validation
26+
runs-on: ubuntu-latest
27+
outputs:
28+
run-affected: ${{ steps.plan.outputs.run-affected }}
29+
run-impact-validation: ${{ steps.plan.outputs.run-impact-validation }}
30+
run-full-quality: ${{ steps.plan.outputs.run-full-quality }}
31+
run-package-boundary: ${{ steps.plan.outputs.run-package-boundary }}
32+
matrix: ${{ steps.plan.outputs.matrix }}
33+
planner-digest: ${{ steps.plan.outputs.planner-digest }}
34+
changed-files-b64: ${{ steps.plan.outputs.changed-files-b64 }}
35+
plan-b64: ${{ steps.plan.outputs.plan-b64 }}
36+
steps:
37+
- uses: actions/checkout@v6
38+
with:
39+
fetch-depth: 0
40+
- name: Build ValidationImpactGraphV2 CI plan
41+
id: plan
42+
shell: bash
43+
env:
44+
BASE_SHA: ${{ github.event_name == 'pull_request' && github.event.pull_request.base.sha || github.event.before }}
45+
MANUAL_SCOPE: ${{ inputs.validation_scope || 'affected' }}
46+
run: |
47+
set -euo pipefail
48+
node --check scripts/plan-ci-validation.js
49+
node scripts/plan-ci-validation.js \
50+
--event "${GITHUB_EVENT_NAME}" \
51+
--base "${BASE_SHA}" \
52+
--head "${GITHUB_SHA}" \
53+
--manual-scope "${MANUAL_SCOPE}" \
54+
--github-output "${GITHUB_OUTPUT}" \
55+
> "${RUNNER_TEMP}/ci-validation-plan.json"
56+
node -e 'const fs=require("fs"); const p=JSON.parse(fs.readFileSync(process.argv[1],"utf8")); process.stdout.write(`### CI validation plan\n\n- planner: \`${p.plannerDigest}\`\n- changed: ${p.totalChangedFiles}\n- affected: ${p.jobs.affected}\n- full: ${p.jobs.fullQuality}${p.fullReasonCodes.length?` (${p.fullReasonCodes.join(", ")})`:""}\n- package: ${p.jobs.packageBoundary}\n`)' "${RUNNER_TEMP}/ci-validation-plan.json" >> "${GITHUB_STEP_SUMMARY}"
57+
58+
affected:
59+
name: Affected (${{ matrix.id }}, Node ${{ matrix.node }})
60+
needs: plan
61+
if: needs.plan.outputs.run-affected == 'true'
1562
runs-on: ${{ matrix.os }}
1663
timeout-minutes: 30
1764
strategy:
1865
fail-fast: false
19-
matrix:
20-
include:
21-
- os: ubuntu-latest
22-
node: 18.17.0
23-
route: test:supported-runtime-control-plane
24-
- os: ubuntu-latest
25-
node: 22.x
26-
route: test:supported-runtime-control-plane
27-
- os: ubuntu-latest
28-
node: 26.x
29-
route: test:supported-runtime-control-plane
30-
- os: windows-latest
31-
node: 18.17.0
32-
route: test:windows-control-plane
33-
- os: windows-latest
34-
node: 24.17.0
35-
route: test:windows-control-plane
66+
matrix: ${{ fromJSON(needs.plan.outputs.matrix) }}
3667
steps:
3768
- uses: actions/checkout@v6
3869
- uses: actions/setup-node@v6
3970
with:
4071
node-version: ${{ matrix.node }}
4172
cache: npm
4273
- run: npm ci
43-
- run: npm run ${{ matrix.route }}
74+
- name: Run exact affected validation plan
75+
if: matrix.kind == 'impact'
76+
shell: bash
77+
env:
78+
CHANGED_FILES_B64: ${{ needs.plan.outputs.changed-files-b64 }}
79+
CI_PLAN_B64: ${{ needs.plan.outputs.plan-b64 }}
80+
run: |
81+
set -euo pipefail
82+
mapfile -d '' CHANGED_FILES < <(node -e 'for(const f of JSON.parse(Buffer.from(process.env.CHANGED_FILES_B64,"base64").toString("utf8"))) process.stdout.write(f+"\0")')
83+
CHANGED_ARGS=()
84+
for file in "${CHANGED_FILES[@]}"; do CHANGED_ARGS+=(--changed "${file}"); done
85+
AUTHORITY_SOURCE="github-actions:${GITHUB_WORKFLOW}:${GITHUB_EVENT_NAME}:${GITHUB_REPOSITORY}:${GITHUB_REF}:${GITHUB_SHA}"
86+
VALIDATION_LEVEL="$(node -e 'const p=JSON.parse(Buffer.from(process.env.CI_PLAN_B64,"base64").toString("utf8")); process.stdout.write(p.effective.verificationLevel)')"
87+
export VALIDATION_LEVEL
88+
POLICY_DIGEST="$(node -e 'const {sha256}=require("./hooks/_runtime/content-identity.cjs"); process.stdout.write(sha256(JSON.stringify({workflow:process.env.GITHUB_WORKFLOW,event:process.env.GITHUB_EVENT_NAME,repository:process.env.GITHUB_REPOSITORY,ref:process.env.GITHUB_REF,commit:process.env.GITHUB_SHA,level:process.env.VALIDATION_LEVEL})))' )"
89+
BUDGET_DIGEST="$(
90+
node scripts/run-validation.js --route changed "${CHANGED_ARGS[@]}" --actor trusted-ci --authority-source "${AUTHORITY_SOURCE}" --policy-digest "${POLICY_DIGEST}" --plan --json |
91+
node -e 'const fs=require("fs"); const value=JSON.parse(fs.readFileSync(0,"utf8")); const digest=value?.data?.plan?.budgetCard?.digest; if(value?.ok!==true||!/^[a-f0-9]{64}$/.test(String(digest||""))) process.exit(1); process.stdout.write(digest)'
92+
)"
93+
node scripts/run-validation.js --route changed "${CHANGED_ARGS[@]}" --actor trusted-ci --authority-source "${AUTHORITY_SOURCE}" --policy-digest "${POLICY_DIGEST}" --approve-plan "${BUDGET_DIGEST}" --json > "${RUNNER_TEMP}/ci-validation-result-${{ matrix.id }}.json"
94+
- name: Run scheduled compatibility route
95+
if: matrix.kind == 'compatibility'
96+
run: npm run ${{ matrix.command }}
97+
- name: Preserve affected validation receipt
98+
if: always() && matrix.kind == 'impact'
99+
uses: actions/upload-artifact@v4
100+
with:
101+
name: ci-validation-result-${{ matrix.id }}-${{ github.run_id }}-${{ github.run_attempt }}
102+
path: ${{ runner.temp }}/ci-validation-result-${{ matrix.id }}.json
103+
if-no-files-found: error
104+
retention-days: 14
44105

45106
full-quality:
46107
name: Full quality (Node 24.17)
108+
needs: plan
109+
if: needs.plan.outputs.run-full-quality == 'true'
47110
runs-on: ubuntu-latest
48111
steps:
49112
- uses: actions/checkout@v6
@@ -64,12 +127,22 @@ jobs:
64127
node scripts/run-validation.js --route full --actor trusted-ci --authority-source "${AUTHORITY_SOURCE}" --policy-digest "${POLICY_DIGEST}" --plan --json |
65128
node -e 'const fs=require("fs"); const value=JSON.parse(fs.readFileSync(0,"utf8")); const digest=value?.data?.plan?.budgetCard?.digest; if(value?.ok!==true || !/^[a-f0-9]{64}$/.test(String(digest||""))) process.exit(1); process.stdout.write(digest)'
66129
)"
67-
node scripts/run-validation.js --route full --actor trusted-ci --authority-source "${AUTHORITY_SOURCE}" --policy-digest "${POLICY_DIGEST}" --approve-plan "${BUDGET_DIGEST}"
130+
node scripts/run-validation.js --route full --actor trusted-ci --authority-source "${AUTHORITY_SOURCE}" --policy-digest "${POLICY_DIGEST}" --approve-plan "${BUDGET_DIGEST}" --json > "${RUNNER_TEMP}/ci-validation-result-full.json"
68131
- run: npm run test:coverage
69132
- run: npm run test:audit
133+
- name: Preserve full validation receipt
134+
if: always()
135+
uses: actions/upload-artifact@v4
136+
with:
137+
name: ci-validation-result-full-${{ github.run_id }}-${{ github.run_attempt }}
138+
path: ${{ runner.temp }}/ci-validation-result-full.json
139+
if-no-files-found: error
140+
retention-days: 14
70141

71-
website-package:
142+
package-boundary:
72143
name: Package boundary (Node 24.17)
144+
needs: plan
145+
if: needs.plan.outputs.run-package-boundary == 'true'
73146
runs-on: ubuntu-latest
74147
steps:
75148
- uses: actions/checkout@v6
@@ -80,3 +153,32 @@ jobs:
80153
- run: npm ci
81154
- run: npm run release:dry-run:all
82155
- run: npm run test:pack-clean
156+
157+
aggregate:
158+
name: Required validation aggregate
159+
if: always()
160+
needs: [plan, affected, full-quality, package-boundary]
161+
runs-on: ubuntu-latest
162+
steps:
163+
- uses: actions/checkout@v6
164+
- name: Download validation receipts
165+
if: needs.plan.result == 'success' && (needs.plan.outputs.run-impact-validation == 'true' || needs.plan.outputs.run-full-quality == 'true')
166+
uses: actions/download-artifact@v5
167+
with:
168+
pattern: ci-validation-result-*-${{ github.run_id }}-${{ github.run_attempt }}
169+
path: ${{ runner.temp }}/ci-validation-results
170+
merge-multiple: true
171+
- name: Verify required jobs and node receipts
172+
env:
173+
DEVCODEX_CI_PLAN_B64: ${{ needs.plan.outputs.plan-b64 }}
174+
DEVCODEX_CI_JOB_RESULTS: >-
175+
{"plan":"${{ needs.plan.result }}","affected":"${{ needs.affected.result }}","fullQuality":"${{ needs['full-quality'].result }}","packageBoundary":"${{ needs['package-boundary'].result }}"}
176+
run: node scripts/plan-ci-validation.js aggregate --results-dir "${RUNNER_TEMP}/ci-validation-results" > "${RUNNER_TEMP}/ci-validation-aggregate.json"
177+
- name: Preserve aggregate receipt
178+
if: always()
179+
uses: actions/upload-artifact@v4
180+
with:
181+
name: ci-validation-aggregate-${{ github.run_id }}-${{ github.run_attempt }}
182+
path: ${{ runner.temp }}/ci-validation-aggregate.json
183+
if-no-files-found: warn
184+
retention-days: 14

0 commit comments

Comments
 (0)