Skip to content

Commit 66ae688

Browse files
committed
Support TeamCity PHPUnit runtime contracts
1 parent ddae9e8 commit 66ae688

5 files changed

Lines changed: 16 additions & 4 deletions

File tree

packages/cli/src/commands/recipe-build.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { readFile, writeFile } from "node:fs/promises"
2-
import { buildGenericAbilityRuntimeRunRecipe, buildRuntimePackageRunRecipe, buildWordPressBenchRecipe, buildWordPressPhpunitRecipe, compileRecipeTemplate, type GenericAbilityRuntimeRunOptions, type RecipeTemplateInput, type RuntimePackageRunRecipeOptions, type RuntimeWordPressInstallMode, type WorkspaceRecipe, type WorkspaceRecipeExtraPlugin, type WorkspaceRecipeMount, type WorkspaceRecipePHPWasmExtensionManifest, type WorkspaceRecipeRuntimeBackendPackage, type WorkspaceRecipeRuntimeService, type WorkspaceRecipeStep } from "@automattic/wp-codebox-core"
2+
import { buildGenericAbilityRuntimeRunRecipe, buildRuntimePackageRunRecipe, buildWordPressBenchRecipe, buildWordPressPhpunitRecipe, compileRecipeTemplate, type GenericAbilityRuntimeRunOptions, type RecipeTemplateInput, type RuntimePackageRunRecipeOptions, type RuntimeWordPressInstallMode, type WorkspaceRecipe, type WorkspaceRecipeExtraPlugin, type WorkspaceRecipeMount, type WorkspaceRecipePHPWasmExtensionManifest, type WorkspaceRecipePluginRuntime, type WorkspaceRecipeRuntimeBackendPackage, type WorkspaceRecipeRuntimeService, type WorkspaceRecipeStep } from "@automattic/wp-codebox-core"
33

