Repository navigation
feat(email): void/email — outbound, inbound, platform proxy, and own-account setup #1441
Workflow file for this run
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: CI | |
| on: | |
| push: | |
| branches: [main] | |
| pull_request: | |
| branches: [main] | |
| types: [opened, synchronize, reopened, labeled] | |
| workflow_call: | |
| inputs: | |
| skip_windows: | |
| type: boolean | |
| required: false | |
| default: false | |
| permissions: {} | |
| jobs: | |
| test: | |
| name: test (${{ matrix.os }}, ${{ matrix.shard }}) | |
| runs-on: ${{ matrix.os == 'ubuntu-latest' && github.repository == 'voidzero-dev/void' && 'blacksmith-4vcpu-ubuntu-2404' || matrix.os }} | |
| permissions: | |
| contents: read | |
| # No Cloudflare creds in this job. The credentialed live deploy e2e runs in the separate | |
| # `live-e2e` job (below), whose secrets are bound to the `cloudflare-e2e` environment. Here the | |
| # live suite (part of `vp run test:all`) sees empty creds and self-skips on every event. | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| # Windows runs on main pushes and on PRs labeled "test: windows", | |
| # unless a reusable workflow caller explicitly disables it. | |
| os: '${{ (((github.event_name == ''push'' && startsWith(github.ref, ''refs/heads/'')) || contains(github.event.pull_request.labels.*.name, ''test: windows'')) && !(github.event_name == ''workflow_call'' && inputs.skip_windows)) && fromJSON(''["ubuntu-latest","windows-latest"]'') || fromJSON(''["ubuntu-latest"]'') }}' | |
| # Unit tests and two integration shards run on separate runners. Each integration | |
| # shard builds its own checkout first, so generated playground state is never shared. | |
| shard: [unit, '1/2', '2/2'] | |
| steps: | |
| - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 | |
| with: | |
| persist-credentials: false | |
| # Defender's real-time scan is synchronous on every file write, and this suite writes a lot of | |
| # them (dependency install, ~26 playground builds, per-worker temp dirs). Excluding the paths | |
| # we generate is purely a speed measure: it never changes what runs. | |
| # | |
| # Skipped for fork pull requests, the only case where the checkout is code no maintainer has | |
| # pushed. Not because scanning is a boundary for this job — it has no secrets, a read-only | |
| # token, an ephemeral runner, and already executes the PR's own build and test code by design | |
| # — but because leaving the scan on for untrusted checkouts costs us nothing: Windows runs on | |
| # a PR only when a maintainer applies the `test: windows` label, so this is rare, while main | |
| # pushes and maintainer branches (the everyday path) keep the speedup. | |
| # | |
| # Warns instead of failing, so a runner image that refuses the call still runs the suite. | |
| - name: Exclude build paths from Windows Defender | |
| if: >- | |
| ${{ contains(matrix.os, 'windows') | |
| && (github.event_name == 'push' | |
| || github.event.pull_request.head.repo.full_name == github.repository) }} | |
| shell: pwsh | |
| run: | | |
| foreach ($path in @('${{ github.workspace }}', '${{ runner.temp }}')) { | |
| try { | |
| Add-MpPreference -ExclusionPath $path -ErrorAction Stop | |
| Write-Host "Defender exclusion added: $path" | |
| } catch { | |
| Write-Host "::warning::could not add Defender exclusion for ${path}: $_" | |
| } | |
| } | |
| - uses: voidzero-dev/setup-vp@2dec1e33f4ab2c6d5bce1b0c4607961bb1a3f7a1 # v1.12.0 | |
| with: | |
| node-version-file: .node-version | |
| cache: true | |
| # The upstream Linux image and Windows already provide browser libraries. | |
| # Forks use GitHub's Ubuntu image and install Chromium's system dependencies. | |
| - run: vp exec playwright install chromium | |
| if: ${{ matrix.shard != 'unit' && (runner.os != 'Linux' || github.repository == 'voidzero-dev/void') }} | |
| - run: vp exec playwright install --with-deps chromium | |
| if: ${{ matrix.shard != 'unit' && runner.os == 'Linux' && github.repository != 'voidzero-dev/void' }} | |
| - run: vp check | |
| if: ${{ matrix.shard == 'unit' }} | |
| # Unit suites import the core package and its workspace dependencies through public exports and | |
| # exercise generated CLI assets, so they need the transitive core stack even though they skip | |
| # playground builds. | |
| - run: vp run build:core | |
| if: ${{ matrix.shard == 'unit' }} | |
| - run: vp test run --project unit | |
| if: ${{ matrix.shard == 'unit' }} | |
| - run: vp run build:all | |
| if: ${{ matrix.shard != 'unit' }} | |
| - run: vp run check | |
| if: ${{ matrix.shard == '1/2' }} | |
| - run: vp test run --project parallel-integration --shard=${{ matrix.shard }} | |
| if: ${{ matrix.shard != 'unit' }} | |
| # Credentialed live Cloudflare deploy e2e, ISOLATED from `test` so the account token exists ONLY in | |
| # a job bound to the `cloudflare-e2e` GitHub Environment. That environment's deployment branch policy | |
| # allows `main` ONLY and the ref is enforced server-side, so a `pull_request` run (ref | |
| # refs/pull/<n>/merge) can never reach the secret — even a PR that edits this file — and a modified | |
| # workflow cannot exfiltrate it. The `if` also keeps the job off everything except a direct push to | |
| # the `main` branch: tag pushes and `workflow_call` (release) carry a non-main ref, so they are | |
| # skipped — which both avoids a branch-policy failure and matches where the secret is allowed, and | |
| # it is scoped to the canonical repo so forks don't run it. It deploys a UNIQUELY-named worker | |
| # (VOID_E2E_RUN_ID) to a throwaway account and tears it down. A preflight step fails the job when a | |
| # credential is empty (unset / deleted / not-yet-rotated token), so a missing secret can never turn | |
| # the live-deploy gate into a silent green no-op (the `test` job's uncredentialed run still skips). | |
| live-e2e: | |
| if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' && github.repository == 'voidzero-dev/void' }} | |
| runs-on: blacksmith-4vcpu-ubuntu-2404 | |
| permissions: | |
| contents: read | |
| environment: cloudflare-e2e | |
| env: | |
| VOID_E2E_CF_TOKEN: ${{ secrets.VOID_E2E_CF_TOKEN }} | |
| VOID_E2E_CF_ACCOUNT_ID: ${{ secrets.VOID_E2E_CF_ACCOUNT_ID }} | |
| VOID_E2E_RUN_ID: ${{ github.run_id }}-${{ github.run_attempt }} | |
| steps: | |
| - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 | |
| with: | |
| persist-credentials: false | |
| - uses: voidzero-dev/setup-vp@2dec1e33f4ab2c6d5bce1b0c4607961bb1a3f7a1 # v1.12.0 | |
| with: | |
| node-version-file: .node-version | |
| cache: true | |
| # Fail closed BEFORE the build: a missing/empty credential must fail this job, not self-skip. The | |
| # `${VAR:?}` expansion exits nonzero when the secret is unset OR empty (GitHub resolves an unset | |
| # secret to ''). | |
| - name: Require live Cloudflare credentials | |
| run: | | |
| : "${VOID_E2E_CF_TOKEN:?empty — set it as a cloudflare-e2e environment secret}" | |
| : "${VOID_E2E_CF_ACCOUNT_ID:?empty — set it as a cloudflare-e2e environment secret}" | |
| # build:core produces the core package and its workspace dependencies, including | |
| # dist/cli/cli.mjs and the built `void` plugin the deploy uses to build the app. | |
| - run: vp run build:core | |
| - run: vp test run packages/void/test/e2e/cloudflare-deploy-live.test.ts | |
| done: | |
| runs-on: ubuntu-latest | |
| if: always() | |
| needs: | |
| - test | |
| - live-e2e | |
| steps: | |
| - run: exit 1 | |
| if: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }} |