Merge pull request #1505 from johndoe6345789/claude/fix-github-actions-SSaHp

fix(ci): resolve E2E test failures and upgrade GitHub Actions to Node.js 24
This commit is contained in:
2026-03-11 18:32:00 +00:00
committed by GitHub
9 changed files with 150 additions and 109 deletions

View File

@@ -11,7 +11,7 @@ runs:
using: composite
steps:
- name: Setup Node
uses: actions/setup-node@v4
uses: actions/setup-node@v5
with:
node-version: ${{ inputs.node-version }}

View File

@@ -16,7 +16,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
- name: Install system deps
run: |
@@ -32,7 +32,7 @@ jobs:
run: conan profile detect --force
- name: Cache Conan packages
uses: actions/cache@v4
uses: actions/cache@v6
with:
path: ~/.conan2/p
key: conan-unit-${{ hashFiles('dbal/production/build-config/conanfile.tests.py') }}
@@ -67,7 +67,7 @@ jobs:
run: ctest -R dbal_unit_tests --output-on-failure
- name: Upload results
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v6
if: always()
with:
name: unit-test-results
@@ -82,7 +82,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
- name: Install Go (for testcontainers-sidecar)
uses: actions/setup-go@v5
@@ -124,7 +124,7 @@ jobs:
-s build_type=Release -s compiler.cppstd=20
- name: Cache Conan packages
uses: actions/cache@v4
uses: actions/cache@v6
with:
path: ~/.conan2/p
key: conan-integration-${{ hashFiles('dbal/production/build-config/conanfile.tests.py') }}
@@ -162,7 +162,7 @@ jobs:
run: ctest -R dbal_integration_tests --output-on-failure -V
- name: Upload results
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v6
if: always()
with:
name: integration-test-results

View File

