feat: support primitive response arrays and shared catalog tooling
This commit is contained in:
@@ -18,6 +18,55 @@ ROOT = Path(__file__).resolve().parents[1]
|
||||
MODULE = "git.yuntuo.hk/k2safe/go-omni"
|
||||
|
||||
|
||||
def verify_shared_catalog(cli, temp, env, version):
|
||||
workspace = temp / "workspace"
|
||||
(workspace / "internal/apierrors").mkdir(parents=True)
|
||||
(workspace / "contracts").mkdir()
|
||||
(workspace / "go.mod").write_text(f"module example.com/releaseWorkspace\n\ngo 1.24.0\nrequire {MODULE} {version}\n")
|
||||
provider = workspace / "internal/apierrors/catalog.go"
|
||||
provider.write_text('package apierrors\nimport errors "' + MODULE + '/errors"\n'
|
||||
'func Catalog() errors.Catalog {return errors.Catalog{DefaultStatus:400,Definitions:map[string]errors.Definition{'
|
||||
'"INVALID":{Code:"INVALID",Message:"invalid"},"MISSING":{Status:404,Code:"MISSING",Message:"missing"}}}}\n')
|
||||
run(["go", "mod", "tidy"], workspace, env)
|
||||
for name in ("api", "id"):
|
||||
service = workspace / "services" / name
|
||||
run([cli, "new", "--module", "example.com/" + name, service], workspace, env)
|
||||
(service / "api/omni.imports.json").write_text(json.dumps({
|
||||
"roots": {"common": {"path": "../../../contracts"}},
|
||||
"errors": {"source": "@common/errors.json", "include": ["INVALID"],
|
||||
"routes": {"GET /api/greet/:name": ["MISSING"]}}}))
|
||||
manifest = workspace / "omni.workspace.json"
|
||||
manifest.write_text(json.dumps({"errorCatalogs": [{"dir": ".", "package": "example.com/releaseWorkspace/internal/apierrors",
|
||||
"function": "Catalog", "output": "contracts/errors.json"}],
|
||||
"services": [{"dir": "services/api"}, {"dir": "services/id"}]}))
|
||||
for command in ("generate", "format", "generate", "check"):
|
||||
run([cli, "workspace", command, "--file", manifest], workspace, env)
|
||||
for name in ("api", "id"):
|
||||
service = workspace / "services" / name
|
||||
assert not (service / "api/omni.errors.json").exists()
|
||||
assert not (service / "internal/apierrors/errorsGen.go").exists()
|
||||
doc = json.loads((service / "docs/openapi.json").read_text())
|
||||
responses = doc["paths"]["/api/greet/{name}"]["get"]["responses"]
|
||||
assert "404" in responses
|
||||
run(["go", "test", "-mod=mod", "./..."], service, env)
|
||||
snapshot = lambda: {str(p.relative_to(workspace)): hashlib.sha256(p.read_bytes()).hexdigest()
|
||||
for p in workspace.rglob("*") if p.is_file()}
|
||||
before = snapshot()
|
||||
run([cli, "workspace", "check", "--file", manifest], workspace, env)
|
||||
assert before == snapshot(), "workspace check changed project files"
|
||||
provider.write_text(provider.read_text().replace('Message:"invalid"', 'Message:"new message"'))
|
||||
before = snapshot()
|
||||
try:
|
||||
run([cli, "workspace", "check", "--file", manifest], workspace, env)
|
||||
except RuntimeError as err:
|
||||
assert "catalog drift" in str(err)
|
||||
else:
|
||||
raise AssertionError("stale catalog accepted")
|
||||
assert before == snapshot(), "drift check changed project files"
|
||||
run([cli, "workspace", "generate", "--file", manifest], workspace, env)
|
||||
run([cli, "workspace", "check", "--file", manifest], workspace, env)
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument("--version", required=True)
|
||||
@@ -71,8 +120,11 @@ def main():
|
||||
serve([str(temp / "managedServer")], managed, env, transport, signal.SIGTERM, True, contract=True, logs=temp)
|
||||
checks += ["default404And405", "goOwnedErrorCatalog", "unwrappedDownloads", "rawCallback", "multipart400And413", "nethttpAndNativeTransfers"]
|
||||
|
||||
verify_shared_catalog(cli, temp, env, args.version)
|
||||
checks += ["sharedGoCatalogExport", "documentOnlyErrorSelection", "workspaceCheckNoWrites", "staleCatalogRejected", "twoIndependentServiceBuilds"]
|
||||
|
||||
env.update(GO_OMNI_SCAFFOLD_INTEGRATION="1", GO_OMNI_RELEASE_CLI=str(cli), GO_OMNI_RELEASE_VERSION=args.version)
|
||||
tests = ["TestManagedGeneratedProject", "TestErrorInheritanceConsumer", "TestErrorParamsConsumer", "TestCompatibilityConsumer", "TestBusinessGeneratedProject"]
|
||||
tests = ["TestManagedGeneratedProject", "TestErrorInheritanceConsumer", "TestErrorParamsConsumer", "TestCompatibilityConsumer", "TestBusinessGeneratedProject", "TestPrimitiveArrayConsumer"]
|
||||
print("Running generated consumers against the remote framework, including lifecycle failure cleanup", flush=True)
|
||||
output = run(["go", "test", "-race", "-count=1", "-json", "-timeout=240s", "./cmd/go-omni/apigen", "-run", "^(" + "|".join(tests) + ")$"], ROOT, env)
|
||||
events = [json.loads(line) for line in output.splitlines() if line.startswith("{")]
|
||||
@@ -81,11 +133,13 @@ def main():
|
||||
evidence = "".join(e.get("Output", "") for e in events)
|
||||
sums = re.findall(r"checksum (h1:\S+); no local replace", evidence)
|
||||
assert len(sums) == len(tests) and all(s == dependency["Sum"] for s in sums), "remote consumer checksum mismatch"
|
||||
checks += ["initializationAndListenFailureCleanup", "drainBeforeDependencyClose", "generatedConsumerRaceTests", "errorParamsAndInheritance", "manualHooksAndScalars", "dependencyFatalShutdown", "fatalProcessExitCode", "initializationShutdownNotification", "configuredBuiltinEndpoints", "projectHealthEnvelope", "endpointConflictCleanup", "responseArrayNullableNull", "strictRequestPolicies", "declarativeMultipartBinding", "backgroundStopDrainResourceOrder", "backgroundInitAndListenFailureCleanup", "backgroundTimeoutRetainsResourcesAndExits"]
|
||||
checks += ["initializationAndListenFailureCleanup", "drainBeforeDependencyClose", "generatedConsumerRaceTests", "errorParamsAndInheritance", "manualHooksAndScalars", "dependencyFatalShutdown", "fatalProcessExitCode", "initializationShutdownNotification", "configuredBuiltinEndpoints", "projectHealthEnvelope", "endpointConflictCleanup", "responseArrayNullableNull", "primitiveAndDynamicArrays", "strictRequestPolicies", "declarativeMultipartBinding", "backgroundStopDrainResourceOrder", "backgroundInitAndListenFailureCleanup", "backgroundTimeoutRetainsResourcesAndExits"]
|
||||
|
||||
sources = ["lifecycle/runtime.go", "lifecycle/phases.go", "config/lifecycle_test.go", "task/task.go", "cmd/go-omni/scaffold/templates/api-runtime.go.tmpl", "cmd/go-omni/apigen/templates.go", "config/project.go", "contract/bind.go", "contract/policy.go", "contract/multipart.go", "contract/file.go", "cmd/go-omni/apigen/business_test.go", "cmd/go-omni/apigen/generate.go", "lifecycle/controller.go", "config/endpoints.go", "health/health.go", "httpx/response.go", "app/app.go", "app/transport.go", "scripts/verifyManagedRelease.py", "scripts/verifyManagedProject.py", "cmd/go-omni/apigen/managed_test.go"]
|
||||
sources += [str(p.relative_to(ROOT)) for p in (ROOT / "cmd/go-omni/apigen/testdata/managed").glob("*.go")]
|
||||
sources += [str(p.relative_to(ROOT)) for p in (ROOT / "cmd/go-omni/apigen/testdata/business").glob("*.go")]
|
||||
sources += ["cmd/go-omni/apigen/responseShape.go", "cmd/go-omni/apigen/documentRefs.go", "cmd/go-omni/apigen/catalogDocument.go", "cmd/go-omni/apigen/workspaceCatalog.go", "config/env.go", "cmd/go-omni/apigen/arrayResponse_test.go"]
|
||||
sources += [str(p.relative_to(ROOT)) for p in (ROOT / "cmd/go-omni/apigen/testdata/arrays").glob("*.go")]
|
||||
report = {"passed": True, "frameworkVersion": args.version, "frameworkSum": dependency["Sum"],
|
||||
"freshModuleCache": True, "noLocalReplace": True,
|
||||
"durationSeconds": round(time.monotonic() - started, 2), "checks": checks,
|
||||
|
||||
Reference in New Issue
Block a user