Publishing Role Images
Required OCI labels
Section titled “Required OCI labels”Every published role image must carry two OCI labels that jackin reads at launch time:
| Label | Value | Purpose |
|---|---|---|
jackin.construct_version | The version tag from the FROM line (e.g. 0.2) | Staleness detection — jackin warns when the published image was built from an older construct than the one currently resolved for a new build |
jackin.role_git_sha | The git commit SHA of the role repo at build time | Version display and staleness tracking |
Using the provided workflow (recommended)
Section titled “Using the provided workflow (recommended)”Role repositories on GitHub should call the jackin-project/jackin-role-action reusable workflow. It handles label injection, Docker layer cache ordering, GitHub API authentication, multi-platform builds (linux/amd64 and linux/arm64), image signing, and manifest assembly automatically.
A minimal caller workflow in your role repo:
name: Publish Image
on: push: branches: [main] paths: - 'Dockerfile' - 'jackin.role.toml' - '.github/workflows/publish-image.yml' workflow_dispatch:
jobs: publish: uses: jackin-project/jackin-role-action/.github/workflows/publish.yml@<SHA> # pin to a release SHA permissions: contents: read id-token: write secrets: registry-username: ${{ secrets.DOCKERHUB_USERNAME }} registry-password: ${{ secrets.DOCKERHUB_TOKEN }} gh-readonly-token: ${{ secrets.GH_READONLY_TOKEN }}Replace <SHA> with the pinned commit SHA from the jackin-role-action releases. Renovate can keep the pin current automatically — the generated role repo scaffold includes a Renovate configuration with the right pattern.
What the workflow does automatically:
- Runs
jackin-role validateandjackin-role construct-versionto extract the construct version from yourFROMline. - Applies
jackin.construct_versionandjackin.role_git_shaas OCI labels at build time viadocker/build-push-action’slabels:input — noARGorLABELdeclarations needed in your Dockerfile. - Builds separate image manifests for
linux/amd64andlinux/arm64. - Assembles and pushes a multi-platform manifest list.
- Signs the image with Sigstore cosign.
Your Dockerfile only needs to declare the tools your role installs. The FROM projectjackin/construct:<version>-<distro> line is the construct version source of truth — the workflow reads it automatically.
Custom CI/CD
Section titled “Custom CI/CD”If your role repo is not on GitHub, or if you use a different CI/CD system (GitLab CI, Jenkins, Buildkite, CircleCI, etc.), you must apply the two labels yourself at build time.
Minimum required steps
Section titled “Minimum required steps”-
Determine the construct version
Read the version from your Dockerfile’s
FROMline. The version is the part between:and-in the construct tag:FROM projectjackin/construct:0.3-trixie# ^^^— this is the construct versionIf the
jackin-rolebinary is available in your CI environment (download it from the jackin releases), you can extract it automatically:Terminal window CONSTRUCT_VERSION=$(jackin-role construct-version .)Otherwise, parse it directly from the
FROMline:Terminal window CONSTRUCT_VERSION=$(grep -m1 '^FROM projectjackin/construct:' Dockerfile \| sed 's|FROM projectjackin/construct:\([^-]*\)-.*|\1|') -
Get the role commit SHA
Terminal window ROLE_GIT_SHA=$(git rev-parse HEAD) -
Build the image with both labels
Pass both labels using
--labelflags:Terminal window docker build \--label "jackin.construct_version=${CONSTRUCT_VERSION}" \--label "jackin.role_git_sha=${ROLE_GIT_SHA}" \-t your-registry/your-role:latest \.No
ARGorLABELdeclarations are needed in the Dockerfile.
Layer cache ordering
Section titled “Layer cache ordering”ARG instructions in a Dockerfile invalidate all subsequent layers when the argument value changes. A git SHA changes on every commit — so if you declare ARG ROLE_GIT_SHA inside the Dockerfile, every commit busts the layer cache for everything below it.
Using --label at build time (or the labels: input in docker/build-push-action) bypasses this: the label is applied to the final image manifest without touching the Dockerfile instruction stream. Your expensive tool-installation RUN layers remain cached across commits.
Example: GitLab CI
Section titled “Example: GitLab CI”build-and-push: stage: build image: docker:27 services: - docker:27-dind script: - CONSTRUCT_VERSION=$(grep -m1 '^FROM projectjackin/construct:' Dockerfile | sed 's|FROM projectjackin/construct:\([^-]*\)-.*|\1|') - ROLE_GIT_SHA=${CI_COMMIT_SHA} - docker login -u "${REGISTRY_USERNAME}" -p "${REGISTRY_PASSWORD}" - > docker build --label "jackin.construct_version=${CONSTRUCT_VERSION}" --label "jackin.role_git_sha=${ROLE_GIT_SHA}" -t "${REGISTRY_IMAGE}:latest" . - docker push "${REGISTRY_IMAGE}:latest"Using a different registry
Section titled “Using a different registry”The reusable workflow accepts a registry input (defaults to Docker Hub) and matching registry-username / registry-password secrets. To publish to a different registry, pass the appropriate values:
jobs: publish: uses: jackin-project/jackin-role-action/.github/workflows/publish.yml@<SHA> permissions: contents: read id-token: write packages: write secrets: registry-username: ${{ github.actor }} registry-password: ${{ secrets.GITHUB_TOKEN }}Set your jackin.role.toml published_image to the full GHCR path:
published_image = "ghcr.io/your-org/jackin-your-role"jobs: publish: uses: jackin-project/jackin-role-action/.github/workflows/publish.yml@<SHA> permissions: contents: read id-token: write secrets: registry: 123456789.dkr.ecr.us-east-1.amazonaws.com registry-username: AWS registry-password: ${{ steps.ecr-login.outputs.token }}Obtain the ECR token in a preceding step using the AWS CLI or the aws-actions/amazon-ecr-login action, then pass it as registry-password. Set published_image in your manifest to the full ECR URI.
jobs: publish: uses: jackin-project/jackin-role-action/.github/workflows/publish.yml@<SHA> with: registry: registry.your-org.internal secrets: registry-username: ${{ secrets.REGISTRY_USER }} registry-password: ${{ secrets.REGISTRY_PASS }}jackin’ must be able to pull the image at launch time. If you publish to a private registry, the credentials must be available in the operator’s Docker environment before running jackin load or jackin console. Configure Docker credentials on the operator’s machine using docker login <registry> or a credential helper.
Minimum Dockerfile requirements
Section titled “Minimum Dockerfile requirements”- The final stage must start from
projectjackin/construct:<version>-<distro>(see Role Repositories for the full contract). - No
ARG CONSTRUCT_VERSIONorARG ROLE_GIT_SHAdeclarations are needed. The workflow or--labelflags at build time handle both. - The construct version jackin reads for staleness detection comes from the
FROMline — not from a label or ARG. Keep the version tag in theFROMline accurate and let Renovate track updates.