aip_sdk.publish_test_plan_version
aip_sdk.publish_test_plan_version(plan: TestPlan, *, ref: str | None = None, base_version: int | None = None, workspace_id: str | None = None, client: APIClient | None = None) -> TestPlanRecord
Publish the next version of a test plan that already exists.
An edit is a new version, never a change to a published one: the version you edited stays
readable exactly as it was, and this call returns the new version stored alongside it. Every
reference is re-resolved against the workspace's current catalogue first, exactly as
publish_test_plan does, so an edit cannot introduce a reference that no longer resolves.
The plan being edited is named by ref, not by plan.name — a plan you fetched or
published can be edited by passing its id, which nobody has to type and so nobody can
typo. plan.name must still match the plan being edited: renaming means publishing a new
plan with publish_test_plan.
Pass base_version whenever you know which version you changed. The publish is then
refused if someone else has published since — without it, two people editing version 3
produce versions 4 and 5, and whatever the first one changed is silently absent from the
second.
Parameters
planTestPlan: The edited methodology. Itsnamemust match the plan being edited.refstr | None: The plan to edit — its name, or theidof any of its versions. Defaults toplan.name. Surrounding whitespace is trimmed; a literal/is refused, since a plan name can never contain one and a version id never does either.base_versionint | None: The version this edit was made from. Refuses the publish if the plan has moved on. Omit to publish on top of whatever is latest.workspace_idstr | None: Target workspace. Falls back to the client's configured workspace.clientAPIClient | None: Explicit API client. Uses the default client when omitted.
Returns
TestPlanRecord: The publishedTestPlanRecord, carrying the newly assigned version.
Examples
import aip_sdk as aip
published = aip.publish_test_plan(plan, workspace_id="ws_001")
published.plan.metrics["llm.toxicity"].threshold = 0.9
try:
edited = aip.publish_test_plan_version(published.plan, ref=published.id, base_version=published.version)
except aip.StaleTestPlanBaseVersionError:
print("Someone else published first — re-read the plan and re-apply the change.")
raise
print(edited.version)
Raises
NoWorkspaceSelectedError: No workspace was given and the client has none configured.InvalidArgumentError:refis empty or contains/, or a metricconfigvalue is not JSON-serializable.NotFoundError: The workspace does not exist, or it holds no plan matchingref.StaleTestPlanBaseVersionError:base_versionis no longer the plan's latest. Re-read the plan, re-apply the change, and publish again.UnprocessableEntityError: The plan was rejected for a reason other than an unresolved reference — including aplan.namethat does not match the plan being edited.TestPlanReferenceError: The plan names something that could not be resolved. Readfailuresfor every unresolved reference.DuplicateTestPlanVersionError: Another edit took the version this one derived. Re-read the plan, re-apply the change, and publish again — a bare retry would fail as stale once it re-checksbase_version, and skipping that check would silently publish over whatever the concurrent edit changed.IdempotencyKeyConflictError: Not reachable through this function in practice — every call generates its own key, so no two calls collide except this SDK's own retry of itself, which is always safe.PayloadTooLargeError: The serialized plan exceeds the platform's size limit.AuthError: Credentials are missing, invalid, or expired.ForbiddenError: The caller is not an editor or admin of the workspace.ResponseParseError: A platform response did not match the shape this SDK version expects. Usually means the platform is running a newer release; upgrading resolves it.APIError: Any other error from the platform.