Niakvio provider pipeline #18
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: Check all manifests and publish Nuvio providers | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| mode: | |
| description: Validation depth | |
| required: true | |
| default: quick | |
| type: choice | |
| options: | |
| - quick | |
| - deep | |
| schedule: | |
| # Report-only compatibility audit on five days each week. | |
| - cron: "17 5 * * 0,1,3,4,6" | |
| # Strict publication audit every Tuesday and Friday. | |
| - cron: "47 4 * * 2,5" | |
| permissions: | |
| contents: read | |
| concurrency: | |
| group: nuvio-provider-publish | |
| cancel-in-progress: false | |
| jobs: | |
| stage-and-test: | |
| name: Discover and validate all upstream providers | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 90 | |
| permissions: | |
| contents: read | |
| outputs: | |
| validation_mode: ${{ steps.resolve-mode.outputs.validation_mode }} | |
| steps: | |
| - name: Checkout without persisted credentials | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| fetch-depth: 1 | |
| persist-credentials: false | |
| - name: Resolve validation mode | |
| id: resolve-mode | |
| shell: bash | |
| run: | | |
| if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then | |
| MODE="${{ github.event.inputs.mode }}" | |
| elif [ "${{ github.event.schedule }}" = "47 4 * * 2,5" ]; then | |
| MODE="deep" | |
| else | |
| MODE="quick" | |
| fi | |
| echo "validation_mode=${MODE}" >> "$GITHUB_OUTPUT" | |
| echo "Resolved validation mode: ${MODE}" | |
| - name: Set up Python | |
| uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 | |
| with: | |
| python-version: "3.12" | |
| - name: Set up Node.js | |
| uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 | |
| with: | |
| node-version: "24" | |
| package-manager-cache: false | |
| - name: Install pinned direct runtime dependencies without lifecycle scripts | |
| run: | | |
| if [ -f package-lock.json ]; then | |
| npm ci --ignore-scripts --no-audit --no-fund | |
| else | |
| echo '::warning::package-lock.json is absent; using pinned direct dependencies without lifecycle scripts.' | |
| npm install --ignore-scripts --no-audit --no-fund --package-lock=false | |
| fi | |
| - name: Reapply overrides to already published providers | |
| run: | | |
| python scripts/reapply_published_overrides.py | |
| python scripts/generate_release_hashes.py | |
| - name: Run repository regression tests | |
| run: npm test | |
| - name: Verify strict gates and SHA-pinned runtime-evidence safeguards | |
| run: python scripts/validate_policy.py | |
| - name: Verify provider settings diagnostic pipeline | |
| run: python scripts/validate_settings_pipeline.py | |
| - name: Verify provider catalogue and language semantics | |
| run: node scripts/validate_provider_semantics.cjs | |
| - name: Discover every non-P2P provider from every upstream manifest | |
| run: python scripts/discover_candidates.py --require-all-upstreams | |
| - name: Verify overrides reached the exact staged provider files | |
| run: python scripts/validate_override_pipeline.py | |
| - name: Check French ISP DNS and HTTP access before runtime scoring | |
| env: | |
| GLOBALPING_API_TOKEN: ${{ secrets.GLOBALPING_API_TOKEN }} | |
| run: | | |
| node scripts/provider_dns_preflight.mjs \ | |
| --stage staging \ | |
| --output health-output/dns-preflight-report.json | |
| - name: Persist safe DNS migration overrides and repatch staged providers | |
| run: | | |
| python scripts/apply_dns_migration_overrides.py \ | |
| --stage staging \ | |
| --report health-output/dns-preflight-report.json | |
| python scripts/validate_override_pipeline.py --stage staging | |
| - name: Execute providers, repair matching failure schemas and retest exact generated JS | |
| shell: bash | |
| env: | |
| NUVIO_DNS_PREFLIGHT_RESULTS: health-output/dns-preflight-report.json | |
| run: | | |
| if [ "${{ steps.resolve-mode.outputs.validation_mode }}" = "deep" ]; then | |
| python scripts/deep_repair_loop.py --stage staging --output health-output --mode deep | |
| python scripts/validate_override_pipeline.py --stage staging | |
| else | |
| NUVIO_HEALTH_OUTPUT=health-output node scripts/health_check.mjs | |
| printf '%s\n' '{"schema_version":1,"mode":"quick","provider_specific_rules":false,"rounds":[],"accepted_repairs":0}' > health-output/repair-report.json | |
| fi | |
| - name: Lock the final tested staging tree against modification | |
| run: | | |
| sudo chown -R root:root staging | |
| sudo chmod -R a-w staging | |
| - name: Generate stage-by-stage diagnostics | |
| run: python scripts/generate_diagnostics.py --results health-output/health-results.json --output health-output | |
| - name: Detect obsolete route patterns | |
| run: python scripts/validate_route_overrides.py --results health-output/health-results.json --report health-output/route-regressions.json | |
| - name: Lock generated validation result | |
| run: | | |
| sudo chown -R root:root health-output | |
| sudo chmod -R a-w health-output | |
| - name: Upload checked staging area | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: nuvio-validation-stage-${{ github.run_id }} | |
| path: | | |
| staging/ | |
| health-output/health-results.json | |
| health-output/dns-preflight-report.json | |
| health-output/diagnostics-report.json | |
| health-output/diagnostics-report.html | |
| health-output/route-regressions.json | |
| health-output/repair-report.json | |
| provider-overrides.json | |
| retention-days: 2 | |
| if-no-files-found: error | |
| - name: Explain report-only quick mode | |
| if: steps.resolve-mode.outputs.validation_mode == 'quick' | |
| run: | | |
| echo "Quick validation completed as report-only." | |
| echo "Only a deep validation may update provider files or manifest.json." | |
| publish: | |
| name: Apply strict validation and Nuvio runtime evidence | |
| needs: stage-and-test | |
| if: needs.stage-and-test.outputs.validation_mode == 'deep' | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 25 | |
| permissions: | |
| contents: write | |
| steps: | |
| - name: Checkout current published repository | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| fetch-depth: 0 | |
| - name: Set up Python | |
| uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 | |
| with: | |
| python-version: "3.12" | |
| - name: Set up Node.js for final provider validation | |
| uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 | |
| with: | |
| node-version: "24" | |
| package-manager-cache: false | |
| - name: Install pinned provider validation dependencies | |
| run: | | |
| if [ -f package-lock.json ]; then | |
| npm ci --ignore-scripts --no-audit --no-fund | |
| else | |
| npm install --ignore-scripts --no-audit --no-fund --package-lock=false | |
| fi | |
| - name: Download checked staging area | |
| uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 | |
| with: | |
| name: nuvio-validation-stage-${{ github.run_id }} | |
| path: checked-artifact | |
| - name: Restore validated DNS migration overrides | |
| run: | | |
| test -f checked-artifact/provider-overrides.json | |
| cp checked-artifact/provider-overrides.json provider-overrides.json | |
| python scripts/reapply_published_overrides.py | |
| # Final provider artifacts are revalidated before promotion in this write-enabled job. | |
| - name: Apply strict gates, finite grace and exact runtime evidence | |
| env: | |
| NUVIO_STAGE: checked-artifact/staging | |
| NUVIO_HEALTH_RESULTS: checked-artifact/health-output/health-results.json | |
| run: python scripts/promote_candidates.py | |
| - name: Verify overrides reached final published provider files | |
| run: python scripts/validate_published_overrides.py | |
| - name: Publish provider files and reports before the manifest | |
| shell: bash | |
| run: | | |
| git config user.name "github-actions[bot]" | |
| git config user.email "41898282+github-actions[bot]@users.noreply.github.com" | |
| cp checked-artifact/health-output/dns-preflight-report.json dns-preflight-report.json | |
| cp checked-artifact/health-output/diagnostics-report.json diagnostics-report.json | |
| cp checked-artifact/health-output/diagnostics-report.html diagnostics-report.html | |
| cp checked-artifact/health-output/route-regressions.json route-regressions.json | |
| if [ -f checked-artifact/health-output/repair-report.json ]; then | |
| cp checked-artifact/health-output/repair-report.json repair-report.json | |
| fi | |
| git add health-report.json health-history.json PROVENANCE.json dns-preflight-report.json diagnostics-report.json diagnostics-report.html route-regressions.json provider-overrides.json | |
| if [ -f repair-report.json ]; then | |
| git add repair-report.json | |
| fi | |
| if [ -d providers ]; then | |
| git add providers | |
| fi | |
| if ! git diff --cached --quiet; then | |
| git commit -m "chore: stage validated provider versions" | |
| git push origin HEAD:main | |
| else | |
| echo "No provider file or validation report change." | |
| fi | |
| - name: Publish the validated manifest in a second phase | |
| shell: bash | |
| run: | | |
| test -f manifest.next.json | |
| mv manifest.next.json manifest.json | |
| python scripts/generate_language_manifests.py | |
| python scripts/sync_release_versions.py --manifest manifest.json | |
| python scripts/generate_release_hashes.py | |
| python scripts/validate_release_integrity.py | |
| git add manifest.json vf/manifest.json package.json sources.json FILE-HASHES.json PATCH-SHA256SUMS.txt SHA256SUMS.json | |
| if git diff --cached --quiet; then | |
| echo "Manifest is unchanged." | |
| exit 0 | |
| fi | |
| git commit -m "chore: publish Nuvio provider manifest" | |
| git push origin HEAD:main |