Skip to content
Local environment Preproduction — not production data

Workspace Versioning

While process versioning snapshots a single process or module, workspace versioning publishes a version of the whole workspace: creating the workspace version v1.0.0 publishes a v1.0.0 version on every process, module, locale and dependency manifest owned by the team. Inherited processes, modules, locales and dependencies from parent workspaces are never touched — each workspace publishes its own.

This gives you a single tag that identifies the full state of the workspace — the base for managing production deployments and rollbacks over the complete set of processes, modules, translations and installed packages.

Workspace versions live in the Versions tab of the team settings, and the version selector in the sidebar offers a shortcut to both. Publish one by clicking Create version and choosing a tag (for example v1.0.0) and an optional comment. This is the only way to publish versions from the web application: the per-entity version pages are gone, and every version you see is a workspace one.

Publishing walks the dependency manifest of every language, then every owned locale, then every owned module and process:

  • An entity that does not have the tag yet gets a new version published — created.
  • An entity that already has the exact tag keeps its existing version — skipped.
  • If publishing one entity fails, the release continues with the rest and the failure is recorded — failed.

Both languages always get a dependency version, even one your workspace declares no packages for: an empty snapshot is what stops a package added after the release from reaching an execution pinned to it.

The per-entity outcome is stored in the version’s manifest, visible from the versions list. A release is therefore safe to retry: re-creating the same tag after a partial failure only publishes what is still missing.

An execution pinned to the release also installs the packages the release shipped with, instead of whatever the dependencies editor holds later. That resolution walks the inheritance chain like the live one does, so a parent workspace that never cut the tag keeps contributing its current packages — see Versioning dependencies for the exact rules.

When the workspace version is published, every bare module import in the published snapshots is pinned to the new tag, so the versioned code keeps running against the exact module code it was released with:

// Working copy (unchanged)
const { myFunc } = fcode.import("my-module");
// Published v1.0.0 snapshot
const { myFunc } = fcode.import("my-module", { version: "v1.0.0" });

Only imports of modules owned by the workspace are pinned. Imports that already carry a second argument — an options object, or the bare string form ("v0.9.0", or an alias like "production") that predates it — are considered intentional and left untouched, and imports of inherited modules stay bare. The live working copy of your source code is never modified: only the published snapshots are rewritten.

Translations are pinned the same way, in code and in form schemas alike, so a release also freezes the text it shipped with:

// Working copy (unchanged)
fcode.i18n("greetings.hello", { name });
// Published v1.0.0 snapshot
fcode.i18n("greetings.hello", { name }, { version: "v1.0.0" });

A call whose options already name a version is left untouched; options that name none — for example only a locale — get the version spliced in, so those calls freeze too while the rest of their options stays as written. See Internationalization for how a pinned call resolves, including what happens when a locale has no snapshot at that tag.

Deleting a workspace version cascades: every owned process, module, locale and dependency version carrying the tag is deleted, together with the aliases pointing at those versions and the executions and schedules that reference them. Calls pinned to a deleted locale version go back to resolving against the current translations, and executions pinned to a deleted dependency version install the current packages. Use it to clean up a release that should never run again.

Deletion is rejected while a workspace alias still points at the version — delete or re-point the alias first. If some entity version cannot be deleted, the workspace version record is kept and the error lists the remaining entities, so retrying the deletion finishes the job.

The cascade also reaches the entities you deleted since the release (see below): when the workspace version being deleted was the last one containing a deleted process, module or locale, that entity is removed for good, with its remaining aliases, executions and schedules.

Deleting entities that a workspace version contains

Section titled “Deleting entities that a workspace version contains”

A published workspace version is a snapshot of the workspace, and it stays complete even when you delete part of the workspace afterwards. Deleting a process, module or locale that at least one workspace version contains does not remove it: the entity is marked as deleted and kept, read-only, for as long as a workspace version contains one of its snapshots. Its page shows a banner naming the versions that retain it and opens on its newest published version.

