Blocks

Blocks are the modular building units of a Polycrate workspace: block.poly structure, block instances and template blocks, recommended metadata, vulnerability products, changelog and examples.poly.

Blocks

Blocks

A Polycrate workspace is a modular system made up of so-called blocks. Blocks are specialized code/function building units that can be configured via the block config (default: block.poly) or the workspace config (default: workspace.poly). Blocks offer actions that can be executed with polycrate run $BLOCK_NAME $ACTION_NAME.

Polycrate looks for blocks in the block root directory (default: blocks inside the workspace directory). Nested directories (e.g. blocks/foo/bar/baz) are allowed.

Block instances

A block instance is an entry under blocks: in workspace.poly. It can consist ad hoc of configuration only (without its own block directory under blocks/), in which case it uses only the tools available in the Polycrate container – or it references a template block with from:.

Template blocks live under blocks/ (locally) or are typically pulled from an OCI-compatible registry. The instance can inherit defaults and the working directory from the template and, if needed, override or extend config: and actions:.

Colloquially, block instances and template blocks are often referred to jointly as a “block” or “blocks”.

Block directory structure

The block directory is the directory below the block root that contains the custom code and the block configuration (block.poly) of a block.

Typical structure:

blocks/my-block/
├── block.poly              # Block configuration (required)
├── README.md               # Documentation
├── CHANGELOG.poly          # Version history (→ Block changelog)
├── examples.poly           # Configuration examples (→ Block examples)
├── install.yml             # Ansible playbook: installation
├── uninstall.yml           # Ansible playbook: uninstallation
├── backup.yml              # Ansible playbook: backup (optional)
├── templates/              # Jinja2 templates for Ansible
│   ├── values.yaml.j2
│   └── deployment.yml.j2
└── scripts/                # Bash/Python scripts (if used)
    └── init.sh

Block configuration (block.poly)

The block configuration contains the metadata and configuration for a single block.

Minimal block.poly

name: acme-demo-app
version: 1.0.0

actions:
  - name: install
    playbook: install.yml

Extended block.poly

# blocks/acme-demo-postgres/block.poly
name: acme-demo-postgres
version: 1.2.3
kind: k8sapp
type: database
flavor: postgresql

# Freely definable configuration (defaults)
config:
  namespace: default
  replicas: 1
  database:
    name: mydb
    user: dbuser
  persistence:
    enabled: true
    size: 10Gi
    storageClass: standard

# Actions
actions:
  - name: install
    playbook: install.yml

  - name: backup
    playbook: backup.yml

  - name: restore
    playbook: restore.yml

The config: section is freely definable and not typed.

Recommended metadata

For template blocks that end up in the hub or as a catalogue app, the following fields should be set. The source of truth is block.poly.

Identity & classification

Field Recommended Description
name yes Technical block name (naming rules)
display_name yes Human-readable title (hub, local). On API publish after blocks push (CLI ≥ 0.51.3) the API field display_name is the registry URL
description yes Short description
icon_url yes Icon URL for hub/API UI
kind yes e.g. k8sapp, k8scluster, linuxapp, dockerapp, library, generic
type yes* Category, e.g. db, kv, mq, s3, web (*for apps)
flavor yes* Technology, e.g. postgresql, redis
implementation optional Operator/stack, e.g. cnpg
alias optional Alternative search names
labels optional Free key/value labels
supports_ha optional true if HA is supported

Version & license

Field Recommended Description
version yes Block version (SemVer)
app_version yes* Upstream app version (outdated/upstream comparison)
license yes e.g. Apache-2.0
license_url optional Link to the license text

URLs

Field Recommended Description
website_url yes Project website
documentation_url yes Documentation
git_repository_url yes* Upstream Git (catalogue meta sync)
releases_url yes* Upstream releases (GitHub sync)

* especially for catalogue apps with upstream tracking.

name: postgres
display_name: "CloudNativePG PostgreSQL"
icon_url: https://cdn.example.com/icons/postgresql.svg
kind: k8sapp
type: db
flavor: postgresql
implementation: cnpg
supports_ha: true
description: "PostgreSQL with CloudNativePG"
app_version: "16.2"
license: Apache-2.0
website_url: https://cloudnative-pg.io
documentation_url: https://cloudnative-pg.io/documentation/
git_repository_url: https://github.com/cloudnative-pg/cloudnative-pg
releases_url: https://github.com/cloudnative-pg/cloudnative-pg/releases

→ Short rules: Best practices – metadata

Vulnerability products

Optional key vulnerability.products — for template blocks that end up as a catalogue app: product identities for CVE/OSV matching.

The section is identity only (vendor/product/PURL/…). No CVE lists and no enrichment in block.poly.

# block.poly (excerpt)
name: authentik
version: 0.12.0
kind: k8sapp
app_version: "2025.2.0"
releases_url: https://github.com/goauthentik/authentik/releases
git_repository_url: https://github.com/goauthentik/authentik

