Automated Builds
Automate your Docker builds so every release is pushed to the Self-Host Pro registry without manual intervention.
Release strategy
A common pattern uses three release channels:
| Channel | Trigger | Tags | Use case |
|---|---|---|---|
| Edge | Push to main | edge-main | Continuous deployment for testing |
| Prerelease | GitHub prerelease | prerelease, prerelease-v1.0.0-beta.1 | Beta testing with select customers |
| Stable | GitHub release | latest, 1.2.0, 1 | Production releases |
This gives you flexibility — push to main for instant edge builds, create a prerelease for beta feedback, then publish a stable release when ready.
Reusable workflow pattern
Instead of duplicating build logic, create a reusable workflow that handles the actual build, then call it from simple trigger workflows.
Build workflow
This workflow handles dependency caching, asset compilation, and pushing to the registry:
name: Docker Build & Publish
on:
workflow_call:
inputs:
docker-tags:
required: true
type: string
description: "Comma or newline separated list of Docker tags"
dockerfile:
type: string
default: "./Dockerfile"
environment:
type: string
required: true
version:
type: string
required: false
jobs:
docker-publish:
runs-on: ubuntu-24.04
steps:
- name: Checkout
uses: actions/checkout@v4
# Add your build steps here (dependency install, asset compilation, etc.)
- name: Build and push
uses: serversideup/github-action-docker-build@v6
with:
tags: ${{ inputs.docker-tags }}
dockerfile: ${{ inputs.dockerfile }}
registry: "shpcr.io"
registry-username: ${{ secrets.SHPCR_USERNAME }}
registry-password: ${{ secrets.SHPCR_PASSWORD }}
Trigger workflows
Each release channel gets a simple workflow that calls the build workflow with appropriate tags:
name: Edge Release
on:
push:
branches:
- main
jobs:
build:
uses: ./.github/workflows/service_docker-build-and-publish.yml
with:
docker-tags: "shpcr.io/your-team/your-product:edge-${{ github.ref_name }}"
environment: edge
secrets: inherit
name: Pre-Release
on:
release:
types: [prereleased]
jobs:
build:
uses: ./.github/workflows/service_docker-build-and-publish.yml
with:
docker-tags: |
shpcr.io/your-team/your-product:prerelease
shpcr.io/your-team/your-product:prerelease-${{ github.ref_name }}
environment: prerelease
secrets: inherit
name: Stable Release
on:
release:
types: [released]
jobs:
prepare:
runs-on: ubuntu-latest
outputs:
version: ${{ steps.set-version.outputs.version }}
major: ${{ steps.set-version.outputs.major }}
steps:
- name: Parse version from tag
id: set-version
run: |
VERSION="${{ github.ref_name }}"
VERSION="${VERSION#v}"
MAJOR="${VERSION%%.*}"
echo "version=${VERSION}" >> $GITHUB_OUTPUT
echo "major=${MAJOR}" >> $GITHUB_OUTPUT
build:
needs: prepare
uses: ./.github/workflows/service_docker-build-and-publish.yml
with:
docker-tags: |
shpcr.io/your-team/your-product:latest
shpcr.io/your-team/your-product:${{ needs.prepare.outputs.version }}
shpcr.io/your-team/your-product:${{ needs.prepare.outputs.major }}
environment: production
secrets: inherit
Required secrets
Add these secrets to your GitHub repository:
| Secret | Value |
|---|---|
SHPCR_USERNAME | Your Self-Host Pro email |
SHPCR_PASSWORD | Your team access token |
See Docker Registry for how to generate an access token.
Other CI/CD systems
The same pattern works with any CI/CD system — GitLab CI, CircleCI, Jenkins, etc. The core steps are:
- Log in to the registry with
docker login shpcr.io - Build your image
- Tag with appropriate version(s)
- Push to
shpcr.io
The workflows above are just orchestration around standard Docker commands.