Skip to main content

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

  • plan TestPlan: The edited methodology. Its name must match the plan being edited.
  • ref str | None: The plan to edit — its name, or the id of any of its versions. Defaults to plan.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_version int | 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_id str | None: Target workspace. Falls back to the client's configured workspace.
  • client APIClient | None: Explicit API client. Uses the default client when omitted.

Returns

  • TestPlanRecord: The published TestPlanRecord, 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: ref is empty or contains /, or a metric config value is not JSON-serializable.
  • NotFoundError: The workspace does not exist, or it holds no plan matching ref.
  • StaleTestPlanBaseVersionError: base_version is 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 a plan.name that does not match the plan being edited.
  • TestPlanReferenceError: The plan names something that could not be resolved. Read failures for 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-checks base_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.