@gfdelarue/testkit 0.4.4 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +752 -462
- package/bin/testkit-windows-owner-arm64.exe +0 -0
- package/bin/testkit-windows-owner-x64.exe +0 -0
- package/dist/app/bugs/categories.js +1 -1
- package/dist/app/bugs/ci-report.js +2 -2
- package/dist/app/bugs/ci-summary.js +3 -3
- package/dist/app/bugs/draft.js +4 -4
- package/dist/app/bugs/facts.js +2 -2
- package/dist/app/bugs/file.js +1 -1
- package/dist/app/bugs/gate.js +1 -1
- package/dist/app/bugs/guide.js +3 -3
- package/dist/app/bugs/issue.js +4 -4
- package/dist/app/bugs/known-failures.js +1 -1
- package/dist/app/bugs/record.js +2 -2
- package/dist/app/bugs/run-reading.js +1 -1
- package/dist/app/bugs/supplied-reproduce.js +1 -0
- package/dist/app/campaigns/campaign.js +1 -1
- package/dist/app/cleanup/index.js +1 -1
- package/dist/app/db-schema/prepare.js +1 -1
- package/dist/app/destroy/index.js +1 -1
- package/dist/app/discover/index.js +2 -2
- package/dist/app/doctor/index.js +1 -1
- package/dist/app/environments/config-driven.js +1 -0
- package/dist/app/environments/environment-file.js +1 -0
- package/dist/app/environments/file-setup.js +1 -0
- package/dist/app/environments/routing.js +1 -0
- package/dist/app/environments/static-values.js +1 -0
- package/dist/app/environments/supplied-input.js +1 -0
- package/dist/app/environments/supplied.js +1 -0
- package/dist/app/environments/task-databases.js +2 -0
- package/dist/app/file-selection.js +1 -1
- package/dist/app/inspect/artifacts.js +1 -1
- package/dist/app/inspect/index.js +1 -1
- package/dist/app/lint/index.js +1 -1
- package/dist/app/lint/native.js +1 -1
- package/dist/app/lint/options.js +1 -1
- package/dist/app/lint/rules/data.js +1 -1
- package/dist/app/lint/rules/engine-imports.js +1 -1
- package/dist/app/lint/rules/syntax.js +1 -1
- package/dist/app/lint/rules/unit.js +1 -1
- package/dist/app/lint/shared.js +1 -1
- package/dist/app/package-inspection.js +1 -1
- package/dist/app/reports/files.js +1 -0
- package/dist/app/reports/prepare.js +2 -0
- package/dist/app/reports/publish.js +1 -0
- package/dist/app/run/caller-redaction.js +1 -0
- package/dist/app/run/engine-evidence-persistence.js +1 -1
- package/dist/app/run/engine-execution-failures.js +1 -1
- package/dist/app/run/engine-execution-reporting.js +1 -1
- package/dist/app/run/engine-execution.js +1 -1
- package/dist/app/run/engine-orchestration.js +1 -1
- package/dist/app/run/environment.js +1 -0
- package/dist/app/run/failure-details.js +1 -1
- package/dist/app/run/live-run.js +1 -1
- package/dist/app/run/orchestrator.js +1 -1
- package/dist/app/run/planning.js +1 -1
- package/dist/app/run/request.js +1 -1
- package/dist/app/run/results.js +1 -1
- package/dist/app/run/run-events.js +1 -1
- package/dist/app/run/run-finalization.js +1 -1
- package/dist/app/run/runtime-fixtures.js +1 -1
- package/dist/app/run/scheduler/estimates.js +1 -1
- package/dist/app/run/scheduler/identity.js +1 -1
- package/dist/app/run/scheduler/index.js +1 -1
- package/dist/app/run/scheduler/locks.js +1 -0
- package/dist/app/run/selection.js +1 -1
- package/dist/app/run/setup/runtime-node-setup-protocol.js +1 -1
- package/dist/app/run/setup/runtime-node-setup-worker.js +1 -1
- package/dist/app/run/setup/runtime-node-setup.js +2 -2
- package/dist/app/run/task-batches.js +1 -1
- package/dist/app/run/task-leases.js +1 -0
- package/dist/app/run/worker-loop.js +1 -1
- package/dist/app/status/runs.js +1 -1
- package/dist/app/tracker/index.js +1 -1
- package/dist/app/typecheck/index.js +4 -4
- package/dist/cli/command-catalog.js +1 -1
- package/dist/cli/command-flags.js +1 -1
- package/dist/cli/command-registry.js +1 -1
- package/dist/cli/commands/artifacts.js +2 -2
- package/dist/cli/commands/bug/file.js +2 -2
- package/dist/cli/commands/bug/record.js +2 -2
- package/dist/cli/commands/discover.js +1 -1
- package/dist/cli/commands/report/prepare.js +5 -0
- package/dist/cli/commands/report/publish.js +2 -0
- package/dist/cli/commands/run.js +2 -2
- package/dist/cli/commands/typecheck.js +1 -1
- package/dist/cli/commands/workspace.js +1 -1
- package/dist/cli/framework/errors.js +1 -1
- package/dist/cli/framework/execute.js +7 -6
- package/dist/cli/framework/parser.js +1 -1
- package/dist/cli/json-errors.js +1 -1
- package/dist/cli/operations/run/operation.js +2 -2
- package/dist/cli/renderers/bug/text.js +1 -1
- package/dist/cli/renderers/discover/report.js +1 -1
- package/dist/cli/renderers/doctor/text.js +1 -1
- package/dist/cli/renderers/run/events.js +2 -2
- package/dist/cli/renderers/run/formatting.js +1 -1
- package/dist/cli/renderers/run/status.js +1 -1
- package/dist/cli/renderers/run/text-reporter.js +24 -22
- package/dist/cli/terminal/colors.js +1 -1
- package/dist/cli/terminal/layout.js +2 -2
- package/dist/config/authoring/http-methods.js +1 -1
- package/dist/config/authoring/index.js +1 -1
- package/dist/config/authoring/preset-env.js +1 -1
- package/dist/config/loader/config-loader.js +1 -1
- package/dist/config/loader/database.js +1 -1
- package/dist/config/loader/decode-execution.js +1 -1
- package/dist/config/loader/dependencies.js +1 -1
- package/dist/config/loader/discover-tests.js +1 -1
- package/dist/config/loader/discovery-summary.js +1 -1
- package/dist/config/loader/discovery.js +2 -2
- package/dist/config/loader/env.js +1 -1
- package/dist/config/loader/execution-model.js +1 -1
- package/dist/config/loader/file-metadata.js +1 -1
- package/dist/config/loader/groups.js +1 -0
- package/dist/config/loader/index.js +1 -1
- package/dist/config/loader/load.js +1 -1
- package/dist/config/loader/managed-configs.js +1 -1
- package/dist/config/loader/owned-discovery.js +1 -0
- package/dist/config/loader/path-policy.js +1 -1
- package/dist/config/loader/runtime-isolation.js +1 -1
- package/dist/config/loader/runtime.js +1 -1
- package/dist/config/loader/skip-config.js +1 -1
- package/dist/config/loader/task-policy.js +1 -0
- package/dist/config/loader/test-selection.js +1 -1
- package/dist/config/loader/validation.js +1 -1
- package/dist/database/activity-gate.js +1 -1
- package/dist/database/admin.js +2 -2
- package/dist/database/bindings.js +1 -0
- package/dist/database/cleanup.js +1 -1
- package/dist/database/docker-metadata.js +3 -3
- package/dist/database/docker.js +3 -3
- package/dist/database/index.js +1 -1
- package/dist/database/lifecycle-cleanup.js +1 -1
- package/dist/database/local-postgres.js +1 -1
- package/dist/database/naming.js +1 -1
- package/dist/database/postgres/connection-check.js +1 -0
- package/dist/database/postgres/protocol.js +2 -0
- package/dist/database/schema-operations.js +1 -1
- package/dist/database/schema-source.js +3 -3
- package/dist/database/source-schema-env.js +1 -0
- package/dist/database/source-url.js +2 -2
- package/dist/database/state-files.js +1 -1
- package/dist/database/state.js +1 -1
- package/dist/database/steps.js +3 -3
- package/dist/domain/file-timeout.js +1 -1
- package/dist/domain/identifiers.js +1 -1
- package/dist/domain/operation-display.js +1 -1
- package/dist/domain/retired-test-types.js +1 -0
- package/dist/domain/runtime-isolation-contract.js +1 -1
- package/dist/domain/suite-selection.js +1 -1
- package/dist/domain/test-outcomes.js +1 -1
- package/dist/domain/test-types.js +1 -1
- package/dist/engines/adapters/evidence-files.js +1 -1
- package/dist/engines/adapters/evidence-identity.js +1 -1
- package/dist/engines/adapters/execution.js +1 -1
- package/dist/engines/adapters/json-bounds.js +2 -0
- package/dist/engines/adapters/native-report.js +1 -1
- package/dist/engines/api/execution-scope.js +1 -1
- package/dist/engines/api/execution.js +1 -1
- package/dist/engines/api/index.js +1 -1
- package/dist/engines/api/runtime-artifact.js +1 -1
- package/dist/engines/bundle-cache.js +1 -1
- package/dist/engines/catalog.js +1 -1
- package/dist/engines/contracts/environment-values.js +1 -0
- package/dist/engines/contracts/fixture-manifest.js +1 -1
- package/dist/engines/definitions.js +1 -1
- package/dist/engines/environment/handles.js +1 -0
- package/dist/engines/environment/index.js +1 -0
- package/dist/engines/factory.js +1 -1
- package/dist/engines/installations/node-vitest.js +1 -1
- package/dist/engines/installations/package-resolution.js +1 -1
- package/dist/engines/installations/playwright-resolution-child.js +1 -1
- package/dist/engines/installations/playwright.js +1 -1
- package/dist/engines/managed-module-resolution-policy-input.js +1 -1
- package/dist/engines/managed-module-resolution-policy.js +1 -1
- package/dist/engines/managed-module-resolution.js +2 -2
- package/dist/engines/manager.js +1 -1
- package/dist/engines/node-vitest/adapter/adapter.js +1 -1
- package/dist/engines/node-vitest/adapter/driver.js +2 -0
- package/dist/engines/node-vitest/adapter/evidence.js +2 -2
- package/dist/engines/node-vitest/adapter/failure-details.js +4 -2
- package/dist/engines/node-vitest/adapter/reporter.js +1 -1
- package/dist/engines/node-vitest/adapter/workspace.js +31 -192
- package/dist/engines/node-vitest/inventory/index.js +2 -0
- package/dist/engines/node-vitest/inventory/list-files.js +3 -0
- package/dist/engines/node-vitest/runtime/contract/index.js +1 -1
- package/dist/engines/node-vitest/runtime/data/http.js +1 -1
- package/dist/engines/node-vitest/runtime/data/index.js +1 -1
- package/dist/engines/node-vitest/runtime/data/report.js +5 -6
- package/dist/engines/node-vitest/runtime/data/scenario.js +2 -2
- package/dist/engines/node-vitest/runtime/runtime-input.js +1 -1
- package/dist/engines/node-vitest/selection.js +1 -0
- package/dist/engines/playwright/adapter/adapter.js +1 -1
- package/dist/engines/playwright/adapter/config.js +4 -4
- package/dist/engines/playwright/adapter/evidence-validation.js +1 -1
- package/dist/engines/playwright/adapter/evidence.js +1 -1
- package/dist/engines/playwright/adapter/reporter.js +1 -1
- package/dist/engines/playwright/runtime/config-file.js +1 -1
- package/dist/engines/playwright/runtime/config.js +1 -1
- package/dist/engines/playwright/runtime/runtime-input.js +43 -20
- package/dist/engines/runtime-input-file.js +1 -1
- package/dist/environment/lifecycle-artifacts.js +1 -1
- package/dist/environment/lifecycle-controller.js +1 -1
- package/dist/environment/lifecycle.js +1 -1
- package/dist/environment/ports.js +1 -0
- package/dist/environment/ready-environment.js +1 -1
- package/dist/environment/run-environment.js +1 -1
- package/dist/environment/run-stopping.js +1 -1
- package/dist/environment/runtime-contexts.js +1 -1
- package/dist/environment/runtime-manager.js +1 -1
- package/dist/environment/runtime-planning.js +1 -1
- package/dist/environment/runtime-preparation.js +1 -1
- package/dist/environment/services.js +3 -1
- package/dist/environment/state.js +1 -1
- package/dist/environment/template.js +1 -1
- package/dist/evidence/artifact-config.js +1 -1
- package/dist/evidence/artifact-validation.js +1 -1
- package/dist/evidence/artifacts.js +2 -2
- package/dist/evidence/bundles.js +1 -1
- package/dist/evidence/environment-record.js +1 -0
- package/dist/evidence/index.js +1 -1
- package/dist/evidence/logs.js +2 -2
- package/dist/evidence/operation-timings.js +1 -1
- package/dist/evidence/read-fields.js +1 -1
- package/dist/evidence/read-run.js +1 -1
- package/dist/evidence/reading.js +1 -1
- package/dist/evidence/redaction.js +4 -0
- package/dist/evidence/reporting.js +1 -1
- package/dist/evidence/run-model.js +1 -0
- package/dist/evidence/storage.js +2 -2
- package/dist/evidence/timing.js +1 -1
- package/dist/kernel/error-serialization.js +1 -1
- package/dist/kernel/redaction-targets.js +1 -0
- package/dist/kernel/redaction.js +4 -1
- package/dist/kernel/unknown-values.js +1 -1
- package/dist/process/environment.js +1 -1
- package/dist/process/execa-bundle.json +3 -3
- package/dist/process/files/json-file.js +1 -1
- package/dist/process/files/paths.js +1 -1
- package/dist/process/host/metadata.js +1 -1
- package/dist/process/host/platform.js +1 -1
- package/dist/process/host-process.js +1 -1
- package/dist/process/index.js +1 -1
- package/dist/process/lifecycle-fence.js +1 -1
- package/dist/process/locks.js +4 -4
- package/dist/process/port-listener.js +2 -0
- package/dist/process/process-group.js +1 -1
- package/dist/process/process-identity.js +1 -1
- package/dist/process/process.js +33 -33
- package/dist/process/readiness.js +1 -1
- package/dist/process/ready-deadline.js +1 -0
- package/dist/process/recovery.js +1 -1
- package/dist/process/runs/manifest.js +1 -1
- package/dist/process/runs/ownership.js +1 -1
- package/dist/process/runs/product-state.js +1 -1
- package/dist/process/runs/stop.js +1 -1
- package/dist/process/service-processes.js +1 -1
- package/dist/process/stoppable-settlement.js +1 -0
- package/dist/process/url-redaction.js +1 -0
- package/dist/process/windows-cli-owner.js +3 -3
- package/dist/process/windows-native.js +1 -1
- package/dist/repo/ci-environment.js +1 -1
- package/dist/repo/fingerprint-policy.js +1 -1
- package/dist/repo/managed-git.js +1 -1
- package/dist/repo/physical-tree.js +1 -1
- package/dist/repo/publish-directory.js +3 -0
- package/dist/repo/state.js +4 -4
- package/dist/steps/build-config.js +1 -1
- package/dist/steps/configured-step-testkit-modules.js +1 -1
- package/dist/steps/configured-steps.js +1 -1
- package/dist/steps/environment.js +1 -1
- package/dist/steps/index.js +1 -1
- package/dist/steps/run.js +2 -2
- package/dist/toolchains/archive.js +1 -1
- package/dist/toolchains/index.js +3 -3
- package/dist/toolchains/node-provisioning.js +2 -2
- package/dist/toolchains/semver.js +1 -1
- package/dist/toolchains/vitest/index.js +1 -1
- package/dist/tracker/redaction.js +1 -2
- package/dist/{config/runtime/build-assets.d.ts → types/config-build-assets.d.ts} +5 -3
- package/dist/{database/steps.d.ts → types/config-database-steps.d.ts} +7 -7
- package/dist/{config/runtime/next-runtime-tsconfig.d.ts → types/config-next-runtime-tsconfig.d.ts} +5 -3
- package/dist/types/config.d.ts +501 -0
- package/dist/types/drizzle.d.ts +13 -0
- package/dist/{config/runtime/env/index.d.ts → types/env.d.ts} +22 -20
- package/dist/types/environment.d.ts +40 -0
- package/dist/types/index.d.ts +21 -0
- package/dist/types/node-vitest-contract.d.ts +75 -0
- package/dist/types/node-vitest-data.d.ts +407 -0
- package/dist/types/playwright.d.ts +130 -0
- package/dist/types/tooling-vitest.d.ts +13 -0
- package/dist/types/workspace.d.ts +617 -0
- package/docs/bug-records.md +83 -81
- package/docs/engines.md +213 -0
- package/docs/test-types.md +35 -33
- package/package.json +22 -29
- package/testkit-config-schema.md +403 -171
- package/dist/app/bugs/areas.d.ts +0 -38
- package/dist/app/bugs/assessment.d.ts +0 -9
- package/dist/app/bugs/categories.d.ts +0 -41
- package/dist/app/bugs/ci-report.d.ts +0 -21
- package/dist/app/bugs/ci-summary.d.ts +0 -13
- package/dist/app/bugs/draft.d.ts +0 -70
- package/dist/app/bugs/facts.d.ts +0 -48
- package/dist/app/bugs/file.d.ts +0 -45
- package/dist/app/bugs/gate.d.ts +0 -22
- package/dist/app/bugs/guide.d.ts +0 -20
- package/dist/app/bugs/issue.d.ts +0 -18
- package/dist/app/bugs/known-failures.d.ts +0 -49
- package/dist/app/bugs/record.d.ts +0 -14
- package/dist/app/bugs/run-reading.d.ts +0 -51
- package/dist/app/bugs/store.d.ts +0 -34
- package/dist/app/campaigns/brief.d.ts +0 -7
- package/dist/app/campaigns/campaign.d.ts +0 -14
- package/dist/app/campaigns/index.d.ts +0 -38
- package/dist/app/campaigns/store.d.ts +0 -5
- package/dist/app/campaigns/summary.d.ts +0 -13
- package/dist/app/cleanup/index.d.ts +0 -52
- package/dist/app/db-schema/prepare.d.ts +0 -11
- package/dist/app/db-schema/refresh.d.ts +0 -17
- package/dist/app/db-schema/verify.d.ts +0 -11
- package/dist/app/destroy/index.d.ts +0 -16
- package/dist/app/discover/index.d.ts +0 -8
- package/dist/app/doctor/index.d.ts +0 -17
- package/dist/app/file-selection.d.ts +0 -1
- package/dist/app/inspect/artifacts.d.ts +0 -30
- package/dist/app/inspect/index.d.ts +0 -112
- package/dist/app/lint/index.d.ts +0 -28
- package/dist/app/lint/native.d.ts +0 -10
- package/dist/app/lint/options.d.ts +0 -67
- package/dist/app/lint/policy.d.ts +0 -21
- package/dist/app/lint/rules/data.d.ts +0 -3
- package/dist/app/lint/rules/engine-imports.d.ts +0 -3
- package/dist/app/lint/rules/syntax.d.ts +0 -4
- package/dist/app/lint/rules/unit.d.ts +0 -3
- package/dist/app/lint/shared.d.ts +0 -36
- package/dist/app/package-inspection.d.ts +0 -20
- package/dist/app/run/endpoint-readiness.d.ts +0 -43
- package/dist/app/run/endpoint-readiness.js +0 -1
- package/dist/app/run/engine-evidence-persistence.d.ts +0 -39
- package/dist/app/run/engine-execution-cleanup.d.ts +0 -8
- package/dist/app/run/engine-execution-cleanup.js +0 -1
- package/dist/app/run/engine-execution-failures.d.ts +0 -41
- package/dist/app/run/engine-execution-observer.d.ts +0 -21
- package/dist/app/run/engine-execution-reporting.d.ts +0 -17
- package/dist/app/run/engine-execution.d.ts +0 -63
- package/dist/app/run/engine-failure-stack.d.ts +0 -1
- package/dist/app/run/engine-orchestration.d.ts +0 -49
- package/dist/app/run/failure-details.d.ts +0 -37
- package/dist/app/run/live-run.d.ts +0 -27
- package/dist/app/run/operation-progress.d.ts +0 -13
- package/dist/app/run/orchestrator.d.ts +0 -68
- package/dist/app/run/planning-types.d.ts +0 -68
- package/dist/app/run/planning.d.ts +0 -15
- package/dist/app/run/playwright-configuration.d.ts +0 -2
- package/dist/app/run/playwright-configuration.js +0 -1
- package/dist/app/run/request.d.ts +0 -30
- package/dist/app/run/results.d.ts +0 -161
- package/dist/app/run/run-events.d.ts +0 -144
- package/dist/app/run/run-finalization.d.ts +0 -52
- package/dist/app/run/run-guards.d.ts +0 -3
- package/dist/app/run/runtime-failures.d.ts +0 -18
- package/dist/app/run/runtime-fixtures.d.ts +0 -2
- package/dist/app/run/runtime-task-types.d.ts +0 -20
- package/dist/app/run/scheduler/estimates.d.ts +0 -32
- package/dist/app/run/scheduler/identity.d.ts +0 -9
- package/dist/app/run/scheduler/index.d.ts +0 -124
- package/dist/app/run/scheduler/observations.d.ts +0 -20
- package/dist/app/run/selection.d.ts +0 -10
- package/dist/app/run/setup/runtime-node-setup-errors.d.ts +0 -13
- package/dist/app/run/setup/runtime-node-setup-protocol.d.ts +0 -85
- package/dist/app/run/setup/runtime-node-setup-worker.d.ts +0 -1
- package/dist/app/run/setup/runtime-node-setup.d.ts +0 -48
- package/dist/app/run/task-batches.d.ts +0 -23
- package/dist/app/run/worker-loop.d.ts +0 -57
- package/dist/app/setup/playwright.d.ts +0 -22
- package/dist/app/status/index.d.ts +0 -9
- package/dist/app/status/model.d.ts +0 -29
- package/dist/app/status/runs.d.ts +0 -99
- package/dist/app/stop/index.d.ts +0 -14
- package/dist/app/tracker/index.d.ts +0 -8
- package/dist/app/tracker/remote.d.ts +0 -13
- package/dist/app/tracker/token.d.ts +0 -7
- package/dist/app/typecheck/index.d.ts +0 -63
- package/dist/cli/command-catalog.d.ts +0 -137
- package/dist/cli/command-flags.d.ts +0 -19
- package/dist/cli/command-registry.d.ts +0 -3
- package/dist/cli/commands/artifacts.d.ts +0 -48
- package/dist/cli/commands/bug/file.d.ts +0 -16
- package/dist/cli/commands/bug/guide.d.ts +0 -5
- package/dist/cli/commands/bug/record.d.ts +0 -9
- package/dist/cli/commands/campaign/finish.d.ts +0 -10
- package/dist/cli/commands/campaign/start.d.ts +0 -7
- package/dist/cli/commands/campaign/status.d.ts +0 -13
- package/dist/cli/commands/ci/report.d.ts +0 -15
- package/dist/cli/commands/cleanup.d.ts +0 -13
- package/dist/cli/commands/db/schema/refresh.d.ts +0 -2
- package/dist/cli/commands/db/schema/verify.d.ts +0 -2
- package/dist/cli/commands/destroy.d.ts +0 -9
- package/dist/cli/commands/discover.d.ts +0 -2
- package/dist/cli/commands/doctor.d.ts +0 -2
- package/dist/cli/commands/guard/unsafe-entrypoint.d.ts +0 -2
- package/dist/cli/commands/lint.d.ts +0 -2
- package/dist/cli/commands/run/status.d.ts +0 -5
- package/dist/cli/commands/run/stop.d.ts +0 -7
- package/dist/cli/commands/run.d.ts +0 -9
- package/dist/cli/commands/setup/playwright.d.ts +0 -2
- package/dist/cli/commands/status.d.ts +0 -5
- package/dist/cli/commands/stop.d.ts +0 -12
- package/dist/cli/commands/typecheck.d.ts +0 -2
- package/dist/cli/commands/workspace.d.ts +0 -2
- package/dist/cli/entrypoint.d.ts +0 -1
- package/dist/cli/framework/command.d.ts +0 -21
- package/dist/cli/framework/definitions.d.ts +0 -100
- package/dist/cli/framework/errors.d.ts +0 -6
- package/dist/cli/framework/execute.d.ts +0 -14
- package/dist/cli/framework/help.d.ts +0 -11
- package/dist/cli/framework/index.d.ts +0 -3
- package/dist/cli/framework/parser.d.ts +0 -6
- package/dist/cli/index.d.ts +0 -4
- package/dist/cli/json-errors.d.ts +0 -3
- package/dist/cli/operations/db/schema/refresh/operation.d.ts +0 -7
- package/dist/cli/operations/db/schema/verify/operation.d.ts +0 -7
- package/dist/cli/operations/run/operation.d.ts +0 -24
- package/dist/cli/process-signal.d.ts +0 -1
- package/dist/cli/renderers/bug/text.d.ts +0 -8
- package/dist/cli/renderers/campaign/text.d.ts +0 -2
- package/dist/cli/renderers/ci/text.d.ts +0 -2
- package/dist/cli/renderers/cleanup/format.d.ts +0 -14
- package/dist/cli/renderers/db-schema/text.d.ts +0 -4
- package/dist/cli/renderers/destroy/text.d.ts +0 -4
- package/dist/cli/renderers/discover/report.d.ts +0 -7
- package/dist/cli/renderers/discover/text.d.ts +0 -3
- package/dist/cli/renderers/doctor/text.d.ts +0 -2
- package/dist/cli/renderers/lint/text.d.ts +0 -2
- package/dist/cli/renderers/run/events.d.ts +0 -8
- package/dist/cli/renderers/run/failure.d.ts +0 -8
- package/dist/cli/renderers/run/formatting.d.ts +0 -79
- package/dist/cli/renderers/run/status.d.ts +0 -6
- package/dist/cli/renderers/run/text-reporter.d.ts +0 -19
- package/dist/cli/renderers/status/text.d.ts +0 -2
- package/dist/cli/renderers/stop/text.d.ts +0 -7
- package/dist/cli/renderers/typecheck/text.d.ts +0 -2
- package/dist/cli/terminal/colors.d.ts +0 -10
- package/dist/cli/terminal/layout.d.ts +0 -11
- package/dist/cli/version-drift.d.ts +0 -25
- package/dist/config/authoring/build-config-contract.d.ts +0 -27
- package/dist/config/authoring/configured-step-contract.d.ts +0 -18
- package/dist/config/authoring/http-execution-contract.d.ts +0 -70
- package/dist/config/authoring/http-methods.d.ts +0 -18
- package/dist/config/authoring/index.d.ts +0 -381
- package/dist/config/authoring/preset-env.d.ts +0 -19
- package/dist/config/authoring/runtime.d.ts +0 -64
- package/dist/config/loader/bugs.d.ts +0 -15
- package/dist/config/loader/config-loader.d.ts +0 -9
- package/dist/config/loader/database-materialization.d.ts +0 -19
- package/dist/config/loader/database-roles.d.ts +0 -2
- package/dist/config/loader/database.d.ts +0 -55
- package/dist/config/loader/decode-discovery.d.ts +0 -5
- package/dist/config/loader/decode-execution.d.ts +0 -9
- package/dist/config/loader/dependencies.d.ts +0 -7
- package/dist/config/loader/discover-tests.d.ts +0 -111
- package/dist/config/loader/discovery-summary.d.ts +0 -29
- package/dist/config/loader/discovery.d.ts +0 -54
- package/dist/config/loader/env.d.ts +0 -4
- package/dist/config/loader/execution-model.d.ts +0 -16
- package/dist/config/loader/file-metadata.d.ts +0 -19
- package/dist/config/loader/index.d.ts +0 -10
- package/dist/config/loader/load.d.ts +0 -91
- package/dist/config/loader/managed-configs.d.ts +0 -23
- package/dist/config/loader/path-policy.d.ts +0 -9
- package/dist/config/loader/paths.d.ts +0 -5
- package/dist/config/loader/runtime-isolation.d.ts +0 -44
- package/dist/config/loader/runtime.d.ts +0 -25
- package/dist/config/loader/skip-config.d.ts +0 -44
- package/dist/config/loader/test-selection.d.ts +0 -15
- package/dist/config/loader/validation.d.ts +0 -16
- package/dist/config/loader/values.d.ts +0 -4
- package/dist/config/loader/values.js +0 -1
- package/dist/database/activity-gate.d.ts +0 -22
- package/dist/database/admin.d.ts +0 -31
- package/dist/database/cleanup.d.ts +0 -36
- package/dist/database/configured-steps.d.ts +0 -27
- package/dist/database/constants.d.ts +0 -11
- package/dist/database/docker-metadata.d.ts +0 -3
- package/dist/database/docker.d.ts +0 -65
- package/dist/database/drizzle/index.d.ts +0 -13
- package/dist/database/fingerprint.d.ts +0 -12
- package/dist/database/index.d.ts +0 -39
- package/dist/database/lifecycle-cleanup.d.ts +0 -7
- package/dist/database/local-postgres.d.ts +0 -71
- package/dist/database/naming.d.ts +0 -17
- package/dist/database/postgres/index.d.ts +0 -71
- package/dist/database/progress.d.ts +0 -6
- package/dist/database/roles.d.ts +0 -19
- package/dist/database/runtime-config.d.ts +0 -16
- package/dist/database/runtime-reservations.d.ts +0 -19
- package/dist/database/schema-operations.d.ts +0 -18
- package/dist/database/schema-source.d.ts +0 -96
- package/dist/database/source-refresh-lock.d.ts +0 -8
- package/dist/database/source-url.d.ts +0 -22
- package/dist/database/state-files.d.ts +0 -13
- package/dist/database/state.d.ts +0 -26
- package/dist/database/template-steps.d.ts +0 -39
- package/dist/domain/file-timeout.d.ts +0 -28
- package/dist/domain/identifiers.d.ts +0 -9
- package/dist/domain/operation-display.d.ts +0 -10
- package/dist/domain/operation-reason.d.ts +0 -5
- package/dist/domain/postgres-route.d.ts +0 -4
- package/dist/domain/runtime-identity.d.ts +0 -1
- package/dist/domain/runtime-isolation-contract.d.ts +0 -5
- package/dist/domain/service-name.d.ts +0 -2
- package/dist/domain/suite-selection.d.ts +0 -20
- package/dist/domain/test-outcomes.d.ts +0 -3
- package/dist/domain/test-types.d.ts +0 -16
- package/dist/engines/adapters/evidence-files.d.ts +0 -32
- package/dist/engines/adapters/evidence-identity.d.ts +0 -12
- package/dist/engines/adapters/execution.d.ts +0 -42
- package/dist/engines/adapters/native-report.d.ts +0 -25
- package/dist/engines/adapters/node-startup-cache.d.ts +0 -8
- package/dist/engines/adapters/workspace.d.ts +0 -4
- package/dist/engines/api/capabilities.d.ts +0 -31
- package/dist/engines/api/capabilities.js +0 -1
- package/dist/engines/api/evidence.d.ts +0 -38
- package/dist/engines/api/execution-observer.d.ts +0 -8
- package/dist/engines/api/execution-scope.d.ts +0 -17
- package/dist/engines/api/execution.d.ts +0 -101
- package/dist/engines/api/index.d.ts +0 -5
- package/dist/engines/api/k6-runtime-input.d.ts +0 -26
- package/dist/engines/api/k6-runtime-input.js +0 -1
- package/dist/engines/api/runtime-artifact.d.ts +0 -19
- package/dist/engines/bundle-cache.d.ts +0 -32
- package/dist/engines/catalog.d.ts +0 -27
- package/dist/engines/contracts/fixture-manifest.d.ts +0 -34
- package/dist/engines/contracts/json-bounds.d.ts +0 -36
- package/dist/engines/contracts/json-bounds.js +0 -2
- package/dist/engines/contracts/k6-repository-configuration.d.ts +0 -12
- package/dist/engines/contracts/k6-repository-configuration.js +0 -1
- package/dist/engines/contracts/test-context.d.ts +0 -15
- package/dist/engines/contracts/test-context.js +0 -1
- package/dist/engines/definitions.d.ts +0 -22
- package/dist/engines/factory.d.ts +0 -6
- package/dist/engines/generated-performance.d.ts +0 -1
- package/dist/engines/installation-catalog.d.ts +0 -27
- package/dist/engines/installation-catalog.js +0 -1
- package/dist/engines/installations/k6.d.ts +0 -98
- package/dist/engines/installations/k6.js +0 -1
- package/dist/engines/installations/node-vitest.d.ts +0 -33
- package/dist/engines/installations/package-requirements.d.ts +0 -28
- package/dist/engines/installations/package-resolution.d.ts +0 -51
- package/dist/engines/installations/playwright-resolution-child.d.ts +0 -1
- package/dist/engines/installations/playwright.d.ts +0 -75
- package/dist/engines/installations/types.d.ts +0 -10
- package/dist/engines/k6/adapter/bundle.d.ts +0 -25
- package/dist/engines/k6/adapter/bundle.js +0 -112
- package/dist/engines/k6/adapter/evidence.d.ts +0 -15
- package/dist/engines/k6/adapter/evidence.js +0 -4
- package/dist/engines/k6/adapter/executor.d.ts +0 -13
- package/dist/engines/k6/adapter/executor.js +0 -1
- package/dist/engines/k6/adapter/index.d.ts +0 -1
- package/dist/engines/k6/adapter/index.js +0 -1
- package/dist/engines/k6/adapter/input.d.ts +0 -21
- package/dist/engines/k6/adapter/input.js +0 -1
- package/dist/engines/k6/adapter/native-summary.d.ts +0 -11
- package/dist/engines/k6/adapter/native-summary.js +0 -1
- package/dist/engines/k6/adapter/repository-configuration.d.ts +0 -2
- package/dist/engines/k6/adapter/repository-configuration.js +0 -1
- package/dist/engines/k6/authoring-type-paths.d.ts +0 -3
- package/dist/engines/k6/authoring-type-paths.js +0 -1
- package/dist/engines/k6/runtime/ambient-types/bundle-manifest.json +0 -146
- package/dist/engines/k6/runtime/ambient-types/k6/LICENSE +0 -21
- package/dist/engines/k6/runtime/ambient-types/k6/browser/index.d.ts +0 -6332
- package/dist/engines/k6/runtime/ambient-types/k6/crypto/index.d.ts +0 -218
- package/dist/engines/k6/runtime/ambient-types/k6/data/index.d.ts +0 -16
- package/dist/engines/k6/runtime/ambient-types/k6/encoding/index.d.ts +0 -46
- package/dist/engines/k6/runtime/ambient-types/k6/execution/index.d.ts +0 -127
- package/dist/engines/k6/runtime/ambient-types/k6/experimental/csv/index.d.ts +0 -96
- package/dist/engines/k6/runtime/ambient-types/k6/experimental/fs/index.d.ts +0 -104
- package/dist/engines/k6/runtime/ambient-types/k6/experimental/redis/index.d.ts +0 -821
- package/dist/engines/k6/runtime/ambient-types/k6/experimental/streams/index.d.ts +0 -198
- package/dist/engines/k6/runtime/ambient-types/k6/global.d.ts +0 -83
- package/dist/engines/k6/runtime/ambient-types/k6/html/index.d.ts +0 -1325
- package/dist/engines/k6/runtime/ambient-types/k6/http/index.d.ts +0 -806
- package/dist/engines/k6/runtime/ambient-types/k6/index.d.ts +0 -126
- package/dist/engines/k6/runtime/ambient-types/k6/metrics/index.d.ts +0 -66
- package/dist/engines/k6/runtime/ambient-types/k6/net/grpc/index.d.ts +0 -247
- package/dist/engines/k6/runtime/ambient-types/k6/options/index.d.ts +0 -459
- package/dist/engines/k6/runtime/ambient-types/k6/package.json +0 -79
- package/dist/engines/k6/runtime/ambient-types/k6/secrets/index.d.ts +0 -36
- package/dist/engines/k6/runtime/ambient-types/k6/timers/index.d.ts +0 -47
- package/dist/engines/k6/runtime/ambient-types/k6/websockets/index.d.ts +0 -324
- package/dist/engines/k6/runtime/ambient-types/k6/ws/index.d.ts +0 -283
- package/dist/engines/k6/runtime/ambient-types/xk6-sql/LICENSE +0 -201
- package/dist/engines/k6/runtime/ambient-types/xk6-sql/index.d.ts +0 -397
- package/dist/engines/k6/runtime/ambient-types/xk6-sql/package.json +0 -15
- package/dist/engines/k6/runtime/artifacts.d.ts +0 -2
- package/dist/engines/k6/runtime/artifacts.js +0 -1
- package/dist/engines/k6/runtime/checks.d.ts +0 -17
- package/dist/engines/k6/runtime/checks.js +0 -1
- package/dist/engines/k6/runtime/dal-fixtures.d.ts +0 -24
- package/dist/engines/k6/runtime/dal-fixtures.js +0 -1
- package/dist/engines/k6/runtime/dal-suite.d.ts +0 -24
- package/dist/engines/k6/runtime/dal-suite.js +0 -1
- package/dist/engines/k6/runtime/dal.d.ts +0 -10
- package/dist/engines/k6/runtime/dal.js +0 -1
- package/dist/engines/k6/runtime/fixtures.d.ts +0 -3
- package/dist/engines/k6/runtime/fixtures.js +0 -1
- package/dist/engines/k6/runtime/http-assertions.d.ts +0 -19
- package/dist/engines/k6/runtime/http-assertions.js +0 -1
- package/dist/engines/k6/runtime/http-checks.d.ts +0 -19
- package/dist/engines/k6/runtime/http-checks.js +0 -1
- package/dist/engines/k6/runtime/http-suite-runtime.d.ts +0 -103
- package/dist/engines/k6/runtime/http-suite-runtime.js +0 -1
- package/dist/engines/k6/runtime/http.d.ts +0 -15
- package/dist/engines/k6/runtime/http.js +0 -1
- package/dist/engines/k6/runtime/index.d.ts +0 -11
- package/dist/engines/k6/runtime/index.js +0 -1
- package/dist/engines/k6/runtime/input.d.ts +0 -3
- package/dist/engines/k6/runtime/input.js +0 -1
- package/dist/engines/k6/runtime/k6-repository-configuration.d.ts +0 -9
- package/dist/engines/k6/runtime/k6-repository-configuration.js +0 -1
- package/dist/engines/k6/runtime/node-setup.d.ts +0 -13
- package/dist/engines/k6/runtime/node-setup.js +0 -1
- package/dist/engines/k6/runtime/runtime-globals.d.ts +0 -10
- package/dist/engines/k6/runtime/runtime.d.ts +0 -54
- package/dist/engines/k6/runtime/runtime.js +0 -1
- package/dist/engines/k6/runtime/shared/assertion-details.d.ts +0 -19
- package/dist/engines/k6/runtime/shared/assertion-details.js +0 -2
- package/dist/engines/k6/runtime/shared/db-normalization.d.ts +0 -19
- package/dist/engines/k6/runtime/shared/db-normalization.js +0 -1
- package/dist/engines/k6/runtime/shared/error-body.d.ts +0 -3
- package/dist/engines/k6/runtime/shared/error-body.js +0 -1
- package/dist/engines/k6/runtime/shared/file-data.d.ts +0 -1
- package/dist/engines/k6/runtime/shared/file-data.js +0 -1
- package/dist/engines/k6/runtime/shared/fixture-engine.d.ts +0 -8
- package/dist/engines/k6/runtime/shared/fixture-engine.js +0 -2
- package/dist/engines/k6/runtime/shared/http-check-plan.d.ts +0 -29
- package/dist/engines/k6/runtime/shared/http-check-plan.js +0 -1
- package/dist/engines/k6/runtime/shared/http-parsing.d.ts +0 -10
- package/dist/engines/k6/runtime/shared/http-parsing.js +0 -3
- package/dist/engines/k6/runtime/shared/ordering.d.ts +0 -2
- package/dist/engines/k6/runtime/shared/ordering.js +0 -1
- package/dist/engines/k6/runtime/shared/properties.d.ts +0 -1
- package/dist/engines/k6/runtime/shared/properties.js +0 -1
- package/dist/engines/k6/runtime/suite.d.ts +0 -4
- package/dist/engines/k6/runtime/suite.js +0 -1
- package/dist/engines/k6/runtime/types.d.ts +0 -244
- package/dist/engines/k6/runtime/types.js +0 -1
- package/dist/engines/k6/runtime/xk6-sql-driver-postgres.d.ts +0 -7
- package/dist/engines/k6/runtime/xk6-sql-driver-postgres.js +0 -1
- package/dist/engines/managed-module-resolution-policy-input.d.ts +0 -9
- package/dist/engines/managed-module-resolution-policy.d.ts +0 -25
- package/dist/engines/managed-module-resolution.d.ts +0 -13
- package/dist/engines/manager.d.ts +0 -25
- package/dist/engines/node-vitest/adapter/adapter.d.ts +0 -16
- package/dist/engines/node-vitest/adapter/consumer-typescript-paths.d.ts +0 -17
- package/dist/engines/node-vitest/adapter/consumer-typescript-paths.js +0 -3
- package/dist/engines/node-vitest/adapter/evidence.d.ts +0 -33
- package/dist/engines/node-vitest/adapter/failure-details.d.ts +0 -3
- package/dist/engines/node-vitest/adapter/index.d.ts +0 -1
- package/dist/engines/node-vitest/adapter/reporter.d.ts +0 -7
- package/dist/engines/node-vitest/adapter/resolution.d.ts +0 -12
- package/dist/engines/node-vitest/adapter/resolution.js +0 -1
- package/dist/engines/node-vitest/adapter/workspace.d.ts +0 -19
- package/dist/engines/node-vitest/runtime/contract/index.d.ts +0 -64
- package/dist/engines/node-vitest/runtime/data/http.d.ts +0 -4
- package/dist/engines/node-vitest/runtime/data/index.d.ts +0 -8
- package/dist/engines/node-vitest/runtime/data/primitives.d.ts +0 -1
- package/dist/engines/node-vitest/runtime/data/report.d.ts +0 -3
- package/dist/engines/node-vitest/runtime/data/runner.d.ts +0 -4
- package/dist/engines/node-vitest/runtime/data/scenario.d.ts +0 -12
- package/dist/engines/node-vitest/runtime/data/types.d.ts +0 -412
- package/dist/engines/node-vitest/runtime/runtime-input.d.ts +0 -64
- package/dist/engines/playwright/adapter/adapter.d.ts +0 -18
- package/dist/engines/playwright/adapter/attachments.d.ts +0 -26
- package/dist/engines/playwright/adapter/config.d.ts +0 -45
- package/dist/engines/playwright/adapter/evidence-validation.d.ts +0 -12
- package/dist/engines/playwright/adapter/evidence.d.ts +0 -32
- package/dist/engines/playwright/adapter/failure-details.d.ts +0 -2
- package/dist/engines/playwright/adapter/index.d.ts +0 -3
- package/dist/engines/playwright/adapter/reporter.d.ts +0 -12
- package/dist/engines/playwright/runtime/config-file.d.ts +0 -2
- package/dist/engines/playwright/runtime/config.d.ts +0 -24
- package/dist/engines/playwright/runtime/index.d.ts +0 -4
- package/dist/engines/playwright/runtime/runtime-input.d.ts +0 -36
- package/dist/engines/playwright/runtime/sandbox.d.ts +0 -84
- package/dist/engines/runtime-input-file.d.ts +0 -27
- package/dist/environment/lifecycle-artifacts.d.ts +0 -7
- package/dist/environment/lifecycle-controller.d.ts +0 -70
- package/dist/environment/lifecycle.d.ts +0 -29
- package/dist/environment/maintenance.d.ts +0 -68
- package/dist/environment/planning-types.d.ts +0 -35
- package/dist/environment/readiness.d.ts +0 -12
- package/dist/environment/readiness.js +0 -1
- package/dist/environment/ready-environment.d.ts +0 -19
- package/dist/environment/run-environment.d.ts +0 -38
- package/dist/environment/run-stopping.d.ts +0 -13
- package/dist/environment/runtime-contexts.d.ts +0 -33
- package/dist/environment/runtime-manager.d.ts +0 -95
- package/dist/environment/runtime-planning.d.ts +0 -16
- package/dist/environment/runtime-preparation.d.ts +0 -30
- package/dist/environment/runtime-service.d.ts +0 -18
- package/dist/environment/services.d.ts +0 -48
- package/dist/environment/state.d.ts +0 -18
- package/dist/environment/status-runtime.d.ts +0 -53
- package/dist/environment/template.d.ts +0 -180
- package/dist/evidence/artifact-config.d.ts +0 -14
- package/dist/evidence/artifact-validation.d.ts +0 -5
- package/dist/evidence/artifacts.d.ts +0 -75
- package/dist/evidence/bundles.d.ts +0 -27
- package/dist/evidence/ci-provenance.d.ts +0 -9
- package/dist/evidence/contracts.d.ts +0 -154
- package/dist/evidence/file-evidence.d.ts +0 -23
- package/dist/evidence/finalization.d.ts +0 -9
- package/dist/evidence/index.d.ts +0 -8
- package/dist/evidence/logs.d.ts +0 -31
- package/dist/evidence/operation-timings.d.ts +0 -60
- package/dist/evidence/read-bundle.d.ts +0 -4
- package/dist/evidence/read-fields.d.ts +0 -22
- package/dist/evidence/read-provenance.d.ts +0 -2
- package/dist/evidence/read-redaction.d.ts +0 -2
- package/dist/evidence/read-retention.d.ts +0 -2
- package/dist/evidence/read-run.d.ts +0 -2
- package/dist/evidence/reading.d.ts +0 -28
- package/dist/evidence/reporting-types.d.ts +0 -330
- package/dist/evidence/reporting.d.ts +0 -3
- package/dist/evidence/secure-file-copy.d.ts +0 -24
- package/dist/evidence/setup-progress.d.ts +0 -63
- package/dist/evidence/step-output.d.ts +0 -16
- package/dist/evidence/storage-inventory.d.ts +0 -27
- package/dist/evidence/storage.d.ts +0 -27
- package/dist/evidence/timing.d.ts +0 -23
- package/dist/file.d.ts +0 -11
- package/dist/index.d.ts +0 -4
- package/dist/kernel/error-serialization.d.ts +0 -38
- package/dist/kernel/redaction.d.ts +0 -2
- package/dist/kernel/unknown-values.d.ts +0 -6
- package/dist/kernel/work-metrics.d.ts +0 -6
- package/dist/process/capture-output.d.ts +0 -7
- package/dist/process/command-shell.d.ts +0 -1
- package/dist/process/environment-overlay.d.ts +0 -17
- package/dist/process/environment.d.ts +0 -33
- package/dist/process/files/contained-path.d.ts +0 -8
- package/dist/process/files/directory-status.d.ts +0 -14
- package/dist/process/files/dotenv.d.ts +0 -2
- package/dist/process/files/file-snapshot.d.ts +0 -34
- package/dist/process/files/json-file.d.ts +0 -12
- package/dist/process/files/paths.d.ts +0 -1
- package/dist/process/files/product-dir.d.ts +0 -1
- package/dist/process/files/temp-dir.d.ts +0 -11
- package/dist/process/host/metadata.d.ts +0 -6
- package/dist/process/host/platform.d.ts +0 -57
- package/dist/process/host-command.d.ts +0 -4
- package/dist/process/host-inspection-command.d.ts +0 -13
- package/dist/process/host-process.d.ts +0 -19
- package/dist/process/index.d.ts +0 -9
- package/dist/process/lifecycle-fence.d.ts +0 -11
- package/dist/process/locks.d.ts +0 -28
- package/dist/process/process-contracts.d.ts +0 -78
- package/dist/process/process-group.d.ts +0 -12
- package/dist/process/process-identity.d.ts +0 -27
- package/dist/process/process-limits.d.ts +0 -6
- package/dist/process/process.d.ts +0 -12
- package/dist/process/readiness.d.ts +0 -37
- package/dist/process/recovery.d.ts +0 -3
- package/dist/process/runs/inspection.d.ts +0 -5
- package/dist/process/runs/manifest.d.ts +0 -86
- package/dist/process/runs/ownership.d.ts +0 -11
- package/dist/process/runs/product-state.d.ts +0 -2
- package/dist/process/runs/schema.d.ts +0 -3
- package/dist/process/runs/stop.d.ts +0 -19
- package/dist/process/runtime-socket.d.ts +0 -4
- package/dist/process/service-processes.d.ts +0 -13
- package/dist/process/shutdown.d.ts +0 -10
- package/dist/process/windows-cli-owner.d.ts +0 -2
- package/dist/process/windows-native.d.ts +0 -6
- package/dist/process/windows-process-identity.d.ts +0 -4
- package/dist/repo/ci-environment.d.ts +0 -7
- package/dist/repo/fingerprint-policy.d.ts +0 -15
- package/dist/repo/git-path.d.ts +0 -2
- package/dist/repo/history.d.ts +0 -17
- package/dist/repo/managed-git.d.ts +0 -10
- package/dist/repo/metadata.d.ts +0 -3
- package/dist/repo/physical-tree.d.ts +0 -37
- package/dist/repo/remote.d.ts +0 -6
- package/dist/repo/state.d.ts +0 -26
- package/dist/repo/tree-listing.d.ts +0 -10
- package/dist/steps/build-config.d.ts +0 -35
- package/dist/steps/configured-step-testkit-modules.d.ts +0 -19
- package/dist/steps/configured-steps.d.ts +0 -51
- package/dist/steps/environment.d.ts +0 -84
- package/dist/steps/index.d.ts +0 -2
- package/dist/steps/module-runner.d.ts +0 -1
- package/dist/steps/run.d.ts +0 -36
- package/dist/toolchains/archive.d.ts +0 -53
- package/dist/toolchains/esbuild.d.ts +0 -9
- package/dist/toolchains/host-node-support.d.ts +0 -3
- package/dist/toolchains/index.d.ts +0 -114
- package/dist/toolchains/managed-node-releases.d.ts +0 -28
- package/dist/toolchains/node-cache.d.ts +0 -20
- package/dist/toolchains/node-integrity.d.ts +0 -18
- package/dist/toolchains/node-provisioning.d.ts +0 -29
- package/dist/toolchains/semver.d.ts +0 -13
- package/dist/toolchains/shared-operation.d.ts +0 -11
- package/dist/toolchains/timeouts.d.ts +0 -1
- package/dist/toolchains/vitest/index.d.ts +0 -13
- package/dist/tracker/gitea.d.ts +0 -14
- package/dist/tracker/github.d.ts +0 -14
- package/dist/tracker/http.d.ts +0 -33
- package/dist/tracker/index.d.ts +0 -4
- package/dist/tracker/redaction.d.ts +0 -4
- package/dist/tracker/requests.d.ts +0 -17
- package/dist/tracker/responses.d.ts +0 -24
- package/dist/tracker/types.d.ts +0 -51
- package/docs/engine-architecture.md +0 -654
- /package/dist/engines/{k6/runtime/runtime-globals.js → api/profiles.js} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
import{makeTempDirAsync as D}from"../../../process/files/temp-dir.js";import{classifyManagedProcessResult as F,terminalOutcome as T,processOutputEvidence as N,failureFromError as P,firstOutputLine as R,processExitDetails as
|
|
1
|
+
import{makeTempDirAsync as D}from"../../../process/files/temp-dir.js";import{toError as g}from"../../../kernel/error-serialization.js";import{classifyManagedProcessResult as F,terminalOutcome as T,processOutputEvidence as N,failureFromError as P,firstOutputLine as R,processExitDetails as b,processExitFailure as C,executeEngineTasks as x,managedProcessFailure as M,emptyEvidence as W,taskTimeoutFailure as U}from"../../adapters/execution.js";import{requireRootDirectory as B,requireAbsoluteWorkspacePath as O,requireConsumerFile as Y,safeSegment as S}from"../../adapters/workspace.js";import u from"node:fs/promises";import H from"node:path";import{setTimeout as $}from"node:timers/promises";import{pathToFileURL as K}from"node:url";import{isEngineTaskDeadlineExceededReason as G,resolveEngineTaskInputs as V}from"../../api/index.js";import{createNativeInvocationProcessEnvironment as j,runManagedProcess as J}from"../../../process/index.js";import{PlaywrightConsumerConfigurationError as z,playwrightExactFileFilter as X,writePlaywrightTaskWorkspace as Q}from"./config.js";import{collectPlaywrightEvidence as Z}from"./evidence.js";import{engineEvidenceIdentity as q}from"../../adapters/evidence-identity.js";import{getNodeStartupCacheEnvironment as rr}from"../../adapters/node-startup-cache.js";const y={codePrefix:"PLAYWRIGHT",label:"Playwright"};export const PLAYWRIGHT_SPAWN_ENVIRONMENT_MAX_BYTES=24*1024;const L=64;class k extends Error{constructor(r){const e=g(r);super(e.message,{cause:e}),this.name="PlaywrightConsumerPreparationError"}}export const playwrightAdapterDependencies={createInvocationEnvironment:j,removeOwnedDirectory:ir,writeTaskWorkspace:Q};const tr=new Set(["EBUSY","ENOTEMPTY","EPERM"]),er=5;async function ir(t){for(let r=0;;r+=1)try{await u.rm(t,{force:!0,recursive:!0});return}catch(e){const i=e instanceof Error&&"code"in e?e.code:void 0;if(r===er||typeof i!="string"||!tr.has(i))throw e;await $((r+1)*100)}}export async function executePlaywrightEngine(t,r,e,i=playwrightAdapterDependencies){const o=await or(t,r,i,e);return x(t,o.tasks,y,(a,s)=>nr(t,o,a,s),lr(t,o.installation))}async function or(t,r,e,i){const o=await B(t.workspace.rootDirectory);O(t.workspace.temporaryDirectory,"temporary directory"),O(t.workspace.artifactDirectory,"artifact directory"),await u.mkdir(t.workspace.temporaryDirectory,{recursive:!0}),await u.mkdir(t.workspace.artifactDirectory,{recursive:!0});const a=await u.realpath(t.workspace.temporaryDirectory),s=await u.realpath(t.workspace.artifactDirectory),n=await D(`playwright-${S(t.invocationId)}-`,{parentDir:a});i.defer(()=>e.removeOwnedDirectory(n));const l=await e.createInvocationEnvironment(n);i.defer(()=>e.removeOwnedDirectory(l.temporaryDirectory));const p=[];for(const[h,c]of t.tasks.entries()){const I=V(t,c),v=`${h.toString().padStart(3,"0")}-${S(c.id)}`,_=H.join(n,v),f=await D(`${v}-`,{parentDir:s});try{const m=cr(t,c.serviceName),E=await pr(()=>Y(o,c.file,"Playwright task file")),w=await e.writeTaskWorkspace({artifactDirectory:f,baseUrl:m,browserFile:r.browserExecutable,databases:t.target.databases,endpoints:t.target.endpoints,handles:t.target.handles,inputs:I,invocationId:t.invocationId,managedModuleEntrypoints:{authoring:r.authoringEntrypoints.authoring,cli:r.family.cli,environment:r.authoringEntrypoints.environment,playwright:r.family.playwright.entrypoint,playwrightCore:r.family.playwrightCore.entrypoint,playwrightTest:r.family.playwrightTest.entrypoint,root:r.authoringEntrypoints.root,rootPackageJson:r.authoringEntrypoints.rootPackageJson},moduleFile:r.family.playwrightTest.entrypoint,orchestration:c.orchestration,rootDirectory:o,serviceName:c.serviceName,sourceFile:E,taskDirectory:_,taskId:c.id});i.defer(async()=>{try{await e.removeOwnedDirectory(w.attachmentDirectory)}catch(d){if(!(d instanceof Error&&"code"in d&&d.code==="ENOTDIR"))throw d}}),p.push({artifactDirectory:f,inputs:I,task:c,preparationFailure:null,prepared:{baseUrl:m,sourceFile:E,workspace:w}})}catch(m){const E=(await ur([_,f],e)).map(w=>w.error);p.push({artifactDirectory:f,inputs:I,task:c,preparationFailure:playwrightPreparationFailure(m,E),prepared:null})}}return Object.freeze({installation:r,invocationEnvironment:l.environment,rootDirectory:o,tasks:Object.freeze(p)})}async function nr(t,r,e,i){const a={...await rr(t.workspace.cacheDirectory,e.inputs.environment),...ar(t,r,e)};try{A(a)}catch{delete a.NODE_COMPILE_CACHE}const s=e.task.deadlineMs-Date.now();if(s<=0)return T(e.task.id,"failed",i,W(),U(e.task.timeoutMs,y));const n=await J({args:[r.installation.family.cli,"test",X(e.prepared.sourceFile),"--config",e.prepared.workspace.configFile],cwd:r.rootDirectory,displayLabel:"Playwright",env:a,executable:process.execPath,signal:t.signal,timeoutMs:s});let l;try{l=await Z({identity:{engineId:"playwright",invocationId:t.invocationId,taskId:e.task.id,sourceFile:e.prepared.sourceFile},artifactDirectory:e.artifactDirectory,outputDirectory:e.prepared.workspace.outputDirectory,reportFile:e.prepared.workspace.reportFile,rootDirectory:r.rootDirectory,sourceFile:e.prepared.sourceFile,stderr:n.stderr,stdout:n.stdout})}catch(h){return T(e.task.id,"failed",i,N(n),playwrightEvidenceCollectionFailure(n,h))}const p=classifyPlaywrightProcessResult(n,l,e.task.timeoutMs,G(t.signal.reason));return T(e.task.id,p.status,i,l.evidence,p.failure)}export function classifyPlaywrightProcessResult(t,r,e,i){const o=F(t,e,i,y);if(o!==null)return o;if(r.outputLimit!==null){const n=r.outputLimit;return{failure:{code:"PLAYWRIGHT_OUTPUT_ARTIFACT_LIMIT",details:{...n},message:`Playwright output exceeded its ${n.limit.toString()} ${n.kind==="bytes"?"byte aggregate":"entry"} artifact limit`},status:"failed"}}const a=r.attachmentFailures.find(n=>n.code==="PLAYWRIGHT_ATTACHMENT_LIMIT");if(a!==void 0)return{failure:a,status:"failed"};if(r.report.failure!==null){const n=r.report.failure;return{...r.report,failure:{...n,details:{...n.details,evidenceErrors:r.reportError===null?0:1,...b(t)}}}}const s=r.attachmentFailures.at(0);return s!==void 0?{failure:s,status:"failed"}:t.exitCode!==0?C(t,y,R(t.stderr)??R(t.stdout)):r.reportError!==null?{failure:{...P(r.reportError,"PLAYWRIGHT_REPORT_INVALID"),classification:"infra"},status:"failed"}:r.report}export function playwrightEvidenceCollectionFailure(t,r){const e=g(r);return M(t,y,e)??{...P(e,"PLAYWRIGHT_EVIDENCE_FAILED"),classification:"infra"}}function ar(t,r,e){const i={...r.invocationEnvironment},o=e.task,a=e.prepared.workspace.inputBootstrapFile,s=e.prepared.workspace.resolutionBootstrapFile;return Object.assign(i,{...e.prepared.baseUrl===null?{}:{BASE_URL:e.prepared.baseUrl},FORCE_COLOR:"0",NO_COLOR:"1",PLAYWRIGHT_BROWSERS_PATH:r.installation.registry.canonicalValue,PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD:"1",TESTKIT_ACTIVE:"1",TESTKIT_INTERNAL_FILE_DEADLINE_MS:String(o.deadlineMs),TESTKIT_INTERNAL_FILE_TIMEOUT_SECONDS:String(Math.max(1,Math.ceil(o.timeoutMs/1e3))),TESTKIT_INVOCATION_ID:t.invocationId,TESTKIT_LEASE_DIR:o.orchestration.lease.directory,TESTKIT_LEASE_ID:o.orchestration.lease.id,TESTKIT_MODE:o.orchestration.mode,...o.orchestration.runtimeId===void 0?{}:{TESTKIT_RUNTIME_ID:o.orchestration.runtimeId},TESTKIT_TEST_FILE:o.file,TESTKIT_TEST_ID:o.id}),i.NODE_OPTIONS=sr(s,a),A(i),i}function sr(t,r){return["--experimental-strip-types",`--require=${JSON.stringify(t)}`,`--import=${JSON.stringify(K(r).href)}`].join(" ")}export function playwrightSpawnEnvironmentBytes(t){return Object.entries(t).reduce((r,[e,i])=>r+(process.platform==="win32"?(e.length+i.length+2)*2:Buffer.byteLength(e,"utf8")+Buffer.byteLength(i,"utf8")+2),0)}function A(t){if(Object.keys(t).length>L)throw new Error(`Playwright physical spawn environment exceeds its ${L.toString()} entry limit`);if(playwrightSpawnEnvironmentBytes(t)>PLAYWRIGHT_SPAWN_ENVIRONMENT_MAX_BYTES)throw new Error(`Playwright physical spawn environment exceeds its ${PLAYWRIGHT_SPAWN_ENVIRONMENT_MAX_BYTES.toString()} byte limit`)}function cr(t,r){const e=t.target.baseUrl;if(e===null)return null;if(typeof e!="string"||e.trim().length===0)throw new Error(`Playwright task service ${r} endpoint must be a non-empty URL`);let i;try{i=new URL(e)}catch(o){throw new Error(`Playwright task service ${r} endpoint is not a valid URL`,{cause:o})}if(i.protocol!=="http:"&&i.protocol!=="https:")throw new Error(`Playwright task service ${r} endpoint must use http or https`);return i.href}function lr(t,r){return{...q({engineId:"playwright",installationKind:"root-playwright-family",profile:t.profile}),browserName:"chromium",packages:{playwright:r.family.playwright.version,playwrightCore:r.family.playwrightCore.version,playwrightTest:r.family.playwrightTest.version},registryMode:r.registry.mode}}export function playwrightPreparationFailure(t,r){if(r.length===0)return{...P(t,"PLAYWRIGHT_PREPARE_FAILED"),classification:t instanceof k||t instanceof z?"product":"infra"};const e=g(t);return{classification:"infra",code:"PLAYWRIGHT_PREPARE_CLEANUP_FAILED",details:{cleanupFailures:r.map(i=>i.message),preparationFailure:e.message},message:`Playwright task preparation failed and its partial workspace could not be removed: ${r.map(i=>i.message).join("; ")}`,...e.stack===void 0?{}:{stack:e.stack}}}async function pr(t){try{return await t()}catch(r){throw new k(r)}}async function ur(t,r){const e=[];for(const i of t)try{await r.removeOwnedDirectory(i)}catch(o){e.push({directory:i,error:g(o)})}return e}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import{ownedRuntimeInputModuleUrl as
|
|
1
|
+
import{ownedRuntimeInputModuleUrl as d}from"../../runtime-input-file.js";import w from"node:crypto";import n from"node:fs/promises";import o from"node:path";import{fileURLToPath as b,pathToFileURL as g}from"node:url";import{createManagedNodeModuleResolution as j}from"../../managed-module-resolution.js";import{materializePlaywrightRuntimeInput as P,playwrightRuntimeInputBootstrapSource as v}from"../runtime/runtime-input.js";import{nativeReporterFile as T}from"../../adapters/native-report.js";import{requireConsumerFile as k}from"../../adapters/workspace.js";export class PlaywrightConsumerConfigurationError extends Error{constructor(r){const t=r instanceof Error?r:new Error(String(r));super(t.message,{cause:t}),this.name="PlaywrightConsumerConfigurationError"}}export async function writePlaywrightTaskWorkspace(e){let r;try{F(e.inputs.supportModules),r=await D(e.rootDirectory,e.inputs)}catch(m){throw new PlaywrightConsumerConfigurationError(m)}await n.mkdir(e.taskDirectory,{recursive:!0}),await n.mkdir(e.artifactDirectory,{recursive:!0});const t=w.randomUUID(),i=o.join(e.taskDirectory,`playwright-${t}.config.mjs`),s=o.join(e.taskDirectory,`playwright-${t}.input-bootstrap.mjs`),h=o.join(e.taskDirectory,`playwright-${t}.resolution-bootstrap.cjs`),f=o.join(e.taskDirectory,"testkit-playwright-report.json"),l=o.join(e.artifactDirectory,"playwright-output");await n.mkdir(l);const p=o.join(e.artifactDirectory,"playwright-attachments");await n.mkdir(p,{mode:448,recursive:!1});const c=await P({baseUrl:e.baseUrl,databases:e.databases,directory:e.taskDirectory,endpoints:e.endpoints,handles:e.handles,inputs:e.inputs,invocationId:e.invocationId,orchestration:e.orchestration,taskId:e.taskId}),y=T("playwright");return await u(h,playwrightResolutionBootstrapSource(e.managedModuleEntrypoints,{consumerRoots:[e.rootDirectory],trustedImporterFiles:[i,s],trustedInternalEntrypoints:[e.moduleFile,y,b(d)]})),await u(s,v({digest:c.digest,file:c.file,sizeBytes:c.sizeBytes,invocationId:e.invocationId,taskId:e.taskId})),await u(i,O({baseConfigFile:r,baseUrl:e.baseUrl,browserFile:e.browserFile,inputBootstrapFile:s,outputDirectory:l,reporterFile:y,report:{attachmentDirectory:p,identity:{engineId:"playwright",invocationId:e.invocationId,taskId:e.taskId,sourceFile:e.sourceFile},reportFile:f,workspaceDirectory:e.taskDirectory},rootDirectory:e.rootDirectory,sourceFile:e.sourceFile})),{attachmentDirectory:p,configFile:i,inputBootstrapFile:s,outputDirectory:l,reportFile:f,resolutionBootstrapFile:h}}export function playwrightResolutionBootstrapSource(e,r){const t={authoring:a(e.authoring,"authoring"),cli:a(e.cli,"cli"),environment:a(e.environment,"environment"),playwright:a(e.playwright,"playwright"),playwrightCore:a(e.playwrightCore,"playwrightCore"),playwrightTest:a(e.playwrightTest,"playwrightTest"),root:a(e.root,"root"),rootPackageJson:a(e.rootPackageJson,"rootPackageJson")},i={"@playwright/test":t.playwrightTest,playwright:t.playwright,"playwright-core":t.playwrightCore};return j({consumerRoots:r.consumerRoots,direct:{"@gfdelarue/testkit":t.root,"@gfdelarue/testkit/environment":t.environment,"@gfdelarue/testkit/package.json":t.rootPackageJson,"@gfdelarue/testkit/playwright":t.authoring},directBridgeRoots:[o.dirname(t.root)],engineLabel:"Playwright",forbiddenConsumerPackagePrefixes:[],packageAnchors:i,reservedPackageNames:["@gfdelarue/testkit"],stateSymbol:"@gfdelarue/testkit/playwright-resolution-hooks/v1",trustedImporterFiles:r.trustedImporterFiles,trustedInternalEntrypoints:r.trustedInternalEntrypoints,verifiedParentlessPackageFiles:{playwright:["lib/common/process.js"]},verifiedProcessEntrypoints:[t.cli]}).bootstrapSource}function a(e,r){if(!o.isAbsolute(e))throw new Error(`Resolved Playwright installation ${r} entrypoint must be absolute`);return e}function O(e){return`
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { createRequire } from "node:module";
|
|
4
4
|
|
|
5
|
-
const OPTIONS = ${JSON.stringify({baseConfigUrl:e.baseConfigFile===null?null:g(e.baseConfigFile).href,baseUrl:e.baseUrl,browserFile:e.browserFile,exactTaskMatchSource:
|
|
5
|
+
const OPTIONS = ${JSON.stringify({baseConfigUrl:e.baseConfigFile===null?null:g(e.baseConfigFile).href,baseUrl:e.baseUrl,browserFile:e.browserFile,exactTaskMatchSource:playwrightExactFileFilter(e.sourceFile),originalConfigDirectory:e.baseConfigFile===null?e.rootDirectory:o.dirname(e.baseConfigFile),originalConfigFile:e.baseConfigFile??o.join(e.rootDirectory,"__testkit_playwright_config__.mjs"),inputBootstrapUrl:g(e.inputBootstrapFile).href,outputDirectory:e.outputDirectory,report:e.report,reporterFile:e.reporterFile,rootDirectory:e.rootDirectory,sourceFile:e.sourceFile})};
|
|
6
6
|
const inputBootstrap = await import(OPTIONS.inputBootstrapUrl);
|
|
7
7
|
if (typeof inputBootstrap.installPlaywrightRuntimeInput !== "function")
|
|
8
8
|
throw new Error("Managed Playwright runtime-input bootstrap is invalid");
|
|
@@ -63,7 +63,7 @@ function normalizeUse(use, label) {
|
|
|
63
63
|
return {
|
|
64
64
|
...value,
|
|
65
65
|
browserName: "chromium",
|
|
66
|
-
baseURL: OPTIONS.baseUrl,
|
|
66
|
+
...(OPTIONS.baseUrl === null ? {} : { baseURL: OPTIONS.baseUrl }),
|
|
67
67
|
launchOptions: {
|
|
68
68
|
...(value.launchOptions && typeof value.launchOptions === "object" ? value.launchOptions : {}),
|
|
69
69
|
executablePath: OPTIONS.browserFile,
|
|
@@ -164,4 +164,4 @@ export default {
|
|
|
164
164
|
fullyParallel: false,
|
|
165
165
|
workers: 1,
|
|
166
166
|
};
|
|
167
|
-
`}function
|
|
167
|
+
`}export function playwrightExactFileFilter(e){return`^${e.split(/[\\/]+/u).map(r=>r.replace(/[.*+?^${}()|[\]\\]/gu,"\\$&")).join("[\\\\/]")}$`}async function D(e,r){if(!Object.hasOwn(r.supportModules,"playwrightConfig"))return null;const t=r.supportModules.playwrightConfig;if(!o.isAbsolute(t))throw new Error("supportModules.playwrightConfig must be an absolute path");return k(e,t,"supportModules.playwrightConfig")}function F(e){const r=Object.keys(e).filter(t=>t!=="playwrightConfig");if(r.length>0)throw new Error(`Playwright engine does not support support module(s): ${r.join(", ")}`)}async function u(e,r){const t=await n.open(e,"wx",384);try{await t.writeFile(r,"utf8")}finally{await t.close()}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import e from"node:path";export function nonNegativeInteger(
|
|
1
|
+
import e from"node:path";import{isUnknownRecord as o}from"../../../kernel/unknown-values.js";export function nonNegativeInteger(n,r){if(typeof n!="number"||!Number.isSafeInteger(n)||n<0)throw new Error(`${r} must be a non-negative safe integer`);return n}export function optionalNonNegativeInteger(n,r){return n==null?null:nonNegativeInteger(n,r)}export function nonNegativeNumber(n,r){if(typeof n!="number"||!Number.isFinite(n)||n<0)throw new Error(`${r} must be a non-negative finite number`);return n}export function requireNonEmptyString(n,r){const t=optionalNonEmptyString(n);if(t===null)throw new Error(`${r} must be a non-empty string`);return t}export function optionalNonEmptyString(n){return typeof n=="string"&&n.trim().length>0?n.trim():null}export function portableReportPath(n){return n.replaceAll("\\","/")}export function portableRelativePath(n,r){return portableReportPath(e.relative(n,r))}export function requireRecord(n,r){if(!o(n))throw new Error(`${r} must contain an object`);return n}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import w from"node:fs/promises";import g from"node:path";import{evidenceArtifact as F,evidenceFileAccess as q,readStableJsonFile as tt,snapshotStableEvidenceFile as C,stableEvidenceFromBuffer as et,writeOwnedEvidenceFile as Y}from"../../adapters/evidence-files.js";import{materializePlaywrightFailureDetails as it}from"./failure-details.js";import{isMissingFileError as rt,isPathWithin as $,nonNegativeInteger as E,nonNegativeNumber as H,optionalNonEmptyString as N,optionalNonNegativeInteger as G,portableRelativePath as U,portableReportPath as W,requireNonEmptyString as b,requireRecord as S,toError as nt}from"./evidence-validation.js";import{readNativeReport as at}from"../../adapters/native-report.js";import{attachmentLimitError as st,attachmentIoError as ot,MAX_ATTACHMENT_BYTES as X,MAX_TOTAL_ATTACHMENT_BYTES as ct}from"./attachments.js";const lt=64*1024*1024,J=1e4,M=512*1024*1024,ut=2*1024*1024,V=128,pt=".testkit-playwright-evidence",dt=/(?:^|\n)(?:Error:\s*)?No tests found(?:\.|\n|$)/u,ht=["failed","interrupted","passed","timedout"];class R extends Error{limit;constructor(e){super(vt(e)),this.limit=e,this.name="PlaywrightOutputArtifactLimitError"}}export async function collectPlaywrightEvidence(t,e=q){await w.mkdir(t.artifactDirectory,{recursive:!0});const i=await w.realpath(t.artifactDirectory),c=await w.realpath(t.rootDirectory),n=g.join(i,pt);await w.mkdir(n,{mode:448,recursive:!1});const a=[],s=[];for(const r of["stdout","stderr"]){const l=t[r];if(l.length===0)continue;a.push({stream:r,text:l});const m=et(Buffer.from(l,"utf8")),y=await Y(n,`${r}.log`,m.contents);s.push(F(y,m,"text/plain; charset=utf-8","engine.process-output",`playwright-${r}`,`${m.sizeBytes.toString()} bytes`))}let p=null,d=null,f=new Set,h=[];try{const r=await tt(t.reportFile,lt,"Testkit native Playwright report",e);if(r.file===null)p=new Error("Playwright did not produce its Testkit native report");else{d=gt(at(r.value,t.identity).result,t.sourceFile);const l=await Y(n,"testkit-playwright-report.json",r.file.contents);s.push(F(l,r.file,"application/json","engine.testkit-playwright-report","testkit-playwright-report","Testkit native Playwright report")),a.push(...d.logs);const m=await it(n,d.failureDetails);m!==null&&s.push(m);const y=await wt(i,n,c,d.attachments,e);s.push(...y.artifacts),f=y.sourcePaths,h=y.failures}}catch(r){p=nt(r)}let o={artifacts:[],bytes:0,entries:0},u=null;try{o=await Pt(i,n,t.outputDirectory,f,e),s.push(...o.artifacts)}catch(r){if(!(r instanceof R))throw r;u=r.limit,a.push({stream:"engine",text:r.message})}const P=ft(d,c,t.sourceFile,h.length),k=u??o;return{attachmentFailures:h,evidence:{artifacts:s,logs:a,metrics:[...Object.entries(d?.stats??{}).map(([r,l])=>({name:r==="duration"?"playwright.duration":`playwright.tests.${r}`,unit:r==="duration"?"milliseconds":"tests",value:l})),...["bytes","entries"].map(r=>({name:`playwright.output.${r}`,unit:r,value:k[r]}))],...d===null?{}:{native:{playwright:{attachmentFailures:h.map(r=>({...r})),specs:d.specs,stats:d.stats}}}},outputLimit:u,report:P,reportError:p}}function ft(t,e,i,c){if(t===null)return{failure:null,status:"failed"};const n=t.specs.filter((s,p)=>K(i,t.sourceFiles[p])),a=t.failureMessages.length>0&&t.failureMessages.every(s=>dt.test(s));return t.stats.unexpected>0||t.failureMessages.length>0&&(!a||n.length>0)?{failure:{...t.failureMessages.some(s=>/browserType\.launch(?:PersistentContext)?:/u.test(s)&&/Executable doesn't exist|Host system is missing dependencies|error while loading shared libraries|Failed to launch/u.test(s))?{classification:"infra"}:{},code:"PLAYWRIGHT_SPECS_FAILED",details:{attachmentFailures:c,failOnFlakyTests:t.failOnFlakyTests,reportErrors:t.reportErrors,runStatus:t.runStatus,stats:t.stats,specs:t.specs.slice(0,50)},message:t.failureMessages.at(0)??`${t.stats.unexpected.toString()} Playwright test(s) failed`},status:"failed"}:n.length>0?{failure:null,status:n.every(s=>s.status==="skipped")?"skipped":"passed"}:{failure:{code:"PLAYWRIGHT_NO_TESTS",details:{file:U(e,i),reportedSpecs:t.specs.slice(0,50),stats:t.stats},message:"Selected Playwright task did not execute any tests"},status:"failed"}}function K(t,e){return g.relative(g.normalize(t),e)===""}function gt(t,e){const i=S(t,"Playwright native report result"),c=ht.find(r=>r===i.status);if(c===void 0)throw new Error("Playwright native report status is invalid");if(typeof i.failOnFlakyTests!="boolean")throw new Error("Playwright native report failOnFlakyTests must be a boolean");const n=i.failOnFlakyTests,a=bt(i.stats),s=O(i.errors,"errors"),p=s.length,d=[],f=[],h=[],o=new Set,u={expected:0,flaky:0,skipped:0,unexpected:0};for(const r of A(i.specs,"specs")){const l=S(r,"Playwright native report spec"),m=b(l.id,"Playwright native spec.id");if(o.has(m))throw new Error("Playwright native report contains a duplicate test identity");o.add(m);const y=b(l.title,"Playwright native spec.title"),v=O(l.parents,"spec.parents");v.length>0&&(v[0]=W(v[0]));const L=W(b(l.file,"Playwright native spec.file")),x=b(l.sourceFile,"Playwright native spec.sourceFile");if(!g.isAbsolute(x)&&!g.win32.isAbsolute(x))throw new Error("Playwright native spec.sourceFile must be absolute");const Z=_(l.projectName,"spec.projectName"),T=l.status;if(T!=="expected"&&T!=="flaky"&&T!=="skipped"&&T!=="unexpected")throw new Error("Playwright native spec.status is invalid");u[T]+=1;const j=O(l.failureMessages,"spec.failureMessages"),z=l.failureStack===null?null:_(l.failureStack,"spec.failureStack"),D=G(l.line,"Playwright native spec.line"),B=G(l.column,"Playwright native spec.column");T==="unexpected"&&(s.push(...j),h.push({kind:K(e,x)?"playwright-spec":"playwright-other-file-spec",key:[...v.slice(1),y].filter(Boolean).join(" "),title:y,count:1,message:j[0]??`Playwright reported "${y}" as an unexpected failure`,...v.length===0?{}:{suitePath:v},location:{path:L,...D===null?{}:{line:D},...B===null?{}:{column:B}},...z===null?{}:{stack:z}})),f.push(x),d.push({durationMs:H(l.durationMs,"Playwright native spec.durationMs"),retries:E(l.retries,"Playwright native spec.retries"),file:L,projectName:Z,status:T,title:[...v,y].filter(Boolean).join(" > ")})}for(const r of["expected","flaky","skipped","unexpected"])if(a[r]!==u[r])throw new Error("Playwright native report stats do not match its cases");const P=A(i.logs,"logs").map(r=>{const l=S(r,"Playwright native report log");if(l.stream!=="stdout"&&l.stream!=="stderr")throw new Error("Playwright native report log stream is invalid");return{stream:l.stream,text:_(l.text,"log.text")}});return{attachments:A(i.attachments,"attachments").map((r,l)=>yt(r,l,o)),failOnFlakyTests:n,failureDetails:h,failureMessages:s,logs:St(P),reportErrors:p,runStatus:c,sourceFiles:f,specs:d,stats:a}}function A(t,e){if(!Array.isArray(t))throw new Error(`Playwright native report ${e} must be an array`);return t}function O(t,e){return A(t,e).map(i=>_(i,e))}function _(t,e){if(typeof t!="string")throw new Error(`Playwright native report ${e} must be a string`);return t}function yt(t,e,i){const c=S(t,`Playwright attachment[${e.toString()}]`),n=b(c.specId,"Playwright attachment.specId");if(!i.has(n))throw new Error("Playwright native attachment references an unknown test identity");const a=N(c.path),s=c.error===void 0?void 0:mt(c.error);if(c.body!==void 0||a===null&&s===void 0)throw new Error("Playwright attachment must contain a path or an error");return{contentType:N(c.contentType)??"application/octet-stream",name:N(c.name)??`attachment-${e.toString()}`,specId:n,...a===null?{}:{path:a},...s===void 0?{}:{error:s},retry:E(c.retry,"Playwright attachment.retry"),specTitle:b(c.specTitle,"Playwright attachment.specTitle")}}function mt(t){const e=S(t,"Playwright attachment.error");if(e.kind==="io")return{kind:"io",message:b(e.message,"Playwright attachment.error.message")};const i=e.kind;if(i!=="individual"&&i!=="total")throw new Error("Playwright attachment.error has an invalid kind");const c=i==="individual"?X:ct,n=E(e.observed,"Playwright attachment.error.observed");if(e.limit!==c||n<=c)throw new Error("Playwright attachment.error has an invalid limit");return{kind:i,limit:c,observed:n}}function I(t,e){const{name:i,specId:c,specTitle:n,retry:a}=t,s=e.kind==="io"?e.message:`exceeds its ${e.limit.toString()} byte ${e.kind} limit (observed ${e.observed.toString()} bytes)`;return{code:e.kind==="io"?"PLAYWRIGHT_ATTACHMENT_FAILED":"PLAYWRIGHT_ATTACHMENT_LIMIT",...e.kind==="io"?{classification:"infra"}:{},details:{name:i,specId:c,specTitle:n,retry:a,...e},message:`Playwright attachment "${i}" (${n}, retry ${a.toString()}): ${s}`}}async function wt(t,e,i,c,n){const a=[],s=[],p=new Set;let d=0;const f=g.join(e,"attachments");c.length>0&&await w.mkdir(f,{mode:448,recursive:!1});for(const[h,o]of c.entries())try{if(o.error!==void 0){o.path!==void 0&&p.add(g.resolve(i,o.path)),s.push(I(o,o.error));continue}const u=await Tt(o.path,i,t,n);p.add(u.file);const P=E(Number(u.identity.size),"Playwright attachment size"),k=st(P,d+P);if(k!==null){s.push(I(o,k));continue}const r=await C(u.file,X,"Playwright attachment",n,u.identity,f,`${h.toString().padStart(4,"0")}-${Q(o.name)}${kt(o)}`);d+=r.identity.sizeBytes,a.push({path:r.filePath,contentType:o.contentType,kind:"engine.playwright-attachment",name:o.name,summary:`${o.specTitle} retry ${o.retry.toString()}`,metadata:{...r.identity,specId:o.specId,specTitle:o.specTitle,retry:o.retry}})}catch(u){s.push(I(o,ot(u)))}return{artifacts:a,failures:s,sourcePaths:p}}async function Pt(t,e,i,c,n){try{const a=await n.lstat(i);if(!a.isDirectory()||a.isSymbolicLink())throw new Error("Playwright output directory must be a non-symbolic-link directory");const s=await w.realpath(i);if(!$(t,s))throw new Error("Playwright output directory escaped the artifact root");const p=await Et(s,c,n),d=[],f=g.join(e,"output");p.candidates.length>0&&await w.mkdir(f,{mode:448,recursive:!1});for(const[h,o]of p.candidates.entries()){const u=await C(o.file,M,"Playwright output file",n,o.identity,f,`${h.toString().padStart(5,"0")}-${Q(g.basename(o.file))}${At(o.file)}`);d.push(F(u.filePath,u.identity,xt(o.file),"engine.playwright-output",o.relativePath,"Playwright output"))}return{artifacts:d,bytes:p.bytes,entries:p.entries}}catch(a){if(rt(a))return{artifacts:[],bytes:0,entries:0};throw a}}async function Et(t,e,i){const c=[];let n=0,a=0;const s=[{depth:0,directory:t}];for(;s.length>0;){const p=s.pop();if(p===void 0)continue;if(p.depth>V)throw new Error(`Playwright output exceeds the ${V.toString()} level directory depth limit`);const d=p.directory,f=await w.readdir(d,{withFileTypes:!0});f.sort((h,o)=>h.name.localeCompare(o.name));for(const h of f){if(a+=1,a>J)throw new R({bytes:n,entries:a,kind:"entries",limit:J,observed:a});const o=g.join(d,h.name),u=await i.lstat(o);if(u.isSymbolicLink())throw new Error("Playwright output must not contain symbolic links");if(u.isDirectory()){s.push({depth:p.depth+1,directory:o});continue}if(!u.isFile())continue;if(u.size<0n||u.size>BigInt(Number.MAX_SAFE_INTEGER))throw new Error("Playwright output file has an invalid size");const P=Number(u.size);if(n+=P,!Number.isSafeInteger(n)||n>M)throw new R({bytes:n,entries:a,kind:"bytes",limit:M,observed:n});e.has(o)||c.push({file:o,identity:u,relativePath:U(t,o)})}}return{bytes:n,candidates:c,entries:a}}function vt(t){return t.kind==="bytes"?`Playwright output exceeds its ${t.limit.toString()} byte aggregate limit (observed ${t.observed.toString()} bytes)`:`Playwright output exceeds its ${t.limit.toString()} entry limit (observed ${t.observed.toString()} entries)`}async function Tt(t,e,i,c){if(t===void 0)throw new Error("Playwright path attachment did not declare a path");const n=g.resolve(e,t),a=await c.lstat(n);if(!a.isFile()||a.isSymbolicLink())throw new Error("Playwright attachment path must be a regular non-symbolic-link file");const s=await w.realpath(n);if(!$(e,s)&&!$(i,s))throw new Error("Playwright attachment path must stay within the consumer or artifact root");return{file:s,identity:a}}function bt(t){const e=S(t,"Playwright report.stats");return{expected:E(e.expected,"Playwright stats.expected"),unexpected:E(e.unexpected,"Playwright stats.unexpected"),flaky:E(e.flaky,"Playwright stats.flaky"),skipped:E(e.skipped,"Playwright stats.skipped"),duration:H(e.duration,"Playwright stats.duration")}}function St(t){let e=ut;const i=[];for(const c of t){if(e<=0)break;const a=Buffer.from(c.text,"utf8").subarray(0,e).toString("utf8");a.length>0&&i.push({...c,text:a}),e-=Buffer.byteLength(a)}return e<=0&&i.push({stream:"engine",text:"Playwright report log evidence was truncated at its bounded limit"}),i}function kt(t){if(t.path!==void 0){const e=g.extname(t.path);if(/^\.[a-z0-9]{1,12}$/iu.test(e))return e}return t.contentType==="application/json"?".json":t.contentType.startsWith("text/")?".txt":t.contentType==="image/png"?".png":t.contentType==="image/jpeg"?".jpg":".bin"}function xt(t){const e=g.extname(t).toLowerCase();return e===".json"?"application/json":e===".zip"?"application/zip":e===".png"?"image/png":e===".jpg"||e===".jpeg"?"image/jpeg":e===".webm"?"video/webm":[".log",".txt",".md"].includes(e)?"text/plain; charset=utf-8":"application/octet-stream"}function At(t){const e=g.extname(t).toLowerCase();return/^\.[a-z0-9]{1,12}$/u.test(e)?e:".bin"}function Q(t){const e=t.trim().toLowerCase().replace(/[^a-z0-9._-]+/gu,"-").replace(/^-+|-+$/gu,"").slice(0,80);return e.length>0?e:"attachment"}
|
|
1
|
+
import{toError as ot}from"../../../kernel/error-serialization.js";import{isPathWithin as N}from"../../../process/files/paths.js";import v from"node:fs/promises";import g from"node:path";import{evidenceArtifact as O,evidenceFileAccess as lt,readStableJsonFile as ct,snapshotStableEvidenceFile as U,stableEvidenceFromBuffer as X,writeOwnedEvidenceFile as V,isMissingFileError as ut}from"../../adapters/evidence-files.js";import{materializePlaywrightFailureDetails as pt}from"./failure-details.js";import{nonNegativeInteger as T,nonNegativeNumber as J,optionalNonEmptyString as R,optionalNonNegativeInteger as K,portableRelativePath as Q,portableReportPath as Z,requireNonEmptyString as k,requireRecord as P}from"./evidence-validation.js";import{readNativeReport as dt}from"../../adapters/native-report.js";import{environmentValueMissingFailure as ht,parseEnvironmentValueMissingFailure as q,readEnvironmentValueMissingFailure as ft}from"../../contracts/environment-values.js";import{attachmentLimitError as mt,attachmentIoError as gt,MAX_ATTACHMENT_BYTES as tt,MAX_TOTAL_ATTACHMENT_BYTES as yt}from"./attachments.js";const wt=64*1024*1024,et=1e4,I=512*1024*1024,vt=2*1024*1024,it=128,Pt=".testkit-playwright-evidence",Et=/(?:^|\n)(?:Error:\s*)?No tests found(?:\.|\n|$)/u,Tt=["failed","interrupted","passed","timedout"];class L extends Error{limit;constructor(e){super(Mt(e)),this.limit=e,this.name="PlaywrightOutputArtifactLimitError"}}export async function collectPlaywrightEvidence(t,e=lt){await v.mkdir(t.artifactDirectory,{recursive:!0});const i=await v.realpath(t.artifactDirectory),s=await v.realpath(t.rootDirectory),n=g.join(i,Pt);await v.mkdir(n,{mode:448,recursive:!1});const r=[],o=[];for(const l of["stdout","stderr"]){const y=t[l];if(y.length===0)continue;r.push({stream:l,text:y});const F=X(Buffer.from(y,"utf8")),f=await V(n,`${l}.log`,F.contents);o.push(O(f,F,"text/plain; charset=utf-8","engine.process-output",`playwright-${l}`,`${F.sizeBytes.toString()} bytes`))}let c=null,p=null,m=new Set,h=[];try{const l=await ct(t.reportFile,wt,"Testkit native Playwright report",e);if(l.file===null)c=new Error("Playwright did not produce its Testkit native report");else{p=St(dt(l.value,t.identity).result,t.sourceFile);const y=p.carriesEnvironmentFailures?X(Buffer.from(kt(l.value))):l.file,F=await V(n,"testkit-playwright-report.json",y.contents);o.push(O(F,y,"application/json","engine.testkit-playwright-report","testkit-playwright-report","Testkit native Playwright report")),r.push(...p.logs);const f=await pt(n,p.failureDetails);f!==null&&o.push(f);const u=await At(i,n,s,p.attachments,e);o.push(...u.artifacts),m=u.sourcePaths,h=u.failures}}catch(l){c=ot(l)}let a={artifacts:[],bytes:0,entries:0},d=null;try{a=await _t(i,n,t.outputDirectory,m,e),o.push(...a.artifacts)}catch(l){if(!(l instanceof L))throw l;d=l.limit,r.push({stream:"engine",text:l.message})}const w=bt(p,s,t.sourceFile,h.length),E=d??a;return{attachmentFailures:h,evidence:{artifacts:o,logs:r,metrics:[...Object.entries(p?.stats??{}).map(([l,y])=>({name:l==="duration"?"playwright.duration":`playwright.tests.${l}`,unit:l==="duration"?"milliseconds":"tests",value:y})),...["bytes","entries"].map(l=>({name:`playwright.output.${l}`,unit:l,value:E[l]}))],...p===null?{}:{native:{playwright:{attachmentFailures:h.map(l=>({...l})),specs:p.specs,stats:p.stats}}}},outputLimit:d,report:w,reportError:c}}function bt(t,e,i,s){if(t===null)return{failure:null,status:"failed"};const n=t.environmentFailures.at(0);if(n!==void 0)return{failure:ht(t.environmentFailures.flatMap(c=>ft(c)??[]),n.message),status:"failed"};const r=t.specs.filter((c,p)=>rt(i,t.sourceFiles[p])),o=t.failureMessages.length>0&&t.failureMessages.every(c=>Et.test(c));return t.stats.unexpected>0||t.failureMessages.length>0&&(!o||r.length>0)?{failure:{...t.failureMessages.some(c=>/browserType\.launch(?:PersistentContext)?:/u.test(c)&&/Executable doesn't exist|Host system is missing dependencies|error while loading shared libraries|Failed to launch/u.test(c))?{classification:"infra"}:{},code:"PLAYWRIGHT_SPECS_FAILED",details:{attachmentFailures:s,failOnFlakyTests:t.failOnFlakyTests,reportErrors:t.reportErrors,runStatus:t.runStatus,stats:t.stats,specs:t.specs.slice(0,50)},message:t.failureMessages.at(0)??`${t.stats.unexpected.toString()} Playwright test(s) failed`},status:"failed"}:r.length>0?{failure:null,status:r.every(c=>c.status==="skipped")?"skipped":"passed"}:{failure:{code:"PLAYWRIGHT_NO_TESTS",details:{file:Q(e,i),reportedSpecs:t.specs.slice(0,50),stats:t.stats},message:"Selected Playwright task did not execute any tests"},status:"failed"}}function rt(t,e){return g.relative(g.normalize(t),e)===""}function St(t,e){const i=P(t,"Playwright native report result"),s=Tt.find(f=>f===i.status);if(s===void 0)throw new Error("Playwright native report status is invalid");if(typeof i.failOnFlakyTests!="boolean")throw new Error("Playwright native report failOnFlakyTests must be a boolean");const n=i.failOnFlakyTests,r=Ot(i.stats),o=j(i.errors,"errors"),c=o.length,p=q(i.environmentFailure,"Playwright native report environment failure"),m=p===null?[]:[p];let h=p!==null;const a=[],d=[],w=[],E=new Set,l={expected:0,flaky:0,skipped:0,unexpected:0};for(const f of x(i.specs,"specs")){const u=P(f,"Playwright native report spec"),B=k(u.id,"Playwright native spec.id");if(E.has(B))throw new Error("Playwright native report contains a duplicate test identity");E.add(B);const A=k(u.title,"Playwright native spec.title"),b=j(u.parents,"spec.parents");b.length>0&&(b[0]=Z(b[0]));const D=Z(k(u.file,"Playwright native spec.file")),_=k(u.sourceFile,"Playwright native spec.sourceFile");if(!g.isAbsolute(_)&&!g.win32.isAbsolute(_))throw new Error("Playwright native spec.sourceFile must be absolute");const st=M(u.projectName,"spec.projectName"),S=u.status;if(S!=="expected"&&S!=="flaky"&&S!=="skipped"&&S!=="unexpected")throw new Error("Playwright native spec.status is invalid");l[S]+=1;const C=j(u.failureMessages,"spec.failureMessages"),Y=u.failureStack===null?null:M(u.failureStack,"spec.failureStack"),H=K(u.line,"Playwright native spec.line"),W=K(u.column,"Playwright native spec.column"),G=rt(e,_),$=q(u.environmentFailure,"Playwright native spec environment failure");$!==null&&(h=!0),G&&$!==null&&m.push($),S==="unexpected"&&(o.push(...C),w.push({...$===null?{}:{classification:"infra"},kind:G?"playwright-spec":"playwright-other-file-spec",key:[...b.slice(1),A].filter(Boolean).join(" "),title:A,count:1,message:C[0]??`Playwright reported "${A}" as an unexpected failure`,...b.length===0?{}:{suitePath:b},location:{path:D,...H===null?{}:{line:H},...W===null?{}:{column:W}},...Y===null?{}:{stack:Y}})),d.push(_),a.push({durationMs:J(u.durationMs,"Playwright native spec.durationMs"),retries:T(u.retries,"Playwright native spec.retries"),file:D,projectName:st,status:S,title:[...b,A].filter(Boolean).join(" > ")})}for(const f of["expected","flaky","skipped","unexpected"])if(r[f]!==l[f])throw new Error("Playwright native report stats do not match its cases");const y=x(i.logs,"logs").map(f=>{const u=P(f,"Playwright native report log");if(u.stream!=="stdout"&&u.stream!=="stderr")throw new Error("Playwright native report log stream is invalid");return{stream:u.stream,text:M(u.text,"log.text")}});return{attachments:x(i.attachments,"attachments").map((f,u)=>Ft(f,u,E)),carriesEnvironmentFailures:h,environmentFailures:m,failOnFlakyTests:n,failureDetails:w,failureMessages:o,logs:Rt(y),reportErrors:c,runStatus:s,sourceFiles:d,specs:a,stats:r}}function kt(t){const e=P(t,"Testkit native Playwright report"),i=nt(P(e.result,"Playwright native report result")),s=x(i.specs,"specs").map(n=>nt(P(n,"Playwright native report spec")));return JSON.stringify({...e,result:{...i,specs:s}})}function nt(t){return Object.fromEntries(Object.entries(t).filter(([e])=>e!=="environmentFailure"))}function x(t,e){if(!Array.isArray(t))throw new Error(`Playwright native report ${e} must be an array`);return t}function j(t,e){return x(t,e).map(i=>M(i,e))}function M(t,e){if(typeof t!="string")throw new Error(`Playwright native report ${e} must be a string`);return t}function Ft(t,e,i){const s=P(t,`Playwright attachment[${e.toString()}]`),n=k(s.specId,"Playwright attachment.specId");if(!i.has(n))throw new Error("Playwright native attachment references an unknown test identity");const r=R(s.path),o=s.error===void 0?void 0:xt(s.error);if(s.body!==void 0||r===null&&o===void 0)throw new Error("Playwright attachment must contain a path or an error");return{contentType:R(s.contentType)??"application/octet-stream",name:R(s.name)??`attachment-${e.toString()}`,specId:n,...r===null?{}:{path:r},...o===void 0?{}:{error:o},retry:T(s.retry,"Playwright attachment.retry"),specTitle:k(s.specTitle,"Playwright attachment.specTitle")}}function xt(t){const e=P(t,"Playwright attachment.error");if(e.kind==="io")return{kind:"io",message:k(e.message,"Playwright attachment.error.message")};const i=e.kind;if(i!=="individual"&&i!=="total")throw new Error("Playwright attachment.error has an invalid kind");const s=i==="individual"?tt:yt,n=T(e.observed,"Playwright attachment.error.observed");if(e.limit!==s||n<=s)throw new Error("Playwright attachment.error has an invalid limit");return{kind:i,limit:s,observed:n}}function z(t,e){const{name:i,specId:s,specTitle:n,retry:r}=t,o=e.kind==="io"?e.message:`exceeds its ${e.limit.toString()} byte ${e.kind} limit (observed ${e.observed.toString()} bytes)`;return{code:e.kind==="io"?"PLAYWRIGHT_ATTACHMENT_FAILED":"PLAYWRIGHT_ATTACHMENT_LIMIT",...e.kind==="io"?{classification:"infra"}:{},details:{name:i,specId:s,specTitle:n,retry:r,...e},message:`Playwright attachment "${i}" (${n}, retry ${r.toString()}): ${o}`}}async function At(t,e,i,s,n){const r=[],o=[],c=new Set;let p=0;const m=g.join(e,"attachments");s.length>0&&await v.mkdir(m,{mode:448,recursive:!1});for(const[h,a]of s.entries())try{if(a.error!==void 0){a.path!==void 0&&c.add(g.resolve(i,a.path)),o.push(z(a,a.error));continue}const d=await Nt(a.path,i,t,n);c.add(d.file);const w=T(Number(d.identity.size),"Playwright attachment size"),E=mt(w,p+w);if(E!==null){o.push(z(a,E));continue}const l=await U(d.file,tt,"Playwright attachment",n,d.identity,m,`${h.toString().padStart(4,"0")}-${at(a.name)}${It(a)}`);p+=l.identity.sizeBytes,r.push({path:l.filePath,contentType:a.contentType,kind:"engine.playwright-attachment",name:a.name,summary:`${a.specTitle} retry ${a.retry.toString()}`,metadata:{...l.identity,specId:a.specId,specTitle:a.specTitle,retry:a.retry}})}catch(d){o.push(z(a,gt(d)))}return{artifacts:r,failures:o,sourcePaths:c}}async function _t(t,e,i,s,n){try{const r=await n.lstat(i);if(!r.isDirectory()||r.isSymbolicLink())throw new Error("Playwright output directory must be a non-symbolic-link directory");const o=await v.realpath(i);if(!N(t,o))throw new Error("Playwright output directory escaped the artifact root");const c=await $t(o,s,n),p=[],m=g.join(e,"output");c.candidates.length>0&&await v.mkdir(m,{mode:448,recursive:!1});for(const[h,a]of c.candidates.entries()){const d=await U(a.file,I,"Playwright output file",n,a.identity,m,`${h.toString().padStart(5,"0")}-${at(g.basename(a.file))}${jt(a.file)}`);p.push(O(d.filePath,d.identity,Lt(a.file),"engine.playwright-output",a.relativePath,"Playwright output"))}return{artifacts:p,bytes:c.bytes,entries:c.entries}}catch(r){if(ut(r))return{artifacts:[],bytes:0,entries:0};throw r}}async function $t(t,e,i){const s=[];let n=0,r=0;const o=[{depth:0,directory:t}];for(;o.length>0;){const c=o.pop();if(c===void 0)continue;if(c.depth>it)throw new Error(`Playwright output exceeds the ${it.toString()} level directory depth limit`);const p=c.directory,m=await v.readdir(p,{withFileTypes:!0});m.sort((h,a)=>h.name.localeCompare(a.name));for(const h of m){if(r+=1,r>et)throw new L({bytes:n,entries:r,kind:"entries",limit:et,observed:r});const a=g.join(p,h.name),d=await i.lstat(a);if(d.isSymbolicLink())throw new Error("Playwright output must not contain symbolic links");if(d.isDirectory()){o.push({depth:c.depth+1,directory:a});continue}if(!d.isFile())continue;if(d.size<0n||d.size>BigInt(Number.MAX_SAFE_INTEGER))throw new Error("Playwright output file has an invalid size");const w=Number(d.size);if(n+=w,!Number.isSafeInteger(n)||n>I)throw new L({bytes:n,entries:r,kind:"bytes",limit:I,observed:n});e.has(a)||s.push({file:a,identity:d,relativePath:Q(t,a)})}}return{bytes:n,candidates:s,entries:r}}function Mt(t){return t.kind==="bytes"?`Playwright output exceeds its ${t.limit.toString()} byte aggregate limit (observed ${t.observed.toString()} bytes)`:`Playwright output exceeds its ${t.limit.toString()} entry limit (observed ${t.observed.toString()} entries)`}async function Nt(t,e,i,s){if(t===void 0)throw new Error("Playwright path attachment did not declare a path");const n=g.resolve(e,t),r=await s.lstat(n);if(!r.isFile()||r.isSymbolicLink())throw new Error("Playwright attachment path must be a regular non-symbolic-link file");const o=await v.realpath(n);if(!N(e,o)&&!N(i,o))throw new Error("Playwright attachment path must stay within the consumer or artifact root");return{file:o,identity:r}}function Ot(t){const e=P(t,"Playwright report.stats");return{expected:T(e.expected,"Playwright stats.expected"),unexpected:T(e.unexpected,"Playwright stats.unexpected"),flaky:T(e.flaky,"Playwright stats.flaky"),skipped:T(e.skipped,"Playwright stats.skipped"),duration:J(e.duration,"Playwright stats.duration")}}function Rt(t){let e=vt;const i=[];for(const s of t){if(e<=0)break;const r=Buffer.from(s.text,"utf8").subarray(0,e).toString("utf8");r.length>0&&i.push({...s,text:r}),e-=Buffer.byteLength(r)}return e<=0&&i.push({stream:"engine",text:"Playwright report log evidence was truncated at its bounded limit"}),i}function It(t){if(t.path!==void 0){const e=g.extname(t.path);if(/^\.[a-z0-9]{1,12}$/iu.test(e))return e}return t.contentType==="application/json"?".json":t.contentType.startsWith("text/")?".txt":t.contentType==="image/png"?".png":t.contentType==="image/jpeg"?".jpg":".bin"}function Lt(t){const e=g.extname(t).toLowerCase();return e===".json"?"application/json":e===".zip"?"application/zip":e===".png"?"image/png":e===".jpg"||e===".jpeg"?"image/jpeg":e===".webm"?"video/webm":[".log",".txt",".md"].includes(e)?"text/plain; charset=utf-8":"application/octet-stream"}function jt(t){const e=g.extname(t).toLowerCase();return/^\.[a-z0-9]{1,12}$/u.test(e)?e:".bin"}function at(t){const e=t.trim().toLowerCase().replace(/[^a-z0-9._-]+/gu,"-").replace(/^-+|-+$/gu,"").slice(0,80);return e.length>0?e:"attachment"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import
|
|
1
|
+
import h from"node:path";import M from"node:fs/promises";import U from"node:crypto";import{stripVTControlCharacters as D}from"node:util";import{writeNativeReport as L}from"../../adapters/native-report.js";import{writeOwnedEvidenceFile as P}from"../../adapters/evidence-files.js";import{boundEnvironmentValueMissingText as V,environmentValueMissingFailure as j,readEnvironmentValueMissingText as F}from"../../contracts/environment-values.js";import{attachmentIoError as C,attachmentLimitError as O}from"./attachments.js";export default class S{options;config;suite;errors=[];missing=[];constructor(t){this.options=t}onBegin(t,r){this.config=t,this.suite=r}onError(t){this.missing.push(...x(t,!1)),this.errors.push(d(g(t)))}async onEnd(t){const r=this.suite.allTests(),o={duration:t.duration,expected:0,flaky:0,skipped:0,unexpected:0},p=[],c=[];let f=0;const y=[];for(const i of r){const v=i.outcome();o[v]+=1;let E=0,m=0,T=[],w=null;const k=[],R=i.parent.project()?.use.baseURL;for(const a of i.results){for(const n of a.errors)k.push(...x(n,!R));E+=a.duration,m=Math.max(m,a.retry);for(const n of["stdout","stderr"])for(const s of a[n])p.push({stream:n,text:typeof s=="string"?s:s.toString("utf8")});for(const n of a.attachments){const s={name:n.name,contentType:n.contentType,...n.path===void 0?{}:{path:n.path},specId:i.id,specTitle:i.title,retry:a.retry};try{let l=n.body?.byteLength;if(l===void 0){if(n.path===void 0)throw new Error("Attachment has no body or path");const u=await M.lstat(n.path);if(!u.isFile()||u.isSymbolicLink())throw new Error("Attachment path must be a regular non-symbolic-link file");l=u.size}const b=O(l,f+l);if(b!==null){c.push({...s,error:b});continue}let A=n.path;if(n.body!==void 0){const u=this.options.attachmentDirectory;if(await M.realpath(u)!==h.resolve(u))throw new Error("Attachment directory must not resolve through symbolic links");A=await P(u,U.randomUUID(),n.body)}c.push({...s,path:A}),f+=l}catch(l){c.push({...s,error:C(l)})}}if(a.errors.length>0){T=a.errors.map(s=>d(g(s)));const n=a.errors.find(s=>s.stack)?.stack;w=n===void 0?null:d(n)}}y.push({id:i.id,title:i.title,parents:X(i,this.config.rootDir),file:I(this.config.rootDir,i.location.file),sourceFile:Z(i,this.config.rootDir),projectName:i.parent.project()?.name??"",line:i.location.line,column:i.location.column,status:v,durationMs:E,retries:m,failureMessages:T,failureStack:w,...N(k)})}await L(this.options,{status:t.status,failOnFlakyTests:this.options.failOnFlakyTests,stats:o,specs:y,logs:p,attachments:c,errors:this.errors,...N(this.missing)},64*1024*1024)}}const z=8,_=/^(?:\w*Error: )?page\.goto: .*Cannot navigate to invalid URL/u,G=/^\s*- navigating to "([^"]*)"/mu,B=/^[A-Za-z][A-Za-z\d+.-]*:/u;function x(e,t){const r=[];let o=e;for(let p=0;p<z&&o!==void 0;p+=1){const c=g(o),f=[...F(c),...t?H(c):[]];f.length>0&&r.push({message:c,values:f}),o=o.cause}return r}function H(e){const t=D(e);if(!_.test(t))return[];const r=G.exec(t)?.[1];return r===void 0||B.test(r)?[]:[{kind:"endpoint",valueName:null}]}function N(e){const t=e.at(0);return t===void 0?{}:{environmentFailure:j(e.flatMap(({values:r})=>r),t.message)}}function d(e){return F(e).length===0?e:V(e)}function Z(e,t){for(let r=e.parent;r;r=r.parent)if(r.type==="file")return h.resolve(t,r.title);return e.location.file}function X(e,t){const r=[];for(let o=e.parent;o&&o.type!=="project"&&o.type!=="root";o=o.parent)r.unshift(o.type==="file"&&o.location?I(t,o.location.file):o.title);return r}function I(e,t){return h.relative(e,t).split(h.sep).join("/")}function g(e){return e.message?.trim()||e.stack?.trim()||e.value?.trim()||"Playwright reported an error"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import
|
|
1
|
+
import f from"node:fs";import i from"node:path";import{hasErrorCode as c}from"../../../kernel/error-serialization.js";export const PLAYWRIGHT_CONFIG_FILENAMES=Object.freeze(["playwright.config.ts","playwright.config.mts","playwright.config.js","playwright.config.mjs","playwright.config.cjs","playwright.config.cts"]);export function findPlaywrightConfigFile(e){for(const o of PLAYWRIGHT_CONFIG_FILENAMES){const r=i.join(e,o);try{if(f.statSync(r).isFile())return r}catch(t){if(c(t,"ENOENT")||c(t,"ENOTDIR"))continue;throw new Error(`Could not inspect optional support module ${r}`,{cause:t})}}return null}export function findNearestPlaywrightConfigFile(e,o){const r=i.resolve(e);let t=i.resolve(r,s(o));const n=i.relative(r,t);for((n.split(i.sep)[0]===".."||i.isAbsolute(n))&&(t=r);;){const l=findPlaywrightConfigFile(t);if(l!==null||t===r)return l;t=i.dirname(t)}}function s(e){if(e.length===0)return".";const[o,...r]=e.map(n=>i.posix.normalize(n).split("/").filter(l=>l!==""&&l!=="."));let t=0;for(;t<o.length&&r.every(n=>n[t]===o[t]);)t+=1;return o.slice(0,t).join("/")||"."}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{DEFAULT_FILE_TIMEOUT_SECONDS as
|
|
1
|
+
import{DEFAULT_FILE_TIMEOUT_SECONDS as h,INTERNAL_FILE_TIMEOUT_SECONDS_ENV as E}from"../../../domain/file-timeout.js";import{readPlaywrightContext as T}from"./runtime-input.js";import{defineConfig as b}from"@playwright/test";import{isUnknownRecord as p}from"../../../kernel/unknown-values.js";const y=["cwd","dotenvFiles","onlyWhenAllowed","override"];export function defineTestkitConfig(e={},t={}){const n=y.filter(w=>Object.hasOwn(t,w));if(n.length>0)throw new Error(`defineTestkitConfig no longer loads dotenv files, so it does not accept ${n.join(", ")}. In a Testkit run, the services your tests use already provide their values. To load a file when you run Playwright on its own, use a dotenv library of your own in playwright.config.ts.`);const r=t.env||process.env,o=S(r,t.defaultFileTimeoutSeconds)*1e3,i=T(),s=i?.managed===!0,u=l(e.use,"Playwright config.use"),d=l(e.expect,"Playwright config.expect"),f=O(u.baseURL,"Playwright config.use.baseURL"),a=i?.baseUrl??r.BASE_URL??f,m={...u,...a?{baseURL:a}:{},actionTimeout:o,navigationTimeout:o},g={...e,...s?{globalTimeout:o}:{},timeout:o,expect:{...d,timeout:o},use:m,...s?{webServer:void 0}:{}};return b(g)}function S(e,t){const n=e[E],r=c(t??h);return n==null?r:c(n)}function c(e){const t=Number(e);if(!Number.isInteger(t)||t<=0)throw new Error("Playwright file timeout seconds must be a positive integer.");return t}function l(e,t){if(e==null)return{};if(!p(e))throw new Error(`${t} must be an object`);return e}function O(e,t){if(e!=null){if(typeof e!="string")throw new Error(`${t} must be a string`);return e}}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import l from"node:fs/promises";import c from"node:path";import{writeOwnedRuntimeInput as m,ownedRuntimeInputModuleUrl as f}from"../../runtime-input-file.js";import{requireBoundedJsonValue as y,RUNTIME_INPUT_JSON_BOUNDS as h}from"../../
|
|
1
|
+
import l from"node:fs/promises";import c from"node:path";import{writeOwnedRuntimeInput as m,ownedRuntimeInputModuleUrl as f}from"../../runtime-input-file.js";import{requireBoundedJsonValue as y,RUNTIME_INPUT_JSON_BOUNDS as h}from"../../adapters/json-bounds.js";import{ENGINE_PROCESS_RESERVED_ENVIRONMENT_KEYS as w}from"../../../process/environment.js";import{managedProcessEnvironmentOverlayInstallerSource as g}from"../../../process/environment-overlay.js";import{isUnknownRecord as u}from"../../../kernel/unknown-values.js";export const PLAYWRIGHT_RUNTIME_INPUT_MAX_BYTES=4*1024*1024,PLAYWRIGHT_RUNTIME_ENVIRONMENT_MAX_BYTES=2*1024*1024,PLAYWRIGHT_RUNTIME_ENVIRONMENT_MAX_ENTRIES=512;const d=new Set(["BASE_URL","FORCE_COLOR","NODE_OPTIONS","NO_COLOR","PLAYWRIGHT_BROWSERS_PATH","PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD","TESTKIT_ACTIVE","TESTKIT_INTERNAL_FILE_DEADLINE_MS","TESTKIT_INTERNAL_FILE_TIMEOUT_SECONDS","TESTKIT_INVOCATION_ID","TESTKIT_RUNTIME_ID","TESTKIT_TEST_FILE","TESTKIT_TEST_ID",...w].map(e=>e.toUpperCase())),p={filename:"runtime-input.json",label:"Playwright runtime input",maxSizeBytes:PLAYWRIGHT_RUNTIME_INPUT_MAX_BYTES},E=Symbol.for("@gfdelarue/testkit/playwright-runtime-input/v1");export function readPlaywrightContext(){const e=Reflect.get(globalThis,E);return T(e)?e.context:null}export async function materializePlaywrightRuntimeInput(e){if(!c.isAbsolute(e.directory))throw new Error("Playwright runtime-input directory must be absolute");await l.mkdir(e.directory,{recursive:!0,mode:448}),process.platform!=="win32"&&await l.chmod(e.directory,448);const t=I(e.inputs.environment),i={baseUrl:e.baseUrl===null?null:v(e.baseUrl),databases:e.databases,endpoints:e.endpoints,engineId:"playwright",environment:t,fixtures:e.inputs.fixtures,handles:e.handles,invocationId:e.invocationId,managed:!0,schemaVersion:1,taskId:e.taskId,uiConfig:e.inputs.configuration??{},...e.inputs.setupData===void 0?{}:{setupData:e.inputs.setupData}},o=await m(e.directory,i,p);return{digest:o.sha256,file:o.file,sizeBytes:o.sizeBytes}}export function playwrightRuntimeInputBootstrapSource(e){const t=JSON.stringify({digest:e.digest,file:e.file,ownedInput:{directory:c.dirname(e.file),file:e.file,sha256:e.digest,sizeBytes:e.sizeBytes},protocol:p,invocationId:e.invocationId,jsonBounds:h,maximumEnvironmentBytes:PLAYWRIGHT_RUNTIME_ENVIRONMENT_MAX_BYTES,maximumEnvironmentEntries:PLAYWRIGHT_RUNTIME_ENVIRONMENT_MAX_ENTRIES,reservedEnvironmentKeys:[...d],taskId:e.taskId}),n=g(),i=`const requireBoundedJsonValue = (${y.toString()});`;return`
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { readVerifiedOwnedFile } from ${JSON.stringify(f)};
|
|
4
4
|
|
|
5
5
|
${n}
|
|
6
|
-
${
|
|
6
|
+
${i}
|
|
7
7
|
const OPTIONS = ${t};
|
|
8
8
|
const STATE = Symbol.for("@gfdelarue/testkit/playwright-runtime-input/v1");
|
|
9
9
|
|
|
@@ -31,9 +31,11 @@ export async function installPlaywrightRuntimeInput() {
|
|
|
31
31
|
});
|
|
32
32
|
const context = Object.freeze({
|
|
33
33
|
baseUrl: input.baseUrl,
|
|
34
|
+
databases: input.databases,
|
|
34
35
|
endpoints: input.endpoints,
|
|
35
36
|
env: input.environment,
|
|
36
37
|
fixtures: input.fixtures,
|
|
38
|
+
handles: input.handles,
|
|
37
39
|
managed: true,
|
|
38
40
|
...(input.setupData === undefined ? {} : { setupData: input.setupData }),
|
|
39
41
|
uiConfig: input.uiConfig,
|
|
@@ -68,11 +70,11 @@ function deepFreezeJson(root) {
|
|
|
68
70
|
|
|
69
71
|
function validateRuntimeInput(value) {
|
|
70
72
|
const input = requireRecord(value, "Playwright runtime input");
|
|
71
|
-
const allowed = new Set(["baseUrl", "endpoints", "engineId", "environment", "fixtures", "invocationId", "managed", "schemaVersion", "setupData", "taskId", "uiConfig"]);
|
|
73
|
+
const allowed = new Set(["baseUrl", "databases", "endpoints", "engineId", "environment", "fixtures", "handles", "invocationId", "managed", "schemaVersion", "setupData", "taskId", "uiConfig"]);
|
|
72
74
|
for (const key of Object.keys(input)) {
|
|
73
75
|
if (!allowed.has(key)) throw new Error("Playwright runtime input contains unsupported field " + key);
|
|
74
76
|
}
|
|
75
|
-
for (const key of ["baseUrl", "endpoints", "engineId", "environment", "fixtures", "invocationId", "managed", "schemaVersion", "taskId", "uiConfig"]) {
|
|
77
|
+
for (const key of ["baseUrl", "databases", "endpoints", "engineId", "environment", "fixtures", "handles", "invocationId", "managed", "schemaVersion", "taskId", "uiConfig"]) {
|
|
76
78
|
if (!Object.prototype.hasOwnProperty.call(input, key))
|
|
77
79
|
throw new Error("Playwright runtime input is missing field " + key);
|
|
78
80
|
}
|
|
@@ -80,29 +82,32 @@ function validateRuntimeInput(value) {
|
|
|
80
82
|
throw new Error("Playwright runtime input has an unsupported identity");
|
|
81
83
|
if (input.managed !== true)
|
|
82
84
|
throw new Error("Playwright runtime input must be managed by Testkit");
|
|
83
|
-
if (
|
|
84
|
-
throw new Error("Playwright runtime input.baseUrl must be a non-empty string");
|
|
85
|
-
let parsedBaseUrl;
|
|
86
|
-
try {
|
|
87
|
-
parsedBaseUrl = new URL(input.baseUrl);
|
|
88
|
-
} catch (error) {
|
|
89
|
-
throw new Error("Playwright runtime input.baseUrl must be a valid URL", { cause: error });
|
|
90
|
-
}
|
|
91
|
-
if ((parsedBaseUrl.protocol !== "http:" && parsedBaseUrl.protocol !== "https:") || parsedBaseUrl.href !== input.baseUrl)
|
|
92
|
-
throw new Error("Playwright runtime input.baseUrl must be a canonical HTTP(S) URL");
|
|
85
|
+
if (input.baseUrl !== null) validateBaseUrl(input.baseUrl);
|
|
93
86
|
if (input.invocationId !== OPTIONS.invocationId || input.taskId !== OPTIONS.taskId)
|
|
94
87
|
throw new Error("Playwright runtime input does not match its invocation and task");
|
|
95
|
-
|
|
88
|
+
requireNamedValues(input.databases, "Playwright runtime input.databases");
|
|
89
|
+
requireNamedValues(input.endpoints, "Playwright runtime input.endpoints");
|
|
90
|
+
requireHandles(input.handles, "Playwright runtime input.handles");
|
|
96
91
|
validateEnvironment(input.environment);
|
|
97
92
|
requireRecord(input.fixtures, "Playwright runtime input.fixtures");
|
|
98
93
|
requireRecord(input.uiConfig, "Playwright runtime input.uiConfig");
|
|
99
|
-
requireBoundedJsonValue(input, "Playwright runtime input", OPTIONS.jsonBounds
|
|
100
|
-
unitLabel: "bytes",
|
|
101
|
-
unitsOf: (text) => Buffer.byteLength(text, "utf8"),
|
|
102
|
-
});
|
|
94
|
+
requireBoundedJsonValue(input, "Playwright runtime input", OPTIONS.jsonBounds);
|
|
103
95
|
return input;
|
|
104
96
|
}
|
|
105
97
|
|
|
98
|
+
function validateBaseUrl(value) {
|
|
99
|
+
if (typeof value !== "string" || value.trim().length === 0)
|
|
100
|
+
throw new Error("Playwright runtime input.baseUrl must be null or a non-empty string");
|
|
101
|
+
let parsed;
|
|
102
|
+
try {
|
|
103
|
+
parsed = new URL(value);
|
|
104
|
+
} catch (error) {
|
|
105
|
+
throw new Error("Playwright runtime input.baseUrl must be a valid URL", { cause: error });
|
|
106
|
+
}
|
|
107
|
+
if ((parsed.protocol !== "http:" && parsed.protocol !== "https:") || parsed.href !== value)
|
|
108
|
+
throw new Error("Playwright runtime input.baseUrl must be a canonical HTTP(S) URL");
|
|
109
|
+
}
|
|
110
|
+
|
|
106
111
|
function validateEnvironment(value) {
|
|
107
112
|
const environment = requireStringRecord(value, "Playwright runtime input.environment");
|
|
108
113
|
const keys = Object.keys(environment);
|
|
@@ -132,6 +137,24 @@ function validateEnvironmentEntry(key, value) {
|
|
|
132
137
|
throw new Error("Playwright runtime input.environment contains an invalid value for " + key);
|
|
133
138
|
}
|
|
134
139
|
|
|
140
|
+
function requireNamedValues(value, label) {
|
|
141
|
+
const record = requireRecord(value, label);
|
|
142
|
+
for (const [key, entry] of Object.entries(record)) {
|
|
143
|
+
if (key.length === 0 || typeof entry !== "string" || entry.length === 0 || entry.includes("\\0"))
|
|
144
|
+
throw new Error(label + " must map names to non-empty strings");
|
|
145
|
+
}
|
|
146
|
+
return record;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function requireHandles(value, label) {
|
|
150
|
+
const record = requireRecord(value, label);
|
|
151
|
+
for (const [name, descriptor] of Object.entries(record)) {
|
|
152
|
+
if (name.length === 0 || typeof descriptor !== "object" || descriptor === null || Array.isArray(descriptor) || typeof descriptor.kind !== "string" || descriptor.kind.length === 0)
|
|
153
|
+
throw new Error(label + " must map names to handle descriptors with a kind");
|
|
154
|
+
}
|
|
155
|
+
return record;
|
|
156
|
+
}
|
|
157
|
+
|
|
135
158
|
function requireStringRecord(value, label) {
|
|
136
159
|
const record = requireRecord(value, label);
|
|
137
160
|
for (const [key, entry] of Object.entries(record)) {
|
|
@@ -148,4 +171,4 @@ function requireRecord(value, label) {
|
|
|
148
171
|
}
|
|
149
172
|
|
|
150
173
|
await installPlaywrightRuntimeInput();
|
|
151
|
-
`}function T(e){return!u(e)||!u(e.context)||!u(e.input)?!1:typeof e.digest=="string"&&typeof e.file=="string"&&e.input.engineId==="playwright"&&e.input.schemaVersion===1&&Object.isFrozen(e)&&Object.isFrozen(e.context)&&Object.isFrozen(e.input)}function
|
|
174
|
+
`}function T(e){return!u(e)||!u(e.context)||!u(e.input)?!1:typeof e.digest=="string"&&typeof e.file=="string"&&e.input.engineId==="playwright"&&e.input.schemaVersion===1&&Object.isFrozen(e)&&Object.isFrozen(e.context)&&Object.isFrozen(e.input)}function I(e){const t=Object.create(null),n=new Set;let i=0;const o=Object.entries(e);if(o.length>PLAYWRIGHT_RUNTIME_ENVIRONMENT_MAX_ENTRIES)throw new Error(`Playwright consumer environment exceeds its ${PLAYWRIGHT_RUNTIME_ENVIRONMENT_MAX_ENTRIES.toString()} entry limit`);for(const[a,s]of o){b(a,s);const r=a.toUpperCase();if(n.has(r))throw new Error(`Playwright consumer environment contains case-insensitive duplicate key ${a}`);if(n.add(r),r.startsWith("TESTKIT_")||r.startsWith("PLAYWRIGHT_")||r.startsWith("PWTEST_")||r.startsWith("PW_TEST_")||d.has(r))throw new Error(`Playwright consumer environment contains reserved key ${a}`);if(i+=Buffer.byteLength(a,"utf8")+Buffer.byteLength(s,"utf8")+2,i>PLAYWRIGHT_RUNTIME_ENVIRONMENT_MAX_BYTES)throw new Error(`Playwright consumer environment exceeds its ${PLAYWRIGHT_RUNTIME_ENVIRONMENT_MAX_BYTES.toString()} byte limit`);t[a]=s}return t}function v(e){if(typeof e!="string"||e.trim().length===0)throw new Error("Playwright runtime input base URL must be non-empty");let t;try{t=new URL(e)}catch(n){throw new Error("Playwright runtime input base URL must be a valid URL",{cause:n})}if(t.protocol!=="http:"&&t.protocol!=="https:")throw new Error("Playwright runtime input base URL must use HTTP or HTTPS");return t.href}function b(e,t){if(e.length===0||e.includes("=")||e.includes("\0")||typeof t!="string")throw new Error("Playwright consumer environment contains an invalid key");if(t.includes("\0"))throw new Error(`Playwright consumer environment contains an invalid value for ${e}`)}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import
|
|
1
|
+
import m from"node:crypto";import a from"node:fs/promises";import f from"node:path";import{serializeBoundedJson as c,RUNTIME_INPUT_JSON_BOUNDS as h}from"./adapters/json-bounds.js";import{readStableEvidenceFile as y,evidenceFileAccess as b}from"./adapters/evidence-files.js";export const ownedRuntimeInputModuleUrl=new URL("../../dist/engines/runtime-input-file.js",import.meta.url).href;export async function writeOwnedRuntimeInput(i,e,t){const r=c(e,t.label,h),s=await d(i,t.label),w=Buffer.byteLength(r);if(w>t.maxSizeBytes)throw new Error(`${t.label} exceeds the ${t.maxSizeBytes.toString()} byte limit`);const o=f.join(s,t.filename),l=f.join(s,`.${t.filename}.${process.pid.toString()}.${m.randomUUID()}.tmp`);let n=null;try{n=await a.open(l,"wx",384),await n.writeFile(r,"utf8"),await n.close(),n=null,await a.rename(l,o),await a.chmod(o,384)}catch(u){throw await n?.close().catch(()=>{}),await a.rm(l,{force:!0}).catch(()=>{}),u}return{directory:s,file:o,sha256:m.createHash("sha256").update(r,"utf8").digest("hex"),sizeBytes:w}}export async function readVerifiedOwnedFile(i,e){const t=await d(i.directory,e.label);if(f.dirname(i.file)!==t)throw new Error(`${e.label} escaped its owned task directory`);const r=await a.lstat(i.file,{bigint:!0});if(!r.isFile()||r.isSymbolicLink())throw new Error(`${e.label} must be an owned regular file`);if(r.size!==BigInt(i.sizeBytes)||r.size>BigInt(e.maxSizeBytes))throw new Error(`${e.label} size changed after preparation`);if(process.platform!=="win32"&&(r.mode&63n)!==0n)throw new Error(`${e.label} permissions must be owner-only`);const s=await a.realpath(i.file);if(s!==i.file||f.dirname(s)!==t)throw new Error(`${e.label} resolved outside its owned task directory`);const{contents:w,sha256:o}=await y(s,e.maxSizeBytes,e.label,b,r),l=Buffer.from(i.sha256),n=Buffer.from(o);if(l.length!==n.length||!m.timingSafeEqual(n,l))throw new Error(`${e.label} integrity check failed`);return w.toString("utf8")}async function d(i,e){if(!f.isAbsolute(i))throw new Error(`${e} directory must be absolute`);const t=await a.realpath(i);if(!(await a.stat(t)).isDirectory())throw new Error(`${e} directory must be a directory`);return t}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import o from"fs";import a from"path";import{finalizeLiveRunArtifact as
|
|
1
|
+
import o from"fs";import a from"path";import{finalizeLiveRunArtifact as e}from"../evidence/index.js";import{isUnknownRecord as u}from"../kernel/unknown-values.js";export function reconcileInactiveRunArtifact(n,t){typeof t.runId=="string"&&e(n,{runId:t.runId,reason:"stale run process not active",status:"interrupted"})}export function reconcileOrphanedLiveRunArtifact(n,{activeRunIds:t=new Set}={}){const r=f(n),i=r?.run.id||null;return!i||r?.run.status!=="running"||t.has(i)?!1:e(n,{runId:i,reason:"stale live artifact has no active run manifest",status:"interrupted"})}function f(n){try{const t=JSON.parse(o.readFileSync(a.join(n,".testkit","results","live.json"),"utf8"));return c(t)}catch{return null}}function c(n){if(!u(n)||!u(n.run))return null;const t=n.run.id,r=n.run.status;return!s(t)||!s(r)?null:{run:{id:t,status:r}}}function s(n){return n===void 0||typeof n=="string"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import H from"crypto";import{isTerminalRunStatus as
|
|
1
|
+
import H from"crypto";import{isTerminalRunStatus as N}from"../process/runs/schema.js";import{observeProcessCreationIdentity as x}from"../process/process-identity.js";export{isRunManifestActive}from"../process/runs/inspection.js";import{normalizeOperationReason as U}from"../domain/operation-reason.js";import{finalizeLiveRunArtifact as W}from"../evidence/index.js";import{captureProcessCreationIdentity as V}from"../process/service-processes.js";import{requireProductLifecycleFenceProductDir as K,withProductLifecycleFence as B}from"../process/lifecycle-fence.js";import{createRunManifest as Y,listRunManifests as J,readRunMaintenanceStopRequest as Q,removeRunManifestFile as _,requireSafeRunId as X,RUN_MANIFEST_SCHEMA_VERSION as Z,runManifestPath as ee,writeRunManifest as te}from"../process/runs/manifest.js";const ne=1e3,re=String,k=new WeakMap;export function createUnpublishedRunLifecycle(n,r={}){const s=r.runId===void 0?ue():X(r.runId,"Testkit run id"),u=ee(n,s),o=new AbortController,I=new AbortController,d=r.pid===void 0?process.pid:r.pid;if(!Number.isSafeInteger(d)||d<0)throw new Error("Testkit run pid must be a non-negative safe integer");const S=d>0?V(d):null;if(d>0&&S===null)throw new Error(`Could not capture the Testkit run process identity for pid ${d.toString()}`);let f={incarnationId:H.randomUUID(),schemaVersion:Z,runId:s,pid:d,processIdentity:typeof S=="string"?S:null,controller:se(r.controller),status:"starting",startedAt:new Date().toISOString(),heartbeatAt:r.heartbeat===!1?null:new Date().toISOString(),interruptReason:null,services:[],runtimeDirs:[]};const D=[];let w,O=null;const y=new Set,b=new Set,M=r.keepAlive===!0?setInterval(()=>{},ne):null;let R=null,g=null,v=null,L=!1;function $(e){const t=k.get(h);if(!t)throw new Error("Testkit run lifecycle ownership is unavailable");if(!t.published){Y(n,e),t.published=!0;return}te(n,e)}function A(){const e=Q(n,s);return e===null||e.targetIncarnationId!==f.incarnationId||e.targetPid!==d||e.targetProcessIdentity!==f.processIdentity||e.coordinatorPid===O?.coordinatorPid&&e.coordinatorProcessIdentity===O.coordinatorProcessIdentity?null:x(e.coordinatorPid,e.coordinatorProcessIdentity)==="different"?(O=e,null):e}function m(e){T("mutate run state");const t=ie(f);e(t),t.heartbeatAt!==null&&(t.heartbeatAt=new Date().toISOString()),$(t),f=t}function T(e){if(g!==null)throw new Error(`Cannot ${e} after Testkit run ${s} finalization is committed`)}function G(){R||(R=setInterval(()=>{},1e3))}function P(){R&&(clearInterval(R),R=null)}function q(){for(const e of b)clearInterval(e);b.clear()}function z(e="controller process exited before Testkit run finalized"){if(L||N(f.status))return!1;const t=U(e,"controller process exited before Testkit run finalized"),i=new Date,a=f.status==="interrupting"||o.signal.aborted?"interrupted":"failed",l=a==="interrupted"?f.interruptReason??v??t:t;return m(p=>{p.status=a,p.finishedAt=i.toISOString(),p.interruptReason=l,p.heartbeatAt!==null&&(p.heartbeatAt=i.toISOString())}),W(n,{runId:s,reason:l,redactKeys:r.redactKeys,redactionTargets:r.redactionTargets?.(),status:a,finishedAt:i}),!0}const F=()=>{z()};process.on("exit",F);const h={runId:s,manifestPath:u,maintenanceStopSignal:I.signal,signal:o.signal,commitFinalization(e="finished"){if(g!==null)return g;const t=A(),i=o.signal.aborted||t!==null||f.status==="interrupting",a=i?f.interruptReason??v??t?.reason??"run interrupted":null,l=Object.freeze({interruptReason:a,interrupted:i});return m(p=>{p.status=i?"interrupted":e,p.finishedAt=new Date().toISOString(),p.interruptReason=a}),g=l,q(),l},getInterruptReason(){return f.interruptReason??v},isMaintenanceStopCoordinated(){return A()!==null},isStopRequested(){return o.signal.aborted||g?.interrupted===!0},markRunning(){m(e=>{e.status="running"})},markFinished(e="finished"){m(t=>{t.status=e,t.finishedAt=new Date().toISOString()})},heartbeat(e={}){m(t=>{t.heartbeatAt=new Date().toISOString(),e&&typeof e=="object"&&!Array.isArray(e)&&(t.session={...t.session||{},...e})})},startHeartbeat(e=5e3,t=null){T("start a run heartbeat");const i=Number.isFinite(Number(e))&&Number(e)>0?Math.floor(Number(e)):5e3,a=setInterval(()=>{let l;try{l=typeof t=="function"?t():{}}catch{l={}}h.heartbeat(l)},i);return a.unref(),b.add(a),()=>{clearInterval(a),b.delete(a)}},requestStop(e="interrupted"){if(g!==null||N(f.status))return;const t=A(),i=t?t.reason:U(e,"interrupted"),a=!o.signal.aborted;a&&(v=i),G();let l=null;if(a)try{m(c=>{c.status="interrupting",c.interruptReason=i})}catch(c){l=c instanceof Error?c:new Error("Failed to persist the Testkit stop request",{cause:c})}t!==null&&!I.signal.aborted&&I.abort(new Error(`Testkit run ${s} is being stopped by external maintenance`));const p=[...y].map(({supervisor:c})=>c.stop(t===null?void 0:Date.parse(t.requestedAt)+c.shutdownTimeoutMs));if(Promise.allSettled(p).then(P),o.signal.aborted||o.abort(new Error(`testkit run interrupted (${i})`)),!!a&&l!==null)throw l},trackGraphContext(e){m(t=>{ae(t.runtimeDirs,e.runtimeDir)})},registerService(e,t,i,a){if(T("register application service ownership"),i.pid!==t.pid||(process.platform==="win32"?i.recovery.processGroupId!==null:i.recovery.processGroupId!==i.pid))throw new Error("Application service supervisor returned an invalid ownership handoff");const l={supervisor:t,unsubscribe:()=>{}};y.add(l);const p=oe(e);m(c=>{c.services=c.services.filter(C=>C.pid!==i.pid),c.services.push({serviceName:e.name,runtimeLabel:e.runtimeLabel,command:e.testkit.local.start||null,cwd:a,pid:i.pid,processGroupId:i.recovery.processGroupId,processIdentity:i.recovery.creationIdentity,ports:p,startedAt:new Date().toISOString(),shutdownTimeoutMs:t.shutdownTimeoutMs,shutdownDeadlineAt:t.shutdownDeadlineAt})}),l.unsubscribe=t.onShutdownStarted(c=>{m(C=>{const E=C.services.find(j=>j.pid===i.pid);E&&(E.shutdownDeadlineAt=E.shutdownDeadlineAt==null?c:Math.min(E.shutdownDeadlineAt,c))})})},unregisterService(e){T("unregister application service ownership");for(const t of y)t.supervisor.pid===e&&(t.unsubscribe(),y.delete(t));m(t=>{t.services=t.services.filter(i=>i.pid!==e)})},installSignalHandlers(){if(!(D.length>0)&&!(d!==process.pid||x(d,f.processIdentity)!=="matches")){for(const e of["SIGINT","SIGTERM","SIGHUP"]){const t=h.requestStop.bind(h,e);process.on(e,t),D.push([e,t])}process.platform==="win32"&&(w=setInterval(()=>{const e=A();e!==null&&(clearInterval(w),h.requestStop(e.reason))},100),w.unref(),b.add(w))}},removeSignalHandlers(){w&&(clearInterval(w),b.delete(w),w=void 0);for(const[e,t]of D.splice(0))process.off(e,t)},async removeManifest(){await B(n,e=>cleanupOwnedRunLifecycleWithinLifecycleFence(e,h))},finalizeForControllerExit:z,dispose(){L=!0;for(const e of y)e.unsubscribe();process.off("exit",F),h.removeSignalHandlers(),M&&clearInterval(M),P(),q()}};return k.set(h,{incarnationId:f.incarnationId,pid:d,processIdentity:f.processIdentity,productDir:n,published:!1,runId:s}),h}function ie(n){const r={...n,controller:n.controller===null?null:{...n.controller},runtimeDirs:[...n.runtimeDirs],services:n.services.map(s=>({...s,ports:s.ports.map(u=>({...u}))}))};return n.session!==void 0&&(r.session=n.session===null?null:{...n.session}),r}function se(n){return!n||typeof n!="object"||Array.isArray(n)?null:Object.fromEntries(Object.entries(n).filter(([,r])=>r!==void 0).map(([r,s])=>[r,s===null?null:re(s)]))}export function cleanupOwnedRunLifecycleWithinLifecycleFence(n,r){const{manifest:s,ownership:u,productDir:o}=readOwnedRunLifecycleWithinLifecycleFence(n,r);if(!s)return!1;if(s.services.length>0)throw new Error(`Cannot clean Testkit run ${r.runId} service ownership while holding the lifecycle fence`);return _(o,r.runId),u.published=!1,!0}export function readOwnedRunLifecycleWithinLifecycleFence(n,r){const s=K(n),u=k.get(r);if(!u||u.productDir!==s)throw new Error("Cannot clean a Testkit run without matching lifecycle ownership");if(u.runId!==r.runId)throw new Error("Testkit run lifecycle identity has been modified");const o=J(s).find(I=>I.runId===r.runId);if(o!==void 0&&(o.incarnationId!==u.incarnationId||o.pid!==u.pid||o.processIdentity!==u.processIdentity))throw new Error(`Testkit run ${r.runId} ownership no longer matches its manifest`);return{manifest:o??null,ownership:u,productDir:s}}function oe(n){const r=new Set,s=[];for(const u of[n.testkit.local.baseUrl,n.testkit.local.readyUrl])if(u)try{const o=new URL(u),I=le(o.hostname),d=Number(o.port||(o.protocol==="https:"?443:80)),S=`${I}:${d.toString()}`;if(r.has(S))continue;r.add(S),s.push({host:I,port:d})}catch{}return s}function ae(n,r){r&&(n.includes(r)||n.push(r))}function ue(){return`${Date.now().toString()}-${process.pid.toString()}-${H.randomBytes(4).toString("hex")}`}function le(n){return n?n==="::1"?"127.0.0.1":n:"127.0.0.1"}export function disposeFailedRunLifecycle(n){const r=k.get(n);n.dispose(),n.removeSignalHandlers(),r?.published===!0&&_(r.productDir,n.runId)}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{formatRunSummary as w}from"../process/runs/manifest.js";import{cleanupOrphanedLocalInfrastructure as
|
|
1
|
+
import{formatRunSummary as w}from"../process/runs/manifest.js";import{cleanupOrphanedLocalInfrastructure as m,cleanupTerminalRunLocalInfrastructure as R}from"../database/lifecycle-cleanup.js";import{resetResultArtifacts as y}from"../evidence/index.js";import{requireProductLifecycleFenceProductDir as p,withProductLifecycleFence as l}from"../process/lifecycle-fence.js";import{listRunManifests as u,removeRunManifestFile as I,requireSafeRunId as A}from"../process/runs/manifest.js";import{stopRunManifest as L}from"./run-stopping.js";import{createUnpublishedRunLifecycle as k,disposeFailedRunLifecycle as g,isRunManifestActive as o,cleanupOwnedRunLifecycleWithinLifecycleFence as S,readOwnedRunLifecycleWithinLifecycleFence as f}from"./lifecycle-controller.js";import{reconcileInactiveRunArtifact as x,reconcileOrphanedLiveRunArtifact as C}from"./lifecycle-artifacts.js";class h extends Error{constructor(n){super(`Stale Testkit run ${n} still owns application services and requires phased cleanup`),this.name="StaleRunServiceCleanupRequiredError"}}export async function startRunLifecycle(e,n={},s={}){for(;;){await cleanupStaleRuns(e,s);try{return await l(e,t=>startRunLifecycleWithinLifecycleFence(t,n,s))}catch(t){if(!(t instanceof h))throw t}}}export async function startRunLifecycleWithinLifecycleFence(e,n={},s={}){const t=p(e);v(t),await cleanupRunsWithinLifecycleFence(e,s);const c=u(t).find(i=>!o(i)&&i.services.length>0);if(c!==void 0)throw new h(c.runId);v(t);const r=k(t,n);try{return r.installSignalHandlers(),n.resetResultsBeforePublish===!0&&y(t),r.markRunning(),r}catch(i){throw g(r),i}}function v(e){const n=u(e).find(o);if(n)throw new Error(`Active Testkit run ${w(n)} already owns this product`)}export async function cleanupRuns(e,{includeActive:n=!1,localInfrastructure:s}={}){const t=[],c=[];for(;;){const i=await l(e,()=>u(e).flatMap(a=>{const d=o(a);return n&&d||!d&&a.services.length>0?[{active:d,manifest:a}]:[]}));if(i.length===0)break;for(const a of i)await L(e,a.manifest,{reason:a.active?"cleanup":"stale run process not active"}),a.active?t.push(a.manifest):c.push(a.manifest)}const r=await l(e,i=>cleanupRunsWithinLifecycleFence(i,{localInfrastructure:s}));return{...r,cleaned:[...t,...c,...r.cleaned],stoppedActive:t}}export async function cleanupRunsWithinLifecycleFence(e,{protectedLiveRunIds:n=new Set,localInfrastructure:s=!0}={}){const t=p(e),c=u(t),r={cleaned:[],skippedActive:[],stoppedActive:[]};for(const i of c){if(o(i)||i.services.length>0){r.skippedActive.push(i);continue}x(t,i),I(t,A(i.runId,"Testkit run manifest runId")),r.cleaned.push(i)}return C(t,{activeRunIds:new Set([...r.skippedActive.map(i=>i.runId).filter(i=>typeof i=="string"),...n])}),r.resourceCleanup=s?await m(t):{kept:[],removed:[],skipped:[],stopped:[],targets:[]},{cleaned:r.cleaned,resourceCleanup:r.resourceCleanup,skippedActive:r.skippedActive,stoppedActive:r.stoppedActive}}export async function cleanupStaleRuns(e,n={}){const s=[];for(;;){const t=await cleanupRuns(e,n);if(s.push(...t.cleaned),!t.skippedActive.some(r=>!o(r)&&r.services.length>0))return s}}export async function cleanupOwnedRunLifecycleResourcesWithinLifecycleFence(e,n,{localInfrastructure:s=!0}={}){const t=f(e,n);if(t.manifest===null)throw new Error(`Cannot clean terminal Testkit run ${n.runId} resources without its owned manifest`);if(t.manifest.services.length>0)throw new Error(`Cannot clean terminal Testkit run ${n.runId} resources while service ownership remains published`);const c=b(t.manifest);s&&await R(e,c);const r=f(e,n);if(r.manifest===null||!E(r.manifest,c))throw new Error(`Cannot remove terminal Testkit run ${n.runId} because its manifest changed during resource cleanup`);return S(e,n)}function b(e){if(e.status!=="failed"&&e.status!=="finished"&&e.status!=="interrupted")throw new Error(`Cannot clean Testkit run ${e.runId} database resources before terminal finalization`);if(typeof e.finishedAt!="string"||e.finishedAt.length===0)throw new Error(`Cannot clean terminal Testkit run ${e.runId} database resources without a completion time`);return{finishedAt:e.finishedAt,incarnationId:e.incarnationId,pid:e.pid,processIdentity:e.processIdentity,runId:e.runId,status:e.status}}function E(e,n){return e.runId===n.runId&&e.incarnationId===n.incarnationId&&e.pid===n.pid&&e.processIdentity===n.processIdentity&&e.finishedAt===n.finishedAt&&e.status===n.status&&e.services.length===0}export{listRunManifests,RunManifestInventoryError}from"../process/runs/manifest.js";export{stopRunById,stopRunManifest}from"./run-stopping.js";export{cleanupOwnedRunLifecycleWithinLifecycleFence,isRunManifestActive}from"./lifecycle-controller.js";export{isPidRunning}from"../process/runs/stop.js";export{formatRunSummary}from"../process/runs/manifest.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import l from"node:net";export const SERVICE_START_ATTEMPTS=3;const f=32,p=new Set(["EADDRNOTAVAIL","EAFNOSUPPORT","EPROTONOSUPPORT"]);export async function reservePort(){for(let e=0;e<f;e+=1){const r=await c("127.0.0.1",0),t=await i(r);if(t)return t}throw new Error("The OS assigned no TCP port that is free on both IPv4 and IPv6 loopback")}export async function reserveExactPort(e){let r;try{r=await c("127.0.0.1",e)}catch(t){if(s(t)==="EADDRINUSE"||s(t)==="EACCES")return null;throw t}return i(r)}export async function reservePorts(e){const r=new Map;try{for(const t of e)r.set(t,await reservePort())}catch(t){throw await releasePorts(r.values()),t}return r}export async function releasePorts(e){await Promise.all([...e].map(r=>r.release()))}export function portsOf(e){return new Map([...e].map(([r,t])=>[r,t.port]))}async function i(e){const r=P(e);let t=null;try{t=await c("::1",r)}catch(a){if(!p.has(s(a)??"")){if(await u(e),s(a)==="EADDRINUSE")return null;throw a}}const n=t?[e,t]:[e];let o=null;return{port:r,release(){return o??=Promise.all(n.map(u)).then(()=>{}),o}}}function c(e,r){const t=l.createServer(n=>{n.destroy()});return t.unref(),new Promise((n,o)=>{t.once("error",o),t.listen({host:e,port:r,exclusive:!0,...e==="::1"?{ipv6Only:!0}:{}},()=>{t.off("error",o),n(t)})})}function u(e){return new Promise(r=>{e.close(()=>{r()})})}function P(e){const r=e.address();if(r===null||typeof r=="string")throw new Error("The OS did not assign a TCP port");return r.port}function s(e){const r=typeof e=="object"&&e!==null?Reflect.get(e,"code"):void 0;return typeof r=="string"?r:void 0}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
export function createReadyEnvironment(e,r){return{leaseId:r,graphKey:e.graphKey,runtimeId:e.runtimeId,targetNames:[...e.targetNames],services:new Map(e.runtimeConfigs.map(a=>[a.name,{baseUrl:a.testkit.local?.baseUrl||null,database:e.databaseBindings.get(a.name)??null,config:a}]))}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{cleanupOwnedRunLifecycleResourcesWithinLifecycleFence as
|
|
1
|
+
import{cleanupOwnedRunLifecycleResourcesWithinLifecycleFence as w,cleanupRunsWithinLifecycleFence as y,listRunManifests as R,startRunLifecycle as v}from"./lifecycle.js";import{createRuntimeManager as F}from"./runtime-manager.js";import{resolveCommittedRunFinalization as I}from"../evidence/finalization.js";import{withProductLifecycleFence as q}from"../process/lifecycle-fence.js";export function createLocalRunEnvironment(s){return{async start(f){const c={localInfrastructure:f.localInfrastructure!==!1},n=await v(s,f,c),p=n.startHeartbeat(2e3,()=>({kind:"controller",status:n.isStopRequested()?"interrupting":"running"}));let a=null;const m=new Map,l=()=>{if(a===null)throw new Error("Run runtimes have not been provisioned");return a};let d=null;return{runId:n.runId,signal:n.signal,isStopRequested:()=>n.isStopRequested(),getInterruptReason:()=>n.getInterruptReason(),requestStop:e=>{n.requestStop(e)},beginFinalization:p,dispose(){p(),n.removeSignalHandlers(),n.dispose()},get committedFinalization(){return d},provision(e,t){if(a!==null)throw new Error("Run runtimes are already provisioned");a=F({productDir:s,graphs:e,lifecycle:n,runtimeOptions:t})},async acquire(e,t){const r=await l().acquire(e,t);m.set(r.leaseId,r);const{leaseId:o,runtimeId:u,graphKey:i,targetNames:h,services:g}=r;return{leaseId:o,runtimeId:u,graphKey:i,targetNames:h,services:g}},canAcquire:e=>l().canAcquire(e),async release(e,t){const r=m.get(e);r!==void 0&&(await l().release(r,t),m.delete(e))},async cleanupAll(){await a?.cleanupAll()},getStats:()=>a?.getStats()??[],getGraph(e){const t=a?.getGraph(e);return t?{key:t.key,targetNames:[...t.targetNames]}:null},getGraphFailure:e=>a?.getGraphFailure(e)??null,markGraphFailed:(e,t)=>{l().markGraphFailed(e,t)},async finish(e,t,r){return p(),q(s,async o=>{const u=R(s).find(i=>i.runId===n.runId);if(u!==void 0&&u.services.length>0)throw new Error(r==="normal"?"Cannot commit a run while application service ownership remains published":"Cannot publish terminal failure while application service ownership remains published");d??=I(e,n.commitFinalization(e==="failed"?"failed":"finished"));try{await y(o,{...c,protectedLiveRunIds:new Set([n.runId])}),await w(o,n,c)}catch(i){if(r==="normal")throw i}return t(d)})}}}}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{waitForPreparedRunStop as g,drainRunServices as M,requestProcessStop as _,runManifestServiceKey as F,sameRunManifestIncarnation as P}from"../process/runs/stop.js";import{observeProcessCreationIdentity as h,captureProcessCreationIdentity as N}from"../process/index.js";import{normalizeOperationReason as S}from"../domain/operation-reason.js";import{RUN_MAINTENANCE_STOP_REQUEST_SCHEMA_VERSION as L}from"../process/runs/schema.js";import{finalizeLiveRunArtifact as v}from"../evidence/index.js";import{requireProductLifecycleFenceProductDir as q,withProductLifecycleFence as m}from"../process/lifecycle-fence.js";import{listRunManifests as E,readRunMaintenanceStopRequest as T,removeRunMaintenanceStopRequest as y,removeRunManifestFile as O,requireSafeRunId as k,writeRunMaintenanceStopRequest as $,prepareRunShutdownDeadlines as D,persistRunShutdownDeadlines as z}from"../process/runs/manifest.js";export async function stopRunById(
|
|
1
|
+
import{waitForPreparedRunStop as g,drainRunServices as M,requestProcessStop as _,runManifestServiceKey as F,sameRunManifestIncarnation as P}from"../process/runs/stop.js";import{observeProcessCreationIdentity as h,captureProcessCreationIdentity as N}from"../process/index.js";import{normalizeOperationReason as S}from"../domain/operation-reason.js";import{RUN_MAINTENANCE_STOP_REQUEST_SCHEMA_VERSION as L}from"../process/runs/schema.js";import{finalizeLiveRunArtifact as v}from"../evidence/index.js";import{requireProductLifecycleFenceProductDir as q,withProductLifecycleFence as m}from"../process/lifecycle-fence.js";import{listRunManifests as E,readRunMaintenanceStopRequest as T,removeRunMaintenanceStopRequest as y,removeRunManifestFile as O,requireSafeRunId as k,writeRunMaintenanceStopRequest as $,prepareRunShutdownDeadlines as D,persistRunShutdownDeadlines as z}from"../process/runs/manifest.js";export async function stopRunById(i,t,r={}){const n=k(t,"Testkit run id"),e=await m(i,o=>A(o,n,r));if(e===null)return!1;const s=await g(e);return await C(i,e,s),!0}export async function stopRunManifest(i,t,r={}){const n=k(t.runId,"Testkit run manifest runId"),e=await m(i,o=>A(o,n,r,t));if(e===null)return{runId:n,pid:t.pid,reason:S(r.reason,"stopped"),stopped:!0};const s=await g(e);return C(i,e,s)}function A(i,t,r={},n=null){const e=q(i);let s=S(r.reason,"stopped");const o=E(e).find(a=>a.runId===t);if(o===void 0){if(n!==null&&n.pid>0&&n.processIdentity===null&&h(n.pid,n.processIdentity)==="unknown")throw new Error(`Cannot establish the creation identity of Testkit run process ${n.pid.toString()}; refusing unsafe stop`);return n!==null&&n.pid===0&&(v(e,{runId:t,reason:s,status:"interrupted"}),y(e,t)),null}if(n!==null&&!P(o,n))throw new Error(`Testkit run ${t} ownership changed before the stop request could be published`);const u=o.pid,f=u>0?h(u,o.processIdentity):"different";if(u===process.pid&&f==="matches")throw new Error(`Cannot stop active Testkit run ${t} from inside its own controller process`);if(f==="unknown")throw new Error(`Cannot establish the creation identity of Testkit run process ${u.toString()}; refusing unsafe stop`);let l=null,p=new Date().toISOString(),d=null;const I=T(e,t),c=I!==null&&I.targetIncarnationId===o.incarnationId&&I.targetPid===u&&I.targetProcessIdentity===o.processIdentity?I:null;c!==null&&(s=c.reason,p=c.requestedAt);let w=null;const R=()=>{if(w!==null)return w;const a=D(o,p);return f==="different"&&z(e,a),w=a,a};if(f==="matches"){if(d=o.processIdentity,d===null)throw new Error(`Testkit run process ${u.toString()} has no creation identity; refusing unsafe stop`);if(c!==null&&h(c.coordinatorPid,c.coordinatorProcessIdentity)!=="different")return l=c.coordinatorProcessIdentity,{controllerActive:!0,coordinatorProcessIdentity:l,graceMs:r.graceMs||2e3,manifest:R(),requestedAt:p,pid:u,productDir:e,reason:s,runId:t,targetProcessIdentity:d};if(l=N(process.pid),l===null)throw new Error("Could not capture the maintenance coordinator process identity");$(e,{coordinatorPid:process.pid,coordinatorProcessIdentity:l,reason:s,requestedAt:p,runId:t,schemaVersion:L,targetIncarnationId:o.incarnationId,targetPid:u,targetProcessIdentity:d}),R();try{process.platform!=="win32"&&_(u,d,"SIGINT")}catch(a){throw y(e,t),a}}return{controllerActive:f==="matches",coordinatorProcessIdentity:l,graceMs:r.graceMs||2e3,manifest:R(),requestedAt:p,pid:u,productDir:e,reason:s,runId:t,targetProcessIdentity:d}}async function C(i,t,r){for(;;){const n=await m(i,e=>U(e,t,r));if(n.result!==null)return n.result;await M(n.services,r)}}function U(i,t,r){const n=q(i),e=E(n).find(o=>o.runId===t.runId);if(e===void 0||!P(e,t.manifest))return V(n,t),{result:b(t),services:null};const s=e.services.filter(o=>!r.has(F(o)));return s.length>0?{result:null,services:s}:(v(n,{runId:t.runId,reason:t.reason,status:"interrupted"}),O(n,t.runId),{result:b(t),services:null})}function b(i){return{runId:i.runId,pid:i.pid,stopped:!0,reason:i.reason}}function V(i,t){const r=T(i,t.runId);r===null||r.coordinatorPid!==process.pid||r.coordinatorProcessIdentity!==t.coordinatorProcessIdentity||r.targetIncarnationId!==t.manifest.incarnationId||r.targetPid!==t.pid||r.targetProcessIdentity!==t.targetProcessIdentity||y(i,t.runId)}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import
|
|
1
|
+
import P from"fs";import p from"path";import{bindDatabaseUrl as S,lendDatabases as m}from"../database/bindings.js";import{prepareRuntimeServices as l}from"./runtime-preparation.js";import{writeGraphMetadata as D}from"./state.js";import{startLocalServices as C,stopLocalServices as T}from"./services.js";import{resolveRuntimeInstanceConfigs as k}from"./template.js";import{withEnvFileValues as E}from"../config/loader/env.js";import{portsOf as M,releasePorts as u,reserveExactPort as U,reservePort as I,reservePorts as j}from"./ports.js";import{buildExecutionEnv as B,buildTemplateContext as K,buildTemplateExecutionEnv as c,finalizeString as O,withDatabaseBindings as A}from"../steps/index.js";import{sourceSchemaCredentialEnvNames as N}from"../database/source-schema-env.js";import{envRedactionTargets as $,jsonRedactionTargets as F,sensitiveKeyMatcher as g,urlRedactionTargets as L}from"../kernel/redaction-targets.js";const v=/\{[a-zA-Z]+(?::[^}]+)?\}/u;export function createRuntimeInstanceContext(r,e,t){const a=p.join(t,".testkit","_graphs",e.dirName),s=p.join(a,"runtimes",r);return P.mkdirSync(s,{recursive:!0}),D(a,e),{databaseBindings:new Map,graphKey:e.key,targetNames:[...e.targetNames],graphDir:a,graphDirName:e.dirName,runtimeDir:s,runtimeId:r,sourceConfigs:e.runtimeConfigs.map(E),ports:null,portReservations:new Map,triedPortReservations:[],triedPorts:new Map,runtimeConfigs:[],ready:!1,readyPromise:null,startedServices:[]}}export async function ensureRuntimeInstanceReady(r,e,t={}){return r.ready||(r.readyPromise??=V(r,e,t).finally(()=>{r.readyPromise=null}),await r.readyPromise),r}async function V(r,e,t){const a={...t,signal:e.signal},s=await _(r);z(r,t.environmentRecord),r.databaseBindings=await prepareDatabases(r.runtimeConfigs,a),f(r,s),y(r,t.environmentRecord),await l(r.runtimeConfigs,a),r.startedServices=await C(G(r,a),e,t),r.ready=!0}function z(r,e){if(!e)return;const t=g(e.redactKeys);for(const a of r.runtimeConfigs){const s=c(a,{},null);for(const i of[...w(a,s,null,t),...R(a,t)])v.test(i)||e.addRedactionTarget(i)}}function y(r,e){if(!e)return;const t=g(e.redactKeys);for(const a of r.runtimeConfigs){const s=B(a,{},null),i=r.databaseBindings.get(a.name)?.url??null;for(const n of w(a,s,i,t))e.addRedactionTarget(n);for(const n of R(a,t))v.test(n)||e.addRedactionTarget(n)}}function R(r,e){return F("ui",d(r.testkit.ui??{},K(r,null)),e)}function d(r,e){if(typeof r=="string")try{return O(r,e)}catch{return r}return Array.isArray(r)?r.map(t=>d(t,e)):r!==null&&typeof r=="object"?Object.fromEntries(Object.entries(r).map(([t,a])=>[t,d(a,e)])):r}function w(r,e,t,a){const s=r.testkit.local,i=[s?.baseUrl,typeof s?.readyUrl=="string"?s.readyUrl:null,t,...N(r).map(n=>e[n]??process.env[n])];return[...$(e,a),...i.flatMap(n=>n?L(n):[])]}async function _(r){if(r.ports)return r.ports;const e=r.sourceConfigs.filter(s=>s.testkit.local).map(s=>s.name),t=await j(e),a=M(t);try{f(r,a)}catch(s){throw await u(t.values()),s}return r.portReservations=t,a}function f(r,e){r.runtimeConfigs=k(r.sourceConfigs,r.runtimeId,r.runtimeDir,{databaseBindings:r.databaseBindings,graphDirName:r.graphDirName,ports:e}),r.ports=e}function G(r,e){return{get configs(){return r.runtimeConfigs},async releasePort(t){const a=r.portReservations.get(t);r.portReservations.delete(t),await a?.release()},async reassignPort(t,a){const s=r.triedPorts.get(t)??new Set,i=r.ports?.get(t);if(i!==void 0){s.add(i);const o=await U(i);o&&r.triedPortReservations.push(o)}r.triedPorts.set(t,s),await r.portReservations.get(t)?.release();const n=await J(s);r.portReservations.set(t,n);const h=new Map(r.runtimeConfigs.map(o=>[o.name,b(o)]));return f(r,new Map([...r.ports??[],[t,n.port]])),y(r,e.environmentRecord),r.runtimeConfigs.filter(o=>a.has(o.name)&&b(o)!==h.get(o.name)).map(o=>o.name)},async prepare(t){await l(r.runtimeConfigs.filter(a=>t.has(a.name)),e)}}}async function J(r){const e=[];try{for(;;){const t=await I();if(!r.has(t.port))return t;e.push(t)}}finally{await u(e)}}function b(r){return JSON.stringify({env:c(r,{},{},{includeTestkitControls:!1}),prepare:r.testkit.runtime.prepare,readyUrl:r.testkit.local?.readyUrl??null,start:r.testkit.local?.start??null})}async function Z(r,e){r?.ready&&(await T(r.startedServices,e),r.ready=!1,r.startedServices=[])}export async function cleanupRuntimeInstanceContext(r,e){if(!r)return;await Z(r,e),await u([...r.portReservations.values(),...r.triedPortReservations]),r.portReservations.clear(),r.triedPortReservations=[];const t=r.runtimeConfigs.filter(s=>s.testkit.database);if(t.length===0)return;const{dropRecordedTaskDatabases:a}=await import("../database/index.js");for(const s of t)await a({productDir:s.productDir,stateDir:s.stateDir})}export async function prepareDatabases(r,e={}){const t=new Map;if(r.some(a=>a.testkit.database)){const{provisionDatabase:a}=await import("../database/index.js");for(const s of r){const i=await a(A(s,m(r,t)),{progress:{reporter:e.reporter,setupRegistry:e.setupRegistry},provisionedSharedDatabases:e.provisionedSharedDatabases,signal:e.signal,skipSchemaSourceVerify:e.skipSchemaSourceVerify});i&&t.set(s.name,S(i.url))}}return q(r,t)}function q(r,e){const t=m(r,e);for(const a of r){const s=a.testkit.databaseFrom;if(s&&!t.has(a.name))throw H(a.name,s,r)}return t}function H(r,e,t){const a=t.some(s=>s.name===e)?`"${e}" declares no database`:`"${e}" is not in this runtime; add it to dependsOn`;return new Error(`Service "${r}" databaseFrom "${e}" has no database to use: ${a}`)}
|