Nightly (heavy doc gates) #43
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: Nightly (heavy doc gates) | |
| # Runs the HEAVY doc-execution gates that per-PR run-ci skips (SNIPPET-COMPILE, | |
| # SNIPPET-RUN, EXAMPLES-RUN — tier=nightly) via SW_CI_TIER=nightly, which runs the | |
| # FULL gate set (nightly is a superset of the per-PR tier). | |
| # | |
| # Skip-if-unchanged: the guard fingerprints the (port, porting-sdk, python) HEAD SHA | |
| # triple into a cache key. A GREEN heavy run saves that key; the next nightly probes | |
| # it (restore, lookup-only) — a HIT means the exact triple already passed, so the | |
| # heavy job is skipped. A no-op nightly costs a cache probe, not the full run. | |
| on: | |
| schedule: | |
| - cron: '23 7 * * *' | |
| workflow_dispatch: | |
| inputs: | |
| force: | |
| description: 'Run even if nothing changed since the last successful nightly' | |
| type: boolean | |
| default: false | |
| concurrency: | |
| group: nightly-${{ github.ref }} | |
| cancel-in-progress: false | |
| permissions: | |
| contents: read | |
| env: | |
| # Opt into Node.js 24 ahead of GitHub's 2026-06-02 default switch. | |
| FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true" | |
| jobs: | |
| guard: | |
| runs-on: ubuntu-latest | |
| outputs: | |
| changed: ${{ steps.check.outputs.changed }} | |
| cache_key: ${{ steps.fp.outputs.cache_key }} | |
| steps: | |
| - name: Fingerprint input HEAD SHAs (port + porting-sdk + python) | |
| id: fp | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| PSDK_TOKEN: ${{ secrets.PORTING_SDK_TOKEN }} | |
| run: | | |
| set -euo pipefail | |
| port_sha='${{ github.sha }}' | |
| psdk_sha=$(GH_TOKEN="$PSDK_TOKEN" gh api repos/signalwire/porting-sdk/commits/main --jq .sha) | |
| py_sha=$(gh api repos/signalwire/signalwire-python/commits/main --jq .sha) | |
| echo "cache_key=nightly-green-v1-${port_sha}-${psdk_sha}-${py_sha}" >> "$GITHUB_OUTPUT" | |
| echo "inputs -> port=$port_sha psdk=$psdk_sha python=$py_sha" | |
| - name: Probe last-green marker | |
| id: probe | |
| uses: actions/cache/restore@v6 | |
| with: | |
| path: .nightly-green-marker | |
| key: ${{ steps.fp.outputs.cache_key }} | |
| lookup-only: true | |
| - name: Decide | |
| id: check | |
| env: | |
| FORCE: ${{ github.event.inputs.force }} | |
| run: | | |
| set -euo pipefail | |
| if [ "$FORCE" = "true" ]; then echo "changed=true" >> "$GITHUB_OUTPUT"; exit 0; fi | |
| if [ "${{ steps.probe.outputs.cache-hit }}" = "true" ]; then | |
| echo "input triple already passed a nightly -> skipping heavy gates" | |
| echo "changed=false" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "input triple not yet green -> running heavy gates" | |
| echo "changed=true" >> "$GITHUB_OUTPUT" | |
| fi | |
| heavy: | |
| needs: guard | |
| if: needs.guard.outputs.changed == 'true' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout signalwire-java | |
| uses: actions/checkout@v7 | |
| with: | |
| path: signalwire-java | |
| - name: Checkout porting-sdk (mock_relay + mock_signalwire test harnesses + audit scripts) | |
| uses: actions/checkout@v7 | |
| with: | |
| repository: signalwire/porting-sdk | |
| # Coordinated-pass pin: 'main' normally; set the PORTING_SDK_REF repo variable | |
| # to a wave branch to test a coordinated porting-sdk change, declared on the PR | |
| # (see porting-sdk/COORDINATED_PASS.md). No revert commit. | |
| ref: ${{ vars.PORTING_SDK_REF || 'main' }} | |
| path: porting-sdk | |
| token: ${{ secrets.PORTING_SDK_TOKEN }} | |
| # The EMISSION gate compares this port's to_dict() output against the | |
| # signalwire-python oracle (FunctionResult), which pulls fastapi via | |
| # signalwire/__init__. Check it out only if it isn't already present as a | |
| # sibling (it is in the cross-port matrix checkout; it is NOT in this | |
| # per-port workflow), so the EMISSION gate has its reference. | |
| - name: Checkout signalwire-python (EMISSION oracle) if not already present | |
| uses: actions/checkout@v7 | |
| with: | |
| repository: signalwire/signalwire-python | |
| path: signalwire-python | |
| ref: ${{ vars.PORTING_SDK_REF || 'main' }} | |
| - name: Set up JDK 21 | |
| uses: actions/setup-java@v5 | |
| with: | |
| distribution: temurin | |
| java-version: '21' | |
| - name: Set up Gradle | |
| uses: gradle/actions/setup-gradle@v6 | |
| - name: Set up Python (porting-sdk audit scripts + mock servers) | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: '3.12' | |
| - name: Install Python test harnesses (mock_relay + mock_signalwire) | |
| run: | | |
| pip install -e porting-sdk/test_harness/mock_relay | |
| pip install -e porting-sdk/test_harness/mock_signalwire | |
| # The EMISSION gate needs `import signalwire` (the oracle). Install it from | |
| # the adjacent checkout only if it isn't already importable — so a runner | |
| # that already has it (or a future shared setup) isn't reinstalled. | |
| - name: Install signalwire-python (EMISSION oracle) if not importable | |
| run: | | |
| if python -c "import signalwire.core.function_result" 2>/dev/null; then | |
| echo "signalwire-python already importable; skipping install" | |
| else | |
| pip install ./signalwire-python | |
| fi | |
| - name: Run CI gate script (TEST -> SIGNATURES -> DRIFT -> NO-CHEAT) | |
| working-directory: signalwire-java | |
| env: | |
| PORTING_SDK: ${{ github.workspace }}/porting-sdk | |
| SW_CI_TIER: nightly | |
| # COORDINATED-PASS reads the live PR body/labels via 'gh api' to see a | |
| # 'Coordinated-With:' declaration edited after the triggering push. | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: bash scripts/run-ci.sh | |
| - name: Record green marker for this input triple | |
| run: 'echo green > .nightly-green-marker' | |
| - uses: actions/cache/save@v6 | |
| with: | |
| path: .nightly-green-marker | |
| key: ${{ needs.guard.outputs.cache_key }} | |