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 Hubdocker tag my-plugin:dev username/my-plugin:latest# GitHub Container Registrydocker tag my-plugin:dev ghcr.io/orgname/my-plugin:latest# Private registrydocker tag my-plugin:dev registry.company.com/plugins/my-plugin:latest
Push to Registry
# Login to Docker Hubdocker login# Pushdocker push username/my-plugin:latest# Also push a versioned tagdocker push username/my-plugin:1.0.0
# Login to GitHub Container Registryecho $GITHUB_TOKEN | docker login ghcr.io -u USERNAME --password-stdin# Pushdocker push ghcr.io/orgname/my-plugin:latestdocker push ghcr.io/orgname/my-plugin:1.0.0
# Login to private registrydocker login registry.company.com# Pushdocker push registry.company.com/plugins/my-plugin:latest
Verify the Push
# Pull the image to verifydocker pull username/my-plugin:latest# Run a testdocker 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:
| Pattern | Example | Description |
|---|---|---|
org/plugin-name | atomi/setup-plugin | Organization namespace |
username/plugin-name | johndoe/git-init | User namespace |
registry/org/plugin-name | ghcr.io/atomi/plugins/setup | Full 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.yamlplugins:- name: org/my-plugin:1.0.0 # Pinned versionconfig: {}- name: org/my-plugin:latest # Always latestconfig: {}
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 Pluginon:release:types: [published]jobs:publish:runs-on: ubuntu-lateststeps:- uses: actions/checkout@v4- name: Set up Docker Buildxuses: docker/setup-buildx-action@v3- name: Login to GHCRuses: docker/login-action@v3with:registry: ghcr.iousername: ${{ github.actor }}password: ${{ secrets.GITHUB_TOKEN }}- name: Extract versionid: versionrun: echo "VERSION=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT- name: Build and pushuses: docker/build-push-action@v5with:context: .push: truetags: |ghcr.io/${{ github.repository_owner }}/my-plugin:latestghcr.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 CIstages:- build- publishbuild:stage: buildimage: docker:latestscript:- docker build -t my-plugin:$CI_COMMIT_SHA .publish:stage: publishimage: docker:latestonly:- tagsscript:- 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:
- Ensure the Docker image is accessible from the container registry
- Confirm the plugin metadata is registered in the CyanPrint registry
- Test by using the plugin in a template generation
Documentation
Include usage documentation with your plugin:
README.md
# My PluginA CyanPrint plugin that [description].## Configuration| Option | Type | Default | Description ||--------|------|---------|-------------|| `option1` | `string` | `""` | Description of option1 || `option2` | `boolean` | `false` | Description of option2 |## UsageAdd to your template's `cyan.yaml`:\`\`\`yamlplugins:- name: org/my-plugin:1.0.0config:option1: value1option2: true\`\`\`
Related
- Plugin Dockerfile - Container setup
- First Plugin - Create your first plugin