Skip to main content
Version: v5.6.1

3.4 Templates and versions

Included from Basic tiertemplates

After this you can: create a template, pin a version to an exact revision, assign it to assets, and run the version lifecycle with its in-use protections.

Before you start — tick each one:

  • Lesson 3.3 — Git remotes and the identity policy (opschain learn 3.3)

In the GUI: the Templates tab on a project page, beside Git remotes — versions, the assets pinned to each, lock/unlock/archive.

Lesson 1.1 ended with an asset pinned to a template version; this lesson is where that version comes from. A template names which remote its content comes from, a template version pins a revision — branch, tag or commit — of that repository, and every asset pinned to a version takes its action catalog from that exact commit. By the end you will have cut a version, moved assets onto it, and seen the server refuse to pull a version out from under the assets that use it.

1. Create a template and pin its first version​

Both can be made in one command, against the remote from lesson 3.3:

opschain templates create acme \
--code web_tier --name "Web Tier" \
--git-remote infra \
--version 1.0.0 --git-rev v1.0
created template acme/web_tier (01a14002-…-example)
created version 1.0.0 (ready, git rev v1.0 (0a1b2c3))

The server resolves --git-rev against the remote right away: the version stores both the revision you asked for and the exact commit it resolved to, so what a version means never drifts — and a commit you rehearsed locally with --ref before pushing (lesson 2.6) is exactly what pinned assets will run. A revision that does not exist in the repository is a named 422 (Git rev must match a Git revision (branch/tag/commit) in the template's Git remote), not a stored mistake.

Template codes are immutable and lowercase ([a-z0-9_]+). The repository itself carries the template's content — its actions under .opschain/templates/<code>/actions/ — authored exactly as lessons 2.1 and 2.4 taught, which is why a template version is "a revision of a repo" and nothing more.

2. Assign a version to assets​

Assets met templates in lesson 1.1: nodes create … --template web_tier:1.0.0 pins at creation. templates assign is the fleet move — repoint existing assets at a version in one command:

opschain templates assign acme/web_tier --version 1.1.0 \
--asset acme/environments/dev/assets/web \
--asset acme/environments/dev/assets/api
assigned version 1.1.0 of acme/web_tier to 2 asset(s)

Each asset must already belong to this template (the server refuses a cross-template assignment by name), and you need update rights on the template and on every named asset.

How template actions reach the asset catalog. Assigning (or pinning at creation) opens a new entry in the asset's version history and refreshes its action catalog in the background — the server checks out the version's pinned commit and derives the actions it declares. Until the refresh lands, the previous catalog keeps serving, so a broken revision never leaves an asset with no actions. From there it is lesson 3.1's world: opschain actions list shows the catalog, and runs create change executes from it.

opschain nodes show acme/environments/dev/assets/web # template: web_tier:1.1.0
opschain actions list --project acme --env dev --asset web # the refreshed catalog

Declarative YAML action files are the default authoring lane and run on any runner. A template whose repository also carries an actions.rb or a MintModel document — applicable only to existing MintPress customers and those using the MintPress SDK or the packs:mintpress feature — has those actions derived on a Ruby-capable runner and merged into the same catalog, gated by the packs:mintpress entitlement per step; opschain docs packs-mintpress covers that lane in full.

3. The version lifecycle​

templates show is the lifecycle dashboard:

opschain templates show acme/web_tier
code: web_tier
id: 01a14002-…-example
project: acme
name: Web Tier
description: -
type: asset
git_remote: infra
archived: false
versions:
VERSION STATE GIT REV LOCKED ARCHIVED IN USE
1.0.0 ready v1.0 (0a1b2c3) no no -
1.1.0 ready main (9f8e7d6) no no 2 asset(s)

New versions come from version upsert — the same command updates an existing version's revision or description:

opschain templates version upsert acme/web_tier --version 1.2.0 --git-rev release/1.2
upserted version 1.2.0 of acme/web_tier (ready, git rev release/1.2 (4c5d6e7))
opschain templates version upsert acme/web_tier --version 1.2.0 --fetch

--fetch re-resolves the stored revision against the remote — a version pinned to a branch picks up its new head; --float makes that the version's standing behaviour. Versions that assets are in use by are protected: changing or fetching their revision, unlocking them, or archiving them is refused with a named error —

opschain templates version archive acme/web_tier --version 1.1.0
Error: the server answered HTTP 422: Template version cannot be archived as the version is currently in use

— and --ignore-in-use is the deliberate override: it accepts the risk and, for a revision change, rolls the pinned assets onto the newly resolved commit (their catalogs refresh again).

lock is the release freeze: a locked version accepts no revision or metadata changes until unlocked.

opschain templates version lock acme/web_tier --version 1.1.0
locked version 1.1.0 of acme/web_tier

archive retires a version from assignment without deleting anything; unarchive brings it back. The everyday flow is: upsert the next version → assign it → lock what production runs. The GUI's screens ride the same calls over the v2 API (opschain docs api-v2), with the same in-use refusals.

Check yourself​

  • Archive the version your assets pin: what does the server answer, and which column of templates show tells you why before you try?

What you learned​

  • A template names a remote; a version pins a revision of it and stores the exact commit it resolved to, so a version never drifts.
  • templates assign --version … --asset … repins assets in one move and refreshes their action catalogs in the background, the old catalog serving until the new one lands.
  • version upsert cuts or repins versions, --fetch/--float follow a moving branch, and lock freezes a release.
  • A version in use refuses a revision change, unlock or archive by name; --ignore-in-use is the explicit override that rolls the assets forward with it.

Next: lesson 3.5 — Secrets and the vault (opschain learn 3.5), or back to your track (opschain learn).