vulnerability:
  products:
    - vendor: goauthentik
      product: authentik
      ecosystem: Go
      purl: "pkg:golang/goauthentik.io/authentik"
      # cvefeed_product_id: "12345"   # optional
      # cpe: "cpe:2.3:a:goauthentik:authentik:*:*:*:*:*:*:*:*"  # optional
Field Required Description
vendor yes Vendor / upstream organization
product yes Product name for matching
ecosystem no OSV ecosystem (e.g. Go, PyPI, npm, Maven) – without a value there is no meaningful OSV query
purl no Package URL
cpe no CPE string
cvefeed_product_id no External product ID (e.g. CVEfeed)

Behavior

  • Section missing: the block remains valid; products can be maintained manually in the catalogue app tab Vulnerability Products.
  • Section present: after hub/template block import or periodic sync, the API takes over the entries as VulnerabilityProduct (source=block). The block is the source of truth for these keys; manually created rows (source=manual) are preserved.
  • Without products in the block and the UI: the CVE catalogue enrichment (OSV) has nothing to match.

→ Best practices · API: Vulnerability Management

Naming rules

Short overview – details, regex and examples:

→ Naming conventions

Registry examples in this documentation often use the fictional organization acme and the registry registry.acme.corp (convention for generic examples).

Block versions and instances

Best practices:

  • Explicit versions: always specify the version in the from: key (from: .../block:1.2.3)
  • Consistency: update all instances at the same time when upgrading
  • Validation: run polycrate validate workspace-poly ./workspace.poly after version updates

→ Detailed information in Dependencies

Missing block dependencies

If a block in workspace.poly references a block via from: that is not present in the workspace (or has a different version than requested), the command aborts with an error message (excerpt, varies slightly depending on the code path):

dependency 'cargo.ayedo.cloud/ayedo/k8s/postgres' not found in the Workspace. Please run `polycrate workspace update`, `polycrate block pull cargo.ayedo.cloud/ayedo/k8s/postgres` or run Polycrate with the `--blocks-auto-pull` flag

(polycrate block and polycrate blocks are the same command.)

Resolution:

  1. Include the dependency: polycrate workspace update and/or polycrate block pull <registry/path/block-name>:<version> (alias: polycrate blocks pull …)
  2. Automatically on run: polycrate run ... --blocks-auto-pull – missing blocks are pulled automatically before execution

→ Inheritance and from:

Block changelog

Every block can contain a CHANGELOG.poly. Recommended for reusable blocks — see the format below; SemVer notes: Best practices – block scoping.

The format has no author field; authorship can be documented in description: or in the Git commit if needed.

CHANGELOG.poly format

# blocks/my-block/CHANGELOG.poly
- version: "1.2.0"
  date: "2025-12-30"
  type: feat
  message: "Added new feature"
  description: |
    - Implemented feature A
    - Fixed bug B
    - Improved performance

- version: "1.1.0"
  date: "2025-12-15"
  type: fix
  message: "Bugfixes and improvements"
  description: |
    - Fixed critical bug
    - Updated documentation

Changelog types

Type Description
feat New feature
fix Bugfix
chore Maintenance, dependencies
breaking Breaking change
docs Documentation

Showing the changelog

# Show the block changelog in an interactive TUI
polycrate block changelog my-block

# Show the changelog format specification
polycrate block changelog --spec

The TUI shows all versions with details and allows navigation with j/k or the arrow keys.

Block examples (examples.poly)

Blocks can ship an examples.poly file in the block directory containing typical configuration scenarios as named examples. The examples are shown in the CLI as an interactive TUI or as plain text and serve as a template for workspace.poly.

Format

examples.poly is a YAML mapping from example names to a config: section:

# blocks/acme-postgres/examples.poly
single-node:
  config:
    replicas: 1
    database:
      name: devdb
      user: devuser
    persistence:
      enabled: false

ha-production:
  config:
    replicas: 3
    database:
      name: proddb
      user: appuser
    persistence:
      enabled: true
      size: 100Gi
      storageClass: fast-ssd

read-replica:
  config:
    replicas: 2
    read_replica: true
    persistence:
      enabled: true
      size: 50Gi

The config: section of each example corresponds directly to the config: section that can be entered under the block instance in workspace.poly.

Showing examples

# Interactive TUI (select + view details)
polycrate block examples my-block

# Plain-text output (CI, scripting)
polycrate block examples my-block --no-pager

The TUI shows all examples as a navigable list. Enter shows the complete config: section of the selected example as YAML, Esc returns to the list.

Using an example in the workspace

# workspace.poly — adopt an example configuration
blocks:
  - name: postgres
    from: cargo.ayedo.cloud/ayedo/k8s/postgres:2.1.0
    config:
      replicas: 3
      database:
        name: proddb
        user: appuser
      persistence:
        enabled: true
        size: 100Gi
        storageClass: fast-ssd

Hub display

Blocks published on the PolyHub show their examples.poly content in the block detail view. On block push the file is automatically uploaded as part of the block package.


See also