While it is deleted:

  • it disappears from the processes, modules and locales lists and from every listing and resolution against the current workspace. Its page is still reachable from what refers to it: the executions it ran, the schedules pinned to one of its versions, and the manifest of each workspace version that contains it;
  • its published versions still run: a webhook, form, fcode.import or fcode.i18n call that names one of the retaining versions (or an alias pointing at one) behaves as before the deletion, and a child workspace pinned to such a version keeps resolving it. Called without a version it is not found;
  • the executions it already ran are kept, and so are the schedules pinned to one of its versions. Schedules on its current version are deleted, as are its process tags and its error-handler role;
  • its manually published versions (a tag no workspace version carries) are deleted with it, as they would be for any deleted entity, together with their aliases;
  • moving a workspace alias to a version that does not contain it removes the entity’s alias (the alias manifest reports it as ALIAS_REMOVED), while a version that does contain it re-points the alias as usual.

The deletion completes when the last workspace version containing the entity is deleted — either the version itself or just that entity’s snapshot — at which point the entity, its remaining aliases, executions and schedules are removed. Deleting an entity that no workspace version contains removes it immediately, as it always did.

Creating a process with the slug (or name) of a deleted one, or a module or locale with its name, revives it: the new entity keeps the deleted one’s identity, so the versions that retained it are listed as its own history, and its content is what you just wrote. Renaming another entity into a deleted one’s slug or name is rejected.

A module is still refused for deletion while a process, or a process version that imports it without a version, imports it — those imports resolve the module live. Imports pinned to a version no longer block, because they keep resolving through the snapshot.

Once the workspace has a version, a version selector appears in the sidebar, as a pill in the header of the Develop section, listing Live, the workspace aliases (each with the tag it points at) and the version tags. Picking one puts the workspace in version mode, remembered per workspace in your browser so it survives navigation and reloads (a link carrying ?version=<tag or alias> selects that version on arrival):

  • the processes, modules and translations lists show the entities that version contains — the ones deleted since the release included, marked as deleted — and hide the ones created after it;
  • the process, module, translation and dependencies editors show the snapshot published at that version, read-only;
  • Run now, new schedules, the webhook snippet and the form embed code pin to that version. An alias is sent as its name, so a schedule created under production follows the alias when it is re-pointed.

A notice heading the processes, modules, translations and dependencies pages names the version, and its Back to live action — or picking Live in the selector — returns to the current workspace. Inherited processes, modules and translations are not affected: they follow the version pin of the parent link.

Workspace aliases work like process version aliases, but across the whole workspace: pointing the alias production at v1.0.0 creates or updates the production alias on every owned process, module, locale and dependency manifest that has a v1.0.0 version published.

Entities without the target tag (for example a process created after the release) are skipped and reported in the alias manifest; their existing alias, if any, is left untouched.

Since executions, schedules, webhooks, module imports and pinned dependency resolution all accept an alias wherever they accept a tag, moving the production alias to another workspace version re-points the whole workspace in one operation — code, translations and installed packages together, which makes rollbacks a single alias change.

Renaming a workspace alias renames the per-entity aliases in place, so schedules and executions pinned to the alias keep working under the new name. The new name must not be taken by another workspace alias, and if a process or module has a manually created alias with that name, the workspace alias takes ownership of it.

The same operations are available from the CLI:

Terminal window
$ fcode settings:versions:create v1.0.0 --comment "First stable release"
$ fcode settings:aliases:set production v1.0.0

fcode settings:pull also writes the workspace versions and aliases into settings.json (read-only fields, for visibility and git history), and fcode pull writes each published dependency manifest into dependencies/versions/<tag>/.

A process, module or locale that a workspace version keeps after its deletion stays in the local workspace too: fcode pull writes it read-only, versions/ included, and lists it in the deleted column of fcode processes:status (modules:status, i18n:status) with the versions that retain it. fcode push skips it, and editing its files only warns. It leaves the workspace on the pull that follows the deletion of the last retaining version.