44
interface RecipeBuildOptions {
55
recipeType: "phpunit" | "bench" | "template" | "generic-ability-runtime-run" | "runtime-package-run"
@@ -16,6 +16,7 @@ interface WordPressPhpunitBuilderOptions {
1616
backendPackage?: WorkspaceRecipeRuntimeBackendPackage
1717
mounts?: WorkspaceRecipeMount[]
1818
services?: WorkspaceRecipeRuntimeService[]
19+
pluginRuntime?: WorkspaceRecipePluginRuntime
1920
extra_plugins?: WorkspaceRecipeExtraPlugin[]
2021
pluginSource?: string
2122
pluginSlug: string
@@ -86,6 +87,7 @@ function buildRecipe(recipeType: RecipeBuildOptions["recipeType"], options: Word
8687
backendPackage: phpunitOptions.backendPackage,
8788
mounts: Array.isArray(phpunitOptions.mounts) ? phpunitOptions.mounts : [],
8889
services: Array.isArray(phpunitOptions.services) ? phpunitOptions.services : [],
90+
pluginRuntime: phpunitOptions.pluginRuntime ? plainObject(phpunitOptions.pluginRuntime) as WorkspaceRecipePluginRuntime : undefined,
8991
extra_plugins: Array.isArray(phpunitOptions.extra_plugins) ? phpunitOptions.extra_plugins : [],
9092
pluginSource: stringOrUndefined(phpunitOptions.pluginSource),
9193
pluginSlug: requiredString(phpunitOptions.pluginSlug, "pluginSlug"),

packages/runtime-core/src/recipe-builders.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { RuntimePreviewSpec, RuntimeWordPressInstallMode, WorkspaceRecipe, WorkspaceRecipeExtraPlugin, WorkspaceRecipeMount, WorkspaceRecipePHPWasmExtensionManifest, WorkspaceRecipeRuntimeBackendPackage, WorkspaceRecipeRuntimeService, WorkspaceRecipeStep } from "./runtime-contracts.js"
1+
import type { RuntimePreviewSpec, RuntimeWordPressInstallMode, WorkspaceRecipe, WorkspaceRecipeExtraPlugin, WorkspaceRecipeMount, WorkspaceRecipePHPWasmExtensionManifest, WorkspaceRecipePluginRuntime, WorkspaceRecipeRuntimeBackendPackage, WorkspaceRecipeRuntimeService, WorkspaceRecipeStep } from "./runtime-contracts.js"
22
import { commandArg, commandJsonArg, commandStringListArg } from "./command-codecs.js"
33
export { buildRuntimePackageRunRecipe, CODEBOX_RUN_RUNTIME_PACKAGE_ABILITY, RUNTIME_PACKAGE_ARTIFACT_DECLARATION_SCHEMA, RUNTIME_PACKAGE_EXECUTION_INPUT_SCHEMA, RUNTIME_PACKAGE_EXECUTION_RESULT_SCHEMA, RUNTIME_PACKAGE_OUTPUT_PROJECTION_SCHEMA, runtimePackageExecutionInput, type RuntimePackageArtifactDeclaration, type RuntimePackageExecutionInput, type RuntimePackageOutputProjection, type RuntimePackageRunRecipeOptions } from "./runtime-package-execution.js"
44
export { RUNTIME_PACKAGE_DIAGNOSTIC_SCHEMA, RUNTIME_PACKAGE_RESULT_SCHEMA, RUNTIME_PACKAGE_TASK_SCHEMA, normalizeRuntimePackageResult, normalizeRuntimePackageTask, validateRuntimePackageTask, type RuntimePackageDiagnostic, type RuntimePackageResult, type RuntimePackageTask } from "./runtime-package-contracts.js"
@@ -21,6 +21,7 @@ export interface WordPressPhpunitRecipeOptions {
2121
preview?: RuntimePreviewSpec
2222
mounts?: WorkspaceRecipeMount[]
2323
services?: WorkspaceRecipeRuntimeService[]
24+
pluginRuntime?: WorkspaceRecipePluginRuntime
2425
extra_plugins?: WorkspaceRecipeExtraPlugin[]
2526
pluginSource?: string
2627
pluginSlug: string
@@ -88,6 +89,7 @@ export function buildWordPressPhpunitRecipe(options: WordPressPhpunitRecipeOptio
8889
inputs: {
8990
extra_plugins: normalizeExtraPlugins(options.extra_plugins),
9091
...(options.services && options.services.length > 0 ? { services: options.services } : {}),
92+
...(options.pluginRuntime ? { pluginRuntime: options.pluginRuntime } : {}),
9193
mounts: normalizeRecipeMounts([
9294
...(options.pluginSource ? [{ source: options.pluginSource, target: pluginTarget } satisfies WorkspaceRecipeMount] : []),
9395
...(options.mounts ?? []),

packages/runtime-playground/src/wordpress-command-runners.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -970,14 +970,18 @@ export async function runPhpunitCommand({
970970
if (structured) {
971971
throw attachPlaygroundDiagnostics(new Error("wordpress.phpunit terminated before completing bootstrap"), "wordpress.phpunit structured diagnostics", structured)
972972
}
973-
if (!phpunitArgs.includes("--list-tests") && !/\bOK(?:, but there were issues!)? \([1-9]\d* tests?,/m.test(response.text)) {
973+
if (!phpunitArgs.includes("--list-tests") && !hasSuccessfulPhpunitSummary(response.text)) {
974974
const diagnostics = successfulPhpunitResponseDiagnostics(response)
975975
throw attachPlaygroundDiagnostics(new Error("wordpress.phpunit exited successfully without a non-zero PHPUnit test summary"), "wordpress.phpunit successful response diagnostics", diagnostics)
976976
}
977977

978978
return response.text
979979
}
980980

981+
export function hasSuccessfulPhpunitSummary(output: string): boolean {
982+
return /\bOK(?:, but (?:there were issues!|incomplete, skipped, or risky tests!))?(?: \([1-9]\d* tests?,|\s+Tests:\s*[1-9]\d*,\s*Assertions:)/m.test(output)
983+
}
984+
981985
function successfulPhpunitResponseDiagnostics(response: PlaygroundRunResponse): string {
982986
const boundedStream = (value: string): string => value.length > 9_000 ? `${value.slice(0, 9_000)}\n[stream truncated]` : value
983987
return [

tests/phpunit-runtime-failure-diagnostics.test.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { mkdtemp, readFile } from "node:fs/promises"
33
import { tmpdir } from "node:os"
44
import { join } from "node:path"
55
import { PLUGIN_PHPUNIT_RESULT_FILE } from "../packages/runtime-playground/src/phpunit-command-handlers.js"
6-
import { runPhpunitCommand } from "../packages/runtime-playground/src/wordpress-command-runners.js"
6+
import { hasSuccessfulPhpunitSummary, runPhpunitCommand } from "../packages/runtime-playground/src/wordpress-command-runners.js"
77

88
const artifactRoot = await mkdtemp(join(tmpdir(), "wp-codebox-phpunit-runtime-diagnostics-"))
99
const secret = "sk-abcdefghijklmnopqrstuvwxyz"
@@ -51,6 +51,9 @@ assert.ok(preBootstrapRecorder >= 0 && preBootstrapRecorder < wordpressBootstrap
5151

5252
const emptySuccessArtifactRoot = await mkdtemp(join(tmpdir(), "wp-codebox-phpunit-empty-success-"))
5353
const successfulResponseSecret = "ghp_abcdefghijklmnopqrstuvwxyz1234567890"
54+
assert.equal(hasSuccessfulPhpunitSummary("OK (1 test, 1 assertion)"), true)
55+
assert.equal(hasSuccessfulPhpunitSummary("OK, but incomplete, skipped, or risky tests!\nTests: 21, Assertions: 27398, Skipped: 1."), true)
56+
assert.equal(hasSuccessfulPhpunitSummary("Tests: 21, Assertions: 27398, Failures: 1."), false)
5457
await assert.rejects(
5558
() => runPhpunitCommand({
5659
artifactRoot: emptySuccessArtifactRoot,

tests/runtime-services.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ assert.equal(runtimeServicePlan([mariaDbService])[0]?.version, "mariadb:11.4")
3333
assert.equal(validateWorkspaceRecipeJsonSchema({ schema: "wp-codebox/workspace-recipe/v1", inputs: { services: [{ ...service, configuration: { foreignKeyTargetPolicy: "anything" } }] }, workflow: { steps: [{ command: "wordpress.run-php" }] } }).valid, false)
3434
assert.deepEqual(buildWordPressPhpunitRecipe({ pluginSlug: "example", services: [emptyRootService] }).inputs?.services, [emptyRootService])
3535
assert.equal(buildWordPressPhpunitRecipe({ pluginSlug: "example", wordpressInstallMode: "do-not-attempt-installing" }).runtime?.wordpressInstallMode, "do-not-attempt-installing")
36+
assert.deepEqual(buildWordPressPhpunitRecipe({ pluginSlug: "example", pluginRuntime: { php: { memoryLimit: "2G" } } }).inputs?.pluginRuntime, { php: { memoryLimit: "2G" } })
3637
const builderDirectory = await mkdtemp(join(tmpdir(), "wp-codebox-phpunit-builder-"))
3738
try {
3839
const optionsPath = join(builderDirectory, "options.json")

0 commit comments

Comments
 (0)