LogoCyanPrint

Push to Registry

Build and publish your plugin to a container registry

Push to Registry

Publish your plugin to a container registry so others can use it.

Prerequisites

  • Docker installed and logged in
  • Access to a container registry (Docker Hub, GitHub GHCR, etc.)
  • Plugin code ready to publish
  • Dockerfile includes LABEL cyanprint.dev=true (see Plugin Dockerfile)

Build and Push

Tag Your Image

Choose a naming convention for your plugin:

# Docker Hub
docker tag my-plugin:dev username/my-plugin:latest
# GitHub Container Registry
docker tag my-plugin:dev ghcr.io/orgname/my-plugin:latest
# Private registry
docker tag my-plugin:dev registry.company.com/plugins/my-plugin:latest

Push to Registry

# Login to Docker Hub
docker login
# Push
docker push username/my-plugin:latest
# Also push a versioned tag
docker push username/my-plugin:1.0.0
# Login to GitHub Container Registry
echo $GITHUB_TOKEN | docker login ghcr.io -u USERNAME --password-stdin
# Push
docker push ghcr.io/orgname/my-plugin:latest
docker push ghcr.io/orgname/my-plugin:1.0.0
# Login to private registry
docker login registry.company.com
# Push
docker push registry.company.com/plugins/my-plugin:latest

Verify the Push

# Pull the image to verify
docker pull username/my-plugin:latest
# Run a test
docker run --rm username/my-plugin:latest

Pushing to a container registry is only part of the process. You must also register your plugin with the CyanPrint registry (Zinc) for the system to discover and use it. See Register Your Plugin below.

Naming Convention

Use the username/plugin-name or org/plugin-name format for your Docker images:

PatternExampleDescription
org/plugin-nameatomi/setup-pluginOrganization namespace
username/plugin-namejohndoe/git-initUser namespace
registry/org/plugin-nameghcr.io/atomi/plugins/setupFull registry path

The system uses the username/name[:version] format to reference plugins in templates. Container names are auto-generated internally by the system.

Versioning

Semantic Versioning

Use semantic versioning for releases:

# Major version (breaking changes)
docker tag my-plugin:dev org/my-plugin:2.0.0
# Minor version (new features)
docker tag my-plugin:dev org/my-plugin:1.1.0
# Patch version (bug fixes)
docker tag my-plugin:dev org/my-plugin:1.0.1
# Latest tag (current stable)
docker tag my-plugin:dev org/my-plugin:latest

Using in Templates

Templates can pin to specific versions:

# cyan.yaml
plugins:
- name: org/my-plugin:1.0.0 # Pinned version
config: {}
- name: org/my-plugin:latest # Always latest
config: {}

Version references are exact matches or latest. The system does not perform semantic version range matching (e.g., org/plugin:1 will not resolve to the latest 1.x.x).

Automation

GitHub Actions

Create .github/workflows/publish.yml:

name: Publish Plugin
on:
release:
types: [published]
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract version
id: version
run: echo "VERSION=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT
- name: Build and push
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: |
ghcr.io/${{ github.repository_owner }}/my-plugin:latest
ghcr.io/${{ github.repository_owner }}/my-plugin:${{ steps.version.outputs.VERSION }}

This workflow pushes the Docker image to GHCR only. You must also register the plugin with the CyanPrint registry for the system to discover it.

CI/CD Pipeline

# Example GitLab CI
stages:
- build
- publish
build:
stage: build
image: docker:latest
script:
- docker build -t my-plugin:$CI_COMMIT_SHA .
publish:
stage: publish
image: docker:latest
only:
- tags
script:
- docker tag my-plugin:$CI_COMMIT_SHA registry.company.com/plugins/my-plugin:$CI_COMMIT_TAG
- docker push registry.company.com/plugins/my-plugin:$CI_COMMIT_TAG

Register Your Plugin

After pushing your Docker image to a container registry, you must register the plugin with the CyanPrint registry (Zinc) for the system to discover and use it.

The CyanPrint registry stores plugin metadata including:

  • Docker Reference: The full Docker image path (e.g., ghcr.io/org/my-plugin)
  • Docker Tag: The version tag (e.g., 1.0.0, latest)
  • Plugin metadata: Information from your plugin's cyan.yaml

For details on registering your plugin with the CyanPrint registry, refer to the Plugin Registry documentation.

Verify Registration

To verify your plugin is properly registered:

  1. Ensure the Docker image is accessible from the container registry
  2. Confirm the plugin metadata is registered in the CyanPrint registry
  3. Test by using the plugin in a template generation

Documentation

Include usage documentation with your plugin:

README.md

# My Plugin
A CyanPrint plugin that [description].
## Configuration
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `option1` | `string` | `""` | Description of option1 |
| `option2` | `boolean` | `false` | Description of option2 |
## Usage
Add to your template's `cyan.yaml`:
\`\`\`yaml
plugins:
- name: org/my-plugin:1.0.0
config:
option1: value1
option2: true
\`\`\`