@@ -289,7 +289,7 @@ jobs:
echo "$(date -Iseconds)" > gate-artifacts/gate-1/start-time.txt
- name: Upload gate start marker
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v6
with:
name: gate-1-start
path: gate-artifacts/gate-1/
@@ -301,7 +301,7 @@ jobs:
needs: gate-1-start
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v6
- name: Setup Python
uses: actions/setup-python@v5
@@ -384,7 +384,7 @@ jobs:
- name: Upload validation result
if: always()
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v6
with:
name: gate-1-schema-result
path: gate-artifacts/gate-1/
@@ -396,7 +396,7 @@ jobs:
needs: schema-check
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v6
- name: Setup npm with Nexus
uses: ./.github/actions/setup-npm
@@ -418,7 +418,7 @@ jobs:
- name: Upload validation result
if: always()
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v6
with:
name: gate-1-typecheck-result
path: gate-artifacts/gate-1/
@@ -430,7 +430,7 @@ jobs:
needs: schema-check
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v6
- name: Setup npm with Nexus
uses: ./.github/actions/setup-npm
@@ -464,7 +464,7 @@ jobs:
- name: Upload validation result
if: always()
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v6
with:
name: gate-1-lint-result
path: gate-artifacts/gate-1/
@@ -476,7 +476,7 @@ jobs:
needs: schema-check
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v6
- name: Setup npm with Nexus
uses: ./.github/actions/setup-npm
@@ -499,7 +499,7 @@ jobs:
- name: Upload validation result
if: always()
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v6
with:
name: gate-1-security-result
path: gate-artifacts/gate-1/
@@ -511,7 +511,7 @@ jobs:
needs: schema-check
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v6
- name: Check for oversized files
run: |
@@ -534,7 +534,7 @@ jobs:
- name: Upload validation result
if: always()
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v6
with:
name: gate-1-filesize-result
path: gate-artifacts/gate-1/
@@ -546,7 +546,7 @@ jobs:
needs: schema-check
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v6
- name: Check code complexity
run: |
@@ -571,7 +571,7 @@ jobs:
- name: Upload validation result
if: always()
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v6
with:
name: gate-1-complexity-result
path: gate-artifacts/gate-1/
@@ -583,7 +583,7 @@ jobs:
needs: schema-check
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v6
- name: Detect stubs and placeholder code
run: |
@@ -609,7 +609,7 @@ jobs:
- name: Upload validation result
if: always()
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v6
with:
name: gate-1-stub-result
path: gate-artifacts/gate-1/
@@ -620,7 +620,7 @@ jobs:
needs: [schema-check, typecheck, lint, security-scan, file-size-check, code-complexity-check, stub-detection]
steps:
- name: Download all gate 1 artifacts
uses: actions/download-artifact@v4
uses: actions/download-artifact@v6
with:
pattern: gate-1-*
path: gate-artifacts/
@@ -648,7 +648,7 @@ jobs:
ls -la gate-artifacts/gate-1/
- name: Upload consolidated gate 1 report
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v6
with:
name: gate-1-complete-report
path: gate-artifacts/
@@ -674,7 +674,7 @@ jobs:
echo "$(date -Iseconds)" > gate-artifacts/gate-2/start-time.txt
- name: Upload gate start marker
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v6
with:
name: gate-2-start
path: gate-artifacts/gate-2/
@@ -686,7 +686,7 @@ jobs:
needs: gate-2-start
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v6
- name: Setup npm with Nexus
uses: ./.github/actions/setup-npm
@@ -730,7 +730,7 @@ jobs:
- name: Upload coverage report
if: always()
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v6
with:
name: coverage-report
path: frontends/nextjs/coverage/
@@ -745,7 +745,7 @@ jobs:
- name: Upload validation result
if: always()
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v6
with:
name: gate-2-unit-result
path: gate-artifacts/gate-2/
@@ -757,7 +757,7 @@ jobs:
needs: gate-2-start
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v6
- name: Setup npm with Nexus
uses: ./.github/actions/setup-npm
@@ -770,11 +770,6 @@ jobs:
- name: Install Playwright Browsers
run: npx playwright install --with-deps chromium
- name: Start smoke stack
run: |
docker compose -f deployment/docker-compose.smoke.yml up -d --wait --wait-timeout 180
timeout-minutes: 5
- name: Run Playwright tests
run: |
if [ -f e2e/playwright.config.ts ]; then
@@ -782,14 +777,11 @@ jobs:
else
echo "::warning::No playwright.config.ts found — E2E tests not configured"
fi
- name: Stop smoke stack
if: always()
run: docker compose -f deployment/docker-compose.smoke.yml down -v
timeout-minutes: 10
- name: Upload test results
if: always()
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v6
with:
name: playwright-report
path: playwright-report/
@@ -804,7 +796,7 @@ jobs:
- name: Upload validation result
if: always()
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v6
with:
name: gate-2-e2e-result
path: gate-artifacts/gate-2/
@@ -816,7 +808,7 @@ jobs:
needs: gate-2-start
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v6
- name: Setup npm with Nexus
uses: ./.github/actions/setup-npm
@@ -836,7 +828,7 @@ jobs:
- name: Upload daemon test report
if: always()
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v6
with:
name: playwright-report-dbal-daemon
path: frontends/nextjs/playwright-report/
@@ -851,7 +843,7 @@ jobs:
- name: Upload validation result
if: always()
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v6
with:
name: gate-2-dbal-result
path: gate-artifacts/gate-2/
@@ -862,7 +854,7 @@ jobs:
needs: [test-unit, test-e2e, test-dbal-daemon]
steps:
- name: Download all gate 2 artifacts
uses: actions/download-artifact@v4
uses: actions/download-artifact@v6
with:
pattern: gate-2-*
path: gate-artifacts/
@@ -886,7 +878,7 @@ jobs:
ls -la gate-artifacts/gate-2/
- name: Upload consolidated gate 2 report
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v6
with:
name: gate-2-complete-report
path: gate-artifacts/
@@ -912,7 +904,7 @@ jobs:
echo "$(date -Iseconds)" > gate-artifacts/gate-3/start-time.txt
- name: Upload gate start marker
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v6
with:
name: gate-3-start
path: gate-artifacts/gate-3/
@@ -926,7 +918,7 @@ jobs:
build-success: ${{ steps.build-step.outcome }}
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v6
- name: Setup npm with Nexus
uses: ./.github/actions/setup-npm
@@ -941,7 +933,7 @@ jobs:
run: npm run build -w frontends/nextjs
- name: Upload build artifacts
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v6
with:
name: dist
path: frontends/nextjs/.next/
@@ -956,7 +948,7 @@ jobs:
- name: Upload validation result
if: always()
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v6
with:
name: gate-3-build-result
path: gate-artifacts/gate-3/
@@ -969,7 +961,7 @@ jobs:
if: github.event_name == 'pull_request'
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v6
with:
fetch-depth: 0
@@ -999,7 +991,7 @@ jobs:
- name: Upload validation result
if: always()
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v6
with:
name: gate-3-quality-result
path: gate-artifacts/gate-3/
@@ -1011,7 +1003,7 @@ jobs:
if: always() && needs.build.result == 'success' && (needs.quality-check.result == 'success' || needs.quality-check.result == 'skipped')
steps:
- name: Download all gate 3 artifacts
uses: actions/download-artifact@v4
uses: actions/download-artifact@v6
with:
pattern: gate-3-*
path: gate-artifacts/
@@ -1032,7 +1024,7 @@ jobs:
ls -la gate-artifacts/gate-3/
- name: Upload consolidated gate 3 report
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v6
with:
name: gate-3-complete-report
path: gate-artifacts/
@@ -1048,7 +1040,7 @@ jobs:
if: github.event_name == 'pull_request' && !github.event.pull_request.draft
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v6
with:
fetch-depth: 0
@@ -1217,7 +1209,7 @@ jobs:
url: https://staging.metabuilder.example.com
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v6
- name: Setup npm with Nexus
uses: ./.github/actions/setup-npm
@@ -1267,7 +1259,7 @@ jobs:
url: https://metabuilder.example.com
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v6
- name: Setup npm with Nexus
uses: ./.github/actions/setup-npm
@@ -1336,16 +1328,16 @@ jobs:
platforms: linux/amd64,linux/arm64
steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@v6
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
uses: docker/setup-qemu-action@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
uses: docker/setup-buildx-action@v4
- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
uses: docker/login-action@v4
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
@@ -1381,7 +1373,7 @@ jobs:
VCS_REF=${{ github.sha }}
- name: Generate artifact attestation
uses: actions/attest-build-provenance@v2
uses: actions/attest-build-provenance@v4
with:
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}/${{ matrix.image }}
subject-digest: ${{ steps.build.outputs.digest }}
@@ -1404,16 +1396,16 @@ jobs:
platforms: linux/amd64,linux/arm64
steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@v6
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
uses: docker/setup-qemu-action@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
uses: docker/setup-buildx-action@v4
- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
uses: docker/login-action@v4
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
@@ -1450,7 +1442,7 @@ jobs:
VCS_REF=${{ github.sha }}
- name: Generate artifact attestation
uses: actions/attest-build-provenance@v2
uses: actions/attest-build-provenance@v4
with:
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}/${{ matrix.image }}
subject-digest: ${{ steps.build.outputs.digest }}
@@ -1463,16 +1455,16 @@ jobs:
needs: container-base-tier2
steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@v6
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
uses: docker/setup-qemu-action@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
uses: docker/setup-buildx-action@v4
- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
uses: docker/login-action@v4
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
@@ -1509,7 +1501,7 @@ jobs:
VCS_REF=${{ github.sha }}
- name: Generate artifact attestation
uses: actions/attest-build-provenance@v2
uses: actions/attest-build-provenance@v4
with:
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}/devcontainer
subject-digest: ${{ steps.build.outputs.digest }}
@@ -1548,13 +1540,13 @@ jobs:
dockerfile: ./frontends/exploded-diagrams/Dockerfile
steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@v6
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
uses: docker/setup-buildx-action@v4
- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
uses: docker/login-action@v4
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
@@ -1591,7 +1583,7 @@ jobs:
VERSION=${{ steps.meta.outputs.version }}
- name: Generate artifact attestation
uses: actions/attest-build-provenance@v2
uses: actions/attest-build-provenance@v4
with:
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}/${{ matrix.image }}
subject-digest: ${{ steps.build.outputs.digest }}
@@ -1623,14 +1615,14 @@ jobs:
- exploded-diagrams
steps:
- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
uses: docker/login-action@v4
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@0.28.0
uses: aquasecurity/trivy-action@0.35.0
timeout-minutes: 15
with:
image-ref: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}/${{ matrix.image }}:${{ github.ref_name }}
@@ -1638,7 +1630,7 @@ jobs:
output: 'trivy-results-${{ matrix.image }}.sarif'
- name: Upload Trivy results to GitHub Security tab
uses: github/codeql-action/upload-sarif@v3
uses: github/codeql-action/upload-sarif@v4
with:
sarif_file: 'trivy-results-${{ matrix.image }}.sarif'
category: container-${{ matrix.image }}
@@ -1653,7 +1645,7 @@ jobs:
REF_NAME: ${{ github.ref_name }}
steps:
- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
uses: docker/login-action@v4
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
@@ -1684,12 +1676,12 @@ jobs:
language: ${{ inputs.codeql_languages == 'all' && fromJSON('["javascript-typescript","python","cpp","go"]') || fromJSON(format('["{0}"]', inputs.codeql_languages)) }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
uses: github/codeql-action/init@v4
with:
languages: ${{ matrix.language }}
queries: security-and-quality
@@ -1697,7 +1689,7 @@ jobs:
- name: Setup Node.js
if: matrix.language == 'javascript-typescript'
uses: actions/setup-node@v4
uses: actions/setup-node@v5
with:
node-version: '20'
cache: 'npm'
@@ -1715,10 +1707,10 @@ jobs:
go-version: '1.21'
- name: Autobuild
uses: github/codeql-action/autobuild@v3
uses: github/codeql-action/autobuild@v4
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
uses: github/codeql-action/analyze@v4
with:
category: "/language:${{ matrix.language }}"
upload: true
@@ -1750,7 +1742,7 @@ jobs:
if: always()
steps:
- name: Download all gate artifacts
uses: actions/download-artifact@v4
uses: actions/download-artifact@v6
with:
pattern: gate-*-complete-report
path: all-gate-artifacts/
@@ -1815,7 +1807,7 @@ jobs:
}
- name: Upload complete audit trail
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v6
with:
name: complete-gate-audit-trail
path: all-gate-artifacts/

