mirror of
https://github.com/simstudioai/sim.git
synced 2026-09-24 15:45:35 +08:00
* chore(ci): cut redundant runner minutes — dedup promotion-PR test runs, companion-pr-check concurrency, right-size trivial jobs
- ci.yml: new dedup-promotion gate skips the pull_request test-build on
staging/main-headed promotion PRs only when the merge tree provably equals
the head tree (empty base delta over the merge base) AND the push-event run
at the same sha passed its test jobs (polled). Fail-open on any error/
timeout/failure, job-level skip only (skipped job reports Success); verified
no required status checks are configured on main/staging rulesets.
Measured 39 duplicate PR runs / 5.15 days (~227/mo) at ~7.1 min each on
8vcpu (~57 vcpu-min), probe costs ~9 vcpu-min worst case on 2vcpu.
- companion-pr-check.yml: per-PR concurrency group with cancel-in-progress so
superseded synchronize/edit runs stop; no paths filter (check depends on PR
body + cross-repo state, not changed files).
- detect-version and check-docs-changes: 4vcpu -> 2vcpu Blacksmith runners
(pure shell / depth-2 checkout + path filter only).
* improvement(testing): complete stateful shared mocks for env, urls, redis-config, environment-utils
Shared mock infrastructure for vitest isolate:false convergence:
- packages/testing/src/mocks/env.mock.ts: stateful envMock (live env proxy, setEnv/resetEnvMock, process.env fallback)
- packages/testing/src/mocks/urls.mock.ts: complete urlsMock with real-behavior default impls + resetUrlsMock
- packages/testing/src/mocks/redis-config.mock.ts: adds getRedisConnectionDefaults + resetRedisConfigMock
- packages/testing/src/mocks/environment-utils.mock.ts: new environmentUtilsMock + fns + reset
- contract tests: env.mock.test.ts, urls.mock.test.ts, redis-config.mock.test.ts, environment-utils.mock.test.ts
- packages/testing/src/mocks/index.ts: barrel exports
- apps/sim/vitest.setup.ts: global installs for env, urls, redis, environment/utils
- real-module tests unmocked: lib/core/config/env.test.ts, lib/core/config/redis.test.ts, lib/core/utils/urls.test.ts, tools/index.test.ts (urls)
- stubEnv/process.env fallout migrated to setEnv: lib/webhooks/providers/{revenuecat,rootly,instantly}.test.ts, app/api/auth/oauth2/authorize/route.test.ts
* improvement(tests): drop redundant local mocks in executor/tools/providers and misc dirs (shared-worker readiness)
* improvement(tests): drop redundant local mocks in app routes (shared-worker readiness)
* improvement(tests): drop redundant local mocks in lib (shared-worker readiness)
* fix(ci+testing): live base-tip recheck before dedup skip; prod-aware urls mock fallbacks
- the dedup gate re-verifies merge-tree equivalence against the LIVE base
tip at decision time, closing the window where the base branch gains real
commits during the poll (frozen BASE_SHA check alone was stale)
- the urls mock's getBaseUrl protocol prefix and getBaseDomain parse
fallback now follow the shared isProd flag, mirroring the real module
* fix(ci+testing): fail-closed nojobs fallback in dedup gate; TLS-aware redis defaults mock
- the dedup gate no longer infers coverage from overall run conclusion when
no 'Test and Build /' jobs match — a renamed or skipped test job now runs
the tests instead of skipping them
- the shared getRedisConnectionDefaults mock mirrors the real TLS resolution
(rediss:// to a raw IP requires REDIS_TLS_SERVERNAME and yields
tls.servername)
* fix(ci): keep polling while nested test jobs have not appeared yet
An in-progress push run lists its reusable-workflow jobs only after the
caller starts; nojobs is now terminal (fail closed) only once the run has
completed without them.
151 lines
4.1 KiB
TypeScript
151 lines
4.1 KiB
TypeScript
import {
|
|
authMock,
|
|
databaseMock,
|
|
drizzleOrmMock,
|
|
envFlagsMock,
|
|
environmentUtilsMock,
|
|
envMock,
|
|
hybridAuthMock,
|
|
loggerMock,
|
|
redisConfigMock,
|
|
requestUtilsMock,
|
|
schemaMock,
|
|
setupGlobalFetchMock,
|
|
setupGlobalStorageMocks,
|
|
terminalConsoleMock,
|
|
urlsMock,
|
|
workflowAuthzMock,
|
|
} from '@sim/testing'
|
|
import { afterAll, vi } from 'vitest'
|
|
import '@testing-library/jest-dom/vitest'
|
|
|
|
setupGlobalFetchMock()
|
|
setupGlobalStorageMocks()
|
|
|
|
vi.mock('@sim/db', () => databaseMock)
|
|
vi.mock('@sim/db/schema', () => schemaMock)
|
|
vi.mock('drizzle-orm', () => drizzleOrmMock)
|
|
vi.mock('@sim/logger', () => loggerMock)
|
|
vi.mock('@sim/platform-authz/workflow', () => workflowAuthzMock)
|
|
vi.mock('@/lib/auth', () => authMock)
|
|
vi.mock('@/lib/auth/hybrid', () => hybridAuthMock)
|
|
vi.mock('@/lib/core/utils/request', () => requestUtilsMock)
|
|
vi.mock('@/lib/core/config/env-flags', () => envFlagsMock)
|
|
vi.mock('@/lib/core/config/env', () => envMock)
|
|
vi.mock('@/lib/core/utils/urls', () => urlsMock)
|
|
vi.mock('@/lib/core/config/redis', () => redisConfigMock)
|
|
vi.mock('@/lib/environment/utils', () => environmentUtilsMock)
|
|
|
|
vi.mock('@/stores/console/store', () => ({
|
|
useConsoleStore: {
|
|
getState: vi.fn().mockReturnValue({
|
|
addConsole: vi.fn(),
|
|
}),
|
|
},
|
|
}))
|
|
|
|
vi.mock('@/stores/terminal', () => terminalConsoleMock)
|
|
vi.mock('@/stores/terminal/console/store', () => terminalConsoleMock)
|
|
|
|
vi.mock('@/stores/execution/store', () => ({
|
|
useExecutionStore: {
|
|
getState: vi.fn().mockReturnValue({
|
|
getWorkflowExecution: vi.fn().mockReturnValue({
|
|
status: 'idle',
|
|
isExecuting: false,
|
|
isDebugging: false,
|
|
activeBlockIds: new Set(),
|
|
pendingBlocks: [],
|
|
executor: null,
|
|
debugContext: null,
|
|
lastRunPath: new Map(),
|
|
lastRunEdges: new Map(),
|
|
}),
|
|
setStatus: vi.fn(),
|
|
setIsExecuting: vi.fn(),
|
|
setIsDebugging: vi.fn(),
|
|
setPendingBlocks: vi.fn(),
|
|
reset: vi.fn(),
|
|
setActiveBlocks: vi.fn(),
|
|
setBlockRunStatus: vi.fn(),
|
|
setEdgeRunStatus: vi.fn(),
|
|
clearRunPath: vi.fn(),
|
|
}),
|
|
},
|
|
useCurrentWorkflowExecution: vi.fn().mockReturnValue({
|
|
status: 'idle',
|
|
isExecuting: false,
|
|
isDebugging: false,
|
|
activeBlockIds: new Set(),
|
|
pendingBlocks: [],
|
|
executor: null,
|
|
debugContext: null,
|
|
lastRunPath: new Map(),
|
|
lastRunEdges: new Map(),
|
|
}),
|
|
useIsBlockActive: vi.fn().mockReturnValue(false),
|
|
useIsCurrentWorkflowExecuting: vi.fn().mockReturnValue(false),
|
|
useLastRunPath: vi.fn().mockReturnValue(new Map()),
|
|
useLastRunEdges: vi.fn().mockReturnValue(new Map()),
|
|
}))
|
|
|
|
vi.mock('@/blocks/registry', () => ({
|
|
getBlock: vi.fn(() => ({
|
|
name: 'Mock Block',
|
|
description: 'Mock block description',
|
|
icon: () => null,
|
|
subBlocks: [],
|
|
outputs: {},
|
|
})),
|
|
getAllBlocks: vi.fn(() => []),
|
|
getLatestBlock: vi.fn(() => undefined),
|
|
getBlockByToolName: vi.fn((toolName: string) =>
|
|
toolName.startsWith('gmail_')
|
|
? {
|
|
name: 'Gmail',
|
|
description: 'Gmail integration',
|
|
icon: () => null,
|
|
subBlocks: [],
|
|
outputs: {},
|
|
}
|
|
: undefined
|
|
),
|
|
}))
|
|
|
|
vi.mock('@trigger.dev/sdk', () => ({
|
|
task: vi.fn(() => ({ trigger: vi.fn() })),
|
|
tasks: {
|
|
trigger: vi.fn().mockResolvedValue({ id: 'mock-task-id' }),
|
|
batchTrigger: vi.fn().mockResolvedValue([{ id: 'mock-task-id' }]),
|
|
},
|
|
runs: {
|
|
retrieve: vi.fn().mockResolvedValue({ id: 'mock-run-id', status: 'COMPLETED' }),
|
|
},
|
|
configure: vi.fn(),
|
|
}))
|
|
|
|
const originalConsoleError = console.error
|
|
const originalConsoleWarn = console.warn
|
|
|
|
console.error = (...args: any[]) => {
|
|
if (args[0] === 'Workflow execution failed:' && args[1]?.message === 'Test error') {
|
|
return
|
|
}
|
|
if (typeof args[0] === 'string' && args[0].includes('[zustand persist middleware]')) {
|
|
return
|
|
}
|
|
originalConsoleError(...args)
|
|
}
|
|
|
|
console.warn = (...args: any[]) => {
|
|
if (typeof args[0] === 'string' && args[0].includes('[zustand persist middleware]')) {
|
|
return
|
|
}
|
|
originalConsoleWarn(...args)
|
|
}
|
|
|
|
afterAll(() => {
|
|
console.error = originalConsoleError
|
|
console.warn = originalConsoleWarn
|
|
})
|