Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,7 @@ jobs:
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7

- uses: pnpm/action-setup@b906affcce14559ad1aafd4ab0e942779e9f58b1 # v4
with:
version: 11.12.0
- uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6.0.10

- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7
with:
Expand Down
9 changes: 5 additions & 4 deletions .github/workflows/demo.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,7 @@ jobs:
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7

- uses: pnpm/action-setup@b906affcce14559ad1aafd4ab0e942779e9f58b1 # v4
with:
version: 11.12.0
- uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6.0.10

- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7
with:
Expand All @@ -56,9 +54,12 @@ jobs:
cp apps/dashboard/dist/index.html apps/dashboard/dist/404.html
touch apps/dashboard/dist/.nojekyll

- uses: actions/upload-pages-artifact@56afc609e74202658d3ffba0e8f6dda462b719fa # v3
# include-hidden-files: v4 of this action started excluding dotfiles from the tarball, which
# would silently drop the .nojekyll written above.
- uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5.0.0
with:
path: apps/dashboard/dist
include-hidden-files: true

deploy:
needs: build
Expand Down
8 changes: 3 additions & 5 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,7 @@ jobs:

- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7

- uses: pnpm/action-setup@b906affcce14559ad1aafd4ab0e942779e9f58b1 # v4
with:
version: 11.12.0
- uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6.0.10

- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7
with:
Expand Down Expand Up @@ -66,13 +64,13 @@ jobs:
output-file: facet-sbom.spdx.json

- name: Attest SBOM
uses: actions/attest-sbom@bd218ad0dbcb3e146bd073d1d9c6d78e08aa8a0b # v2
uses: actions/attest-sbom@c604332985a26aa8cf1bdc465b92731239ec6b9e # v4.1.0
with:
subject-path: 'dist-tarballs/*.tgz'
sbom-path: facet-sbom.spdx.json

- name: Upload SBOM artifact
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: sbom-spdx
path: facet-sbom.spdx.json
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/scorecard.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,6 @@ jobs:
publish_results: true

- name: Upload SARIF to code scanning
uses: github/codeql-action/upload-sarif@b7351df727350dca84cb9d725d57dcf5bc82ba26 # v3
uses: github/codeql-action/upload-sarif@f205ea1c3313d32999d8d6a48b4f6530d4437b38 # v4.37.4
with:
sarif_file: results.sarif
3 changes: 0 additions & 3 deletions apps/dashboard/src/test/settings.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -163,9 +163,6 @@ beforeEach(() => {

afterEach(() => {
vi.restoreAllMocks();
// `restoreAllMocks` does not undo `stubGlobal`, so without this the stubbed fetch outlives the
// test that installed it and a late react-query retry lands on the wrong mock.
vi.unstubAllGlobals();
});

async function openSettingsWithToken() {
Expand Down
8 changes: 7 additions & 1 deletion apps/dashboard/src/test/setup.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import '@testing-library/jest-dom/vitest';
import { cleanup } from '@testing-library/react';
import { afterEach } from 'vitest';
import { afterEach, vi } from 'vitest';

// jsdom in this config does not expose Storage; provide a minimal in-memory implementation.
function makeStorage(): Storage {
Expand Down Expand Up @@ -61,4 +61,10 @@ if (!('ResizeObserver' in globalThis)) {
// React Testing Library needs explicit cleanup because vitest globals are off.
afterEach(() => {
cleanup();
// `restoreAllMocks` does not undo `stubGlobal`, so a test that stubs `fetch` and only restores
// mocks leaves the stub installed. An unmounted tree's react-query request can still be in
// flight, and it then resolves against the NEXT test's DOM — a failure that moves between files
// and machines depending on which request loses the race. Unstubbing here covers every file
// rather than relying on each one to remember.
vi.unstubAllGlobals();
});
37 changes: 25 additions & 12 deletions apps/server/test/alerts.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -624,20 +624,33 @@ describe('cron alerting', () => {
noRetry() {},
} as unknown as ScheduledController;

await expect(
runScheduled(event, env as Env, [
alertsJob,
{
name: 'after',
run: async () => {
ran = true;
// `alertsJob` calls `runAlerts` with no injectable fetch, so the unreachable-endpoint case has
// to be produced at the global. It used to be produced by letting the real `fetch` try to dial
// hooks.example.com and fail, which made the assertion depend on the runner's DNS: a resolver
// that answers NXDOMAIN with a landing page (common on ISP and VPN networks) fails it outright,
// and workerd surfaced the abandoned connection as an unhandled `internal error` rejection on
// every run of this suite.
vi.stubGlobal(
'fetch',
vi.fn(() => Promise.reject(new Error('unreachable'))),
);
try {
await expect(
runScheduled(event, env as Env, [
alertsJob,
{
name: 'after',
run: async () => {
ran = true;
},
},
},
]),
).resolves.toBeUndefined();
]),
).resolves.toBeUndefined();
} finally {
vi.unstubAllGlobals();
}
expect(ran).toBe(true);
// The job used the real `fetch`, which cannot reach hooks.example.com from the test runtime —
// exactly the "endpoint is unreachable" case. It must be recorded, not thrown.
// A dead endpoint must be recorded, not thrown.
const rows = await deliveryRows();
expect(rows).toHaveLength(1);
expect(rows[0]?.status).toBe('failed');
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"homepage": "https://github.com/writerslogic/facet#readme",
"bugs": "https://github.com/writerslogic/facet/issues",
"type": "module",
"packageManager": "pnpm@11.12.0",
"packageManager": "pnpm@11.20.0",
"engines": {
"node": ">=22"
},
Expand Down
Loading