View File

@@ -4,10 +4,10 @@ import { test, expect } from '@playwright/test'
* Deployment smoke tests — validates all services are reachable
* through the nginx gateway on port 80.
*
* These tests require the full Docker stack to be running.
* They are NOT run in CI (excluded via playwright.config.ts testIgnore).
* CI: The smoke stack (docker-compose.smoke.yml) provides nginx + admin tools.
* Playwright dev servers bind to 0.0.0.0 so nginx can proxy via host.docker.internal.
*
* To run locally:
* Local:
* cd deployment && docker compose -f docker-compose.stack.yml up -d
* PLAYWRIGHT_BASE_URL=http://localhost/workflowui/ npx playwright test deployment-smoke
*/

View File

@@ -1,25 +1,50 @@
/**
* Playwright global setup
* Runs before all tests to seed the database with package data
*
* 1. Starts the smoke-stack Docker containers via Testcontainers
* (nginx gateway + MySQL + MongoDB + Redis + admin tools)
* 2. Seeds the database via the /api/setup endpoint
*/
import { DockerComposeEnvironment, Wait } from 'testcontainers'
import { resolve } from 'path'
let environment: Awaited<ReturnType<DockerComposeEnvironment['up']>> | undefined
async function globalSetup() {
// Wait a bit for the server to start
// ── 1. Start smoke stack via Testcontainers ──────────────────────────────
console.log('[setup] Starting smoke stack via Testcontainers...')
const composeDir = resolve(__dirname, '../deployment')
environment = await new DockerComposeEnvironment(composeDir, 'docker-compose.smoke.yml')
.withWaitStrategy('nginx', Wait.forHealthCheck())
.withWaitStrategy('phpmyadmin', Wait.forHealthCheck())
.withWaitStrategy('mongo-express', Wait.forHealthCheck())
.withWaitStrategy('redisinsight', Wait.forHealthCheck())
.withStartupTimeout(180_000)
.up()
console.log('[setup] Smoke stack healthy')
// Store ref for teardown
;(globalThis as Record<string, unknown>).__TESTCONTAINERS_ENV__ = environment
// ── 2. Wait for dev servers (started by Playwright webServer config) ─────
await new Promise(resolve => setTimeout(resolve, 2000))
try {
// Seed database with package data
const response = await fetch('http://localhost:3000/api/setup', {
method: 'POST',
})
// ── 3. Seed database ────────────────────────────────────────────────────
const setupUrl = process.env.PLAYWRIGHT_BASE_URL
? new URL('/api/setup', process.env.PLAYWRIGHT_BASE_URL.replace(/\/workflowui\/?$/, '')).href
: 'http://localhost:3000/api/setup'
try {
const response = await fetch(setupUrl, { method: 'POST' })
if (!response.ok) {
console.error('Failed to seed database:', response.status, response.statusText)
console.error('[setup] Failed to seed database:', response.status, response.statusText)
} else {
console.log('Database seeded successfully')
console.log('[setup] Database seeded successfully')
}
} catch (error) {
console.error('Failed to call setup endpoint:', error)
console.warn('[setup] Setup endpoint not available (non-fatal):', (error as Error).message)
}
}

18
e2e/global.teardown.ts Normal file
View File

@@ -0,0 +1,18 @@
/**
* Playwright global teardown
* Stops the Testcontainers smoke stack started in global.setup.ts
*/
async function globalTeardown() {
const environment = (globalThis as Record<string, unknown>).__TESTCONTAINERS_ENV__ as
| { down: () => Promise<void> }
| undefined
if (environment) {
console.log('[teardown] Stopping smoke stack...')
await environment.down()
console.log('[teardown] Smoke stack stopped')
}
}
export default globalTeardown

View File

@@ -15,6 +15,8 @@ const baseURL = process.env.PLAYWRIGHT_BASE_URL ?? 'http://localhost:3000/workfl
export default defineConfig({
testDir: './',
testMatch: '**/*.spec.ts',
globalSetup: './global.setup.ts',
globalTeardown: './global.teardown.ts',
fullyParallel: true,
forbidOnly: !!process.env.CI,
retries: process.env.CI ? 2 : 0,
@@ -26,10 +28,13 @@ export default defineConfig({
screenshot: 'only-on-failure',
},
/* Start dev servers automatically when not running against a live Docker stack */
/* Start dev servers automatically when not running against a live Docker stack.
* In CI the smoke stack's nginx (in Docker) proxies to the host dev servers via
* host.docker.internal. On Linux this resolves to the Docker bridge gateway IP
* (e.g. 172.17.0.1), NOT 127.0.0.1 — so dev servers MUST listen on 0.0.0.0. */
webServer: process.env.PLAYWRIGHT_BASE_URL ? undefined : [
{
command: 'npm run dev -w workflowui',
command: `npm run dev -w workflowui -- --hostname ${process.env.CI ? '0.0.0.0' : 'localhost'}`,
url: 'http://localhost:3000/workflowui/',
reuseExistingServer: !process.env.CI,
timeout: 120_000,
@@ -41,7 +46,7 @@ export default defineConfig({
},
},
{
command: 'PORT=3001 npm run dev -w codesnippet',
command: `PORT=3001 npm run dev -w codesnippet -- --hostname ${process.env.CI ? '0.0.0.0' : 'localhost'}`,
url: 'http://localhost:3001/pastebin/',
reuseExistingServer: !process.env.CI,
timeout: 120_000,

View File

@@ -189,7 +189,7 @@ export class MultiTenantContextBuilder {
triggerData: requestData?.triggerData ?? {},
variables: this.buildVariables(requestData?.variables),
secrets: requestData?.secrets ?? {},
request: this.options.captureRequestData === true ? requestData?.request as WorkflowContext['request'] : undefined,
request: this.options.captureRequestData ? requestData?.request as WorkflowContext['request'] : undefined,
multiTenant: multiTenantMeta,
requestMetadata: {
ipAddress: this.requestContext.ipAddress,
@@ -205,7 +205,7 @@ export class MultiTenantContextBuilder {
this.validateContextSafety(context)
// 5. Load and bind credentials
if (this.options.enforceCredentialValidation === true) {
if (this.options.enforceCredentialValidation) {
this.bindCredentials(context)
}
@@ -213,7 +213,7 @@ export class MultiTenantContextBuilder {
this.validateVariableTenantIsolation(context)
// 7. Log context creation (audit)
if (this.options.enableAuditLogging === true) {
if (this.options.enableAuditLogging) {
this.logContextCreation(context)
}
@@ -231,7 +231,7 @@ export class MultiTenantContextBuilder {
// Super-admin (level 4) can access any tenant
if (this.requestContext.userLevel >= 4) {
if (this.options.allowCrossTenantAccess !== true) {
if (!this.options.allowCrossTenantAccess) {
throw new Error(
`Cross-tenant access disabled: User ${this.requestContext.userId} ` +
`cannot access workflow in tenant ${this.workflow.tenantId}`
@@ -366,7 +366,7 @@ export class MultiTenantContextBuilder {
const errors: string[] = []
// 1. Tenant ID must match (unless cross-tenant access is explicitly allowed)
if (context.tenantId !== this.workflow.tenantId && this.options.allowCrossTenantAccess !== true) {
if (context.tenantId !== this.workflow.tenantId && !this.options.allowCrossTenantAccess) {
errors.push(
`Context tenant ${context.tenantId} does not match ` +
`workflow tenant ${this.workflow.tenantId}`
@@ -540,7 +540,7 @@ export class MultiTenantContextBuilder {
// 5. Check credentials
const credentialCount = this.workflow.credentials.length
if (this.options.enforceCredentialValidation === true && credentialCount > 0) {
if (this.options.enforceCredentialValidation && credentialCount > 0) {
warnings.push({
path: 'credentials',
message: `${String(credentialCount)} credential(s) will be validated during execution`,

View File

@@ -35,7 +35,8 @@
"eslint-plugin-react-refresh": "^0.5.0",
"jest": "^30.2.0",
"jsdom": "^28.1.0",
"npm-run-all2": "8.0.4"
"npm-run-all2": "8.0.4",
"testcontainers": "^11.12.0"
},
"dependencies": {
"@hookform/resolvers": "^5.2.2",