chore(deps-dev): bump the dev-dependencies group across 1 directory with 12 updates #958
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: Conformance | |
| # Wires conformance + the release gate into CI (issue #12). The cheap, always-on | |
| # jobs (release-gate, integration) run on every PR/push and gate stable | |
| # releases. deploy-target auto-deploys packages/conformance-target to | |
| # conformance.dwk.io on every push to main, in addition to on demand | |
| # (workflow_dispatch) or the weekly schedule. The hosted conformance suites | |
| # need a deployed, publicly reachable Worker, so they only run on demand or on | |
| # the weekly schedule, against a target URL — they never block ordinary | |
| # pushes. | |
| on: | |
| pull_request: | |
| push: | |
| branches: [main] | |
| schedule: | |
| - cron: "0 6 * * 1" # Mondays 06:00 UTC | |
| workflow_dispatch: | |
| inputs: | |
| standard: | |
| description: "Which hosted suite to run" | |
| required: true | |
| type: choice | |
| options: [micropub, webmention, solid, webdav, activitypub] | |
| target_url: | |
| description: "Base URL of a deployed target to test" | |
| required: false | |
| target_id: | |
| description: "Conformance column to record into" | |
| required: false | |
| default: cloudflare | |
| type: choice | |
| options: [cloudflare, node, fedify] | |
| peer_url: | |
| description: >- | |
| activitypub only: publicly reachable URL for the ephemeral Fedify | |
| peer's inbox. Usually left empty — the job auto-provisions a | |
| Cloudflare Quick Tunnel on the runner. Supply one only to override | |
| (e.g. a tunnel you started yourself against a peer running | |
| elsewhere). | |
| required: false | |
| permissions: | |
| contents: read | |
| jobs: | |
| # Static guard: refuses to let any package go stable (>=1.0.0) before its | |
| # conformance suites + integration lifecycle tests are recorded as passing. | |
| release-gate: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 | |
| - uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6 | |
| - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7 | |
| with: | |
| # Node 24 for parity with CI: @dwk/server's node:sqlite shims run | |
| # flag-free (spec/self-hosting.md §16 decision 2). | |
| node-version: 24 | |
| cache: pnpm | |
| - run: pnpm install --frozen-lockfile | |
| - name: Unit-test the release gate | |
| run: pnpm test:gate | |
| - name: Enforce release gate | |
| run: pnpm release:gate | |
| - name: Unit-test the catalog gate | |
| run: pnpm test:catalog | |
| - name: Enforce catalog gate (catalog.json covers every package) | |
| run: pnpm catalog:check | |
| # Verb-lifecycle integration tests (authenticated GET-through-WAC; PATCH with | |
| # where/conflict; If-Match preconditioned writes) under workerd/Miniflare. | |
| integration: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 | |
| - uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6 | |
| - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7 | |
| with: | |
| # Node 24 for parity with CI: @dwk/server's node:sqlite shims run | |
| # flag-free (spec/self-hosting.md §16 decision 2). | |
| node-version: 24 | |
| cache: pnpm | |
| - run: pnpm install --frozen-lockfile | |
| - name: Build | |
| run: pnpm build | |
| - name: Integration lifecycle tests | |
| run: pnpm test:integration | |
| # Deploys the composed conformance target (packages/conformance-target) to | |
| # conformance.dwk.io so the hosted suites have something to run against. | |
| # Skips gracefully when the Cloudflare secrets are not configured, so the | |
| # weekly schedule (and pushes to main, on forks) stays green before | |
| # one-time setup. Runs on every push to main so conformance.dwk.io tracks | |
| # main directly, in addition to the manual/scheduled paths. | |
| deploy-target: | |
| if: >- | |
| github.event_name == 'workflow_dispatch' || | |
| github.event_name == 'schedule' || | |
| github.event_name == 'push' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Check Cloudflare credentials | |
| id: creds | |
| run: echo "ok=${{ secrets.CLOUDFLARE_API_TOKEN != '' }}" >> "$GITHUB_OUTPUT" | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 | |
| if: steps.creds.outputs.ok == 'true' | |
| - uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6 | |
| if: steps.creds.outputs.ok == 'true' | |
| - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7 | |
| if: steps.creds.outputs.ok == 'true' | |
| with: | |
| # Node 24 for parity with CI: @dwk/server's node:sqlite shims run | |
| # flag-free (spec/self-hosting.md §16 decision 2). | |
| node-version: 24 | |
| cache: pnpm | |
| - run: pnpm install --frozen-lockfile | |
| if: steps.creds.outputs.ok == 'true' | |
| - name: Build workspace packages | |
| if: steps.creds.outputs.ok == 'true' | |
| run: pnpm build | |
| - name: Deploy conformance target | |
| if: steps.creds.outputs.ok == 'true' | |
| uses: cloudflare/wrangler-action@ebbaa1584979971c8614a24965b4405ff95890e0 # v4 | |
| with: | |
| apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} | |
| accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} | |
| workingDirectory: packages/conformance-target | |
| - name: Deploy skipped | |
| if: steps.creds.outputs.ok != 'true' | |
| run: echo "CLOUDFLARE_API_TOKEN not configured; skipping deploy." | |
| # Hosted conformance suites: only on manual dispatch or the weekly schedule, | |
| # since they require a deployed target. The runner is a documented no-op when | |
| # no target URL is supplied. | |
| hosted-suite: | |
| needs: deploy-target | |
| if: github.event_name == 'workflow_dispatch' || github.event_name == 'schedule' | |
| runs-on: ubuntu-latest | |
| strategy: | |
| matrix: | |
| standard: ${{ github.event_name == 'workflow_dispatch' && fromJSON(format('["{0}"]', inputs.standard)) || fromJSON('["micropub","webmention","solid","webdav","activitypub"]') }} | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 | |
| - uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6 | |
| - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7 | |
| with: | |
| # Node 24 for parity with CI: @dwk/server's node:sqlite shims run | |
| # flag-free (spec/self-hosting.md §16 decision 2). | |
| node-version: 24 | |
| cache: pnpm | |
| - run: pnpm install --frozen-lockfile | |
| # litmus is a real CLI the WebDAV dispatcher shells out to; the Fedify | |
| # peer (activitypub) is a devDependency already installed above; the | |
| # other suites are hosted web services that need no local tooling. | |
| - name: Install litmus (WebDAV) | |
| if: matrix.standard == 'webdav' | |
| run: sudo apt-get update && sudo apt-get install -y litmus | |
| # ActivityPub: the ephemeral Fedify peer needs a publicly reachable | |
| # callback URL. Unless the operator supplied peer_url themselves, | |
| # auto-provision a Cloudflare Quick Tunnel (no account needed — | |
| # Cloudflare is already this project's deploy target) forwarding to the | |
| # peer's port on this runner. Failure to come up is non-fatal: the | |
| # callback cases then report `skipped` loudly, and `webfinger` still | |
| # runs. | |
| - name: Provision Quick Tunnel (ActivityPub) | |
| id: tunnel | |
| if: >- | |
| matrix.standard == 'activitypub' && | |
| inputs.target_url != '' && | |
| inputs.peer_url == '' | |
| timeout-minutes: 3 | |
| run: | | |
| curl -fsSL -o /tmp/cloudflared \ | |
| https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64 | |
| chmod +x /tmp/cloudflared | |
| /tmp/cloudflared tunnel --url http://localhost:8765 --no-autoupdate \ | |
| > /tmp/cloudflared.log 2>&1 & | |
| url="" | |
| for _ in $(seq 1 30); do | |
| url=$(grep -oE 'https://[a-z0-9-]+\.trycloudflare\.com' /tmp/cloudflared.log | head -1 || true) | |
| [ -n "$url" ] && break | |
| sleep 2 | |
| done | |
| if [ -z "$url" ]; then | |
| echo "::warning::Quick Tunnel did not come up; callback cases will be skipped." | |
| cat /tmp/cloudflared.log || true | |
| else | |
| echo "peer_url=$url" >> "$GITHUB_OUTPUT" | |
| echo "Quick Tunnel ready: $url" | |
| fi | |
| # The owner publish URL is only meaningful for the ActivityPub suite, and | |
| # building it is a URL *join*, not a string concat. Doing it inline with | |
| # `format()` meant a `target_url` that carries a path or a trailing slash | |
| # — which the WebDAV runbook's `https://…/dav/` requires — produced | |
| # `https://…/dav//outbox`, and every non-ActivityPub dispatch computed a | |
| # nonsense URL that then surfaced in the job log. Resolve it here | |
| # instead: scoped to the one suite that reads it, with trailing slashes | |
| # stripped. An unset token still yields an empty value, so the publish | |
| # cases report `skipped` exactly as before. | |
| - name: Resolve ActivityPub publish URL | |
| id: publish | |
| if: matrix.standard == 'activitypub' | |
| env: | |
| TARGET_URL: ${{ inputs.target_url || 'https://conformance.dwk.io' }} | |
| PUBLISH_TOKEN: ${{ secrets.FEDIFY_PUBLISH_TOKEN }} | |
| run: | | |
| if [ -z "$PUBLISH_TOKEN" ]; then | |
| echo "FEDIFY_PUBLISH_TOKEN unset; publish cases will report skipped." | |
| exit 0 | |
| fi | |
| base="$TARGET_URL" | |
| while [ "$base" != "${base%/}" ]; do base="${base%/}"; done | |
| echo "url=${base}/outbox" >> "$GITHUB_OUTPUT" | |
| echo "Owner publish URL: ${base}/outbox" | |
| - name: Run hosted conformance suite | |
| env: | |
| # The weekly schedule carries no `inputs` (those only exist for | |
| # workflow_dispatch), so without a fallback here every scheduled run | |
| # invoked run-suite.mjs with no --target and silently no-op'd (green | |
| # badge, zero suites actually run). deploy-target above just | |
| # (re)deployed exactly this URL, on both the schedule and dispatch | |
| # paths, so it's the correct default whenever an operator doesn't | |
| # override it. | |
| TARGET_URL: ${{ inputs.target_url || 'https://conformance.dwk.io' }} | |
| # Basic credentials for the WebDAV mount (an app password minted via | |
| # the owner-gated endpoint); unset for the other suites. | |
| WEBDAV_USERNAME: ${{ secrets.WEBDAV_USERNAME }} | |
| WEBDAV_PASSWORD: ${{ secrets.WEBDAV_PASSWORD }} | |
| # Publicly reachable callback URL for the ephemeral Fedify peer | |
| # (issue #246): the operator's peer_url override when given, else | |
| # the Quick Tunnel provisioned above (empty when neither — the | |
| # callback cases then report `skipped`, never silently dropped). | |
| FEDIFY_PEER_URL: ${{ inputs.peer_url || steps.tunnel.outputs.peer_url }} | |
| # Owner publish channel for the fanout/announce-unwrap cases | |
| # (fediverse interop #273): the deployed target's outbox URL plus | |
| # its ACTIVITYPUB_PUBLISH_TOKEN (mirrored into this repo secret). | |
| # Resolved by the step above (empty for every other suite, and when | |
| # the token is unset) ⇒ those cases report `skipped`. | |
| FEDIFY_PUBLISH_URL: ${{ steps.publish.outputs.url }} | |
| FEDIFY_PUBLISH_TOKEN: ${{ secrets.FEDIFY_PUBLISH_TOKEN }} | |
| # Matrix/input values interpolated via env, never directly into the | |
| # `run:` shell — workflow_dispatch inputs are attacker-controlled | |
| # for anyone with write access, so string-building a command from | |
| # them directly is a shell-injection vector. | |
| STANDARD: ${{ matrix.standard }} | |
| TARGET_ID: ${{ inputs.target_id || (matrix.standard == 'activitypub' && 'fedify' || 'cloudflare') }} | |
| run: | | |
| node scripts/conformance/run-suite.mjs "$STANDARD" \ | |
| --target "$TARGET_URL" \ | |
| --target-id "$TARGET_ID" |