Turn on a development environment and promote

Prompt:

Add a development environment, so I can test before production.

Also works:

  • "Let me try each version somewhere before my users see it."
  • "The new version works. Put it live."

What your tool does

  • Calls create_environment with the application identifier and environment: "development" when you ask for a development environment. It finishes before the call returns.
  • Deploys each new version to development as Deploy an application describes. Before asking you to promote, it requests each route the change touched on the development hostname and checks read_logs for errors.
  • Asks you whether to promote once the development deploy is deployed. On your yes, it calls promote with the application identifier and wait_seconds, and follows the response's next call where it returns 202.
  • Checks production as Check the release describes.
  • Asks for no browser approval: create_environment and promote run without one.

What you need

Before your AI starts

This section is for your AI tool: what it checks and gathers before it begins. You don't need to do these steps yourself.

  • Your tool connected and signed in (Connect your tool).
  • The application identifier, which list_applications returns.

Steps

Turning development on is done once. After that, each version is deployed to development and promoted to production.

Turn the development environment on

A new application has one environment, production. Its deploys go straight to production, and roll_back puts an earlier version back. A second environment, development, gives you a hosted copy where you test a version before your users see it.

create_environment turns development on at any time. It takes the application identifier and environment: "development", and finishes before the call returns, with no browser approval. A call that names production is refused 400 invalid_request, because production always exists.

You can call it before or after submit_manifest: either order ends in the same state. submit_manifest creates development's credentials on every application, and its database where the manifest declares one, whichever call comes first. create_environment adds the hosted development copy and creates no database.

From then on:

  • a deploy goes to development, at <label>-dev.ai.host, and promote moves a version to production;
  • where the manifest declares the accounts service, development has its own realm and its own list of end users, and local runs sign testers in there;
  • the manifest's realm member and push providers apply to development as well as production;
  • development's schedules run from its first deploy.

Local data that names production's users matches no one on the development realm, because that realm has its own users.

The call returns created: true and the development hostname. Where the application already has development, it returns created: false and changes nothing, except to finish a step an earlier call left undone. It creates nothing hosted: development's compute starts at its first deploy. The response's page is this page's address.

Deploy to development

With development on, a deploy goes to development. Your tool builds, uploads, and deploys as steps 3 to 5 of Deploy an application describe, and production keeps serving its version meanwhile.

Promote to production

On one environment, promote is refused 409 environment_not_created, since the deploy already reaches production.

On two environments, promote requires the application identifier and takes two optional members:

  • version, the number of a deployed history row of the application. Where it is absent, the development environment's serving version is promoted. Where the development environment runs no version, the call is refused 409 nothing_to_promote.
  • rotate_database_credential, described below.

A named version is refused in two cases:

  • It is not the number of a deployed row, or its row was retired when its environment was deleted: 404 no_such_version. list_versions returns the rows a promote can name.
  • The platform has deleted its image: 409 version_image_pruned. list_versions shows promotable and harness_current on each row.

The platform keeps the images of each environment's twenty most recent deployed versions, its serving version among them, and deletes the rest once a day. To promote an older version, deploy its artifact again.

A promote is also refused while production is halted (409 target_environment_halted) and while a deploy, promote, or redeploy of production is in flight (409 deploy_in_flight). It is refused while a deletion of the application or of either environment runs (409 deletion_in_progress).

The promote takes the same wait_seconds as a deploy and responds the same way. Without it, the promote returns at once with status 202 and state: "deploying". With it, the response waits for the promote to end, within the wait. Its environment is always production. Where something other than the platform responds, call read_status first, and promote again only where it shows no promote started after your call.

The promote builds nothing: it reuses the image built at the deploy, so the code reaching production is the code the development environment ran. The image also contains the runtime harness from the deploy, so a promote keeps that harness, and only a new deploy takes the current one. Where the manifest declares the database kind and no production database exists yet, the first promote provisions it on a production server.

The promote then works in this order:

  1. It mints a new production platform credential and gives it to the new container. The current value keeps working until the switch.
  2. With rotate_database_credential: true, it sets a new password on the production database role before the new container starts.
  3. It starts the new version's production container beside the serving one, with production's settings and credentials. They include TURNZERO_CLOUD_REALM_KEYS where production has a realm.
  4. It polls the health path on the new container alone. On a 200 it switches the production hostname to the new container. A first promote records deployed at once. Where production already serves a version, the switch waits until the promote is 30 seconds old, and deployed comes 3 seconds after it, once every router has the switch.
  5. It removes the previous container about a minute after the switch: the router's resolve interval, 30 seconds by default, plus a 30-second grace.

The switch to the new platform credential happens only when the health check passes, so a failed promote leaves the current credential in place. The previously serving container keeps its platform credential until the platform removes that container. So the platform's services do not refuse a request that still reaches it.

A database rotation is the exception. From the rotation until the switch, a new database connection from the previous container fails, while its open connections continue. So the rotation runs on request, not at every promote.

From the switch, production's schedules restart from the promote. A scheduled run still in flight on the previous container can fail, and its next due time runs again. With wait_seconds, the promote's response includes the outcome where the promote ends within the wait. Otherwise make the next call it gives, read_status with wait_seconds, or check the row in list_versions.

A failed promote ends failed with the outcome named. Its new container is removed, and the serving one is untouched. A promote interrupted by a platform restart before its switch ends failed with the outcome interrupted within about fifteen minutes. One interrupted after its switch ends deployed, because the new version is already running.

A promote of the version production already runs is accepted. It mints a new production platform credential, and a new database password with rotate_database_credential: true, and applies the settings again.

Expected result

With development turned on, the deploy reaches <label>-dev.ai.host, and the promote adds a production promote row.

  • After create_environment, read_status lists development beside production, development as never_deployed until its first deploy.

Refusals

A promote meets the refusals it shares with a deploy, such as deploy_in_flight and setting_secret_missing, which the Refusals of Deploy an application lists.

After development is turned on, create_environment can also be refused name_bound_to_setting, custody_entry_missing, custody_entry_unmovable, or realm_not_declared while it records the manifest's sign-in or push settings there. Development stays on, and the detail says what became of the setting and whether to call it again or submit the manifest. Author the manifest explains each.

Refusal Status Cause Remedy
nothing_to_promote 409 promote named no version, and the development environment runs none. Deploy to development first, or name a deployed version.
no_such_version 404 promote: the version is not a deployed row of the application, or its environment was deleted. Name a row list_versions returns with state: "deployed".
version_image_pruned 409 promote: the platform has deleted the named version's image. Deploy that version's artifact again as a new version, then promote it.