CollabOps

Step Outputs

Passing data between Steps with $COLLABOPS_OUTPUT — dynamic image tags and branch-based routing

A practical example of passing data between Steps using $COLLABOPS_OUTPUT. Image tags are dynamically generated based on the branch.

Use collabops/docker-login for generic Docker registries (GHCR, Docker Hub, Harbor, etc.). For GCP Artifact Registry use gcloud-docker-auth, and for AWS ECR use aws-ecr-auth. Pushing without authentication returns denied from the registry.

Full Code

name: dynamic-image-tags

triggers:
  push:
    # Runs on main and hotfix branches
    branches: ["main", "hotfix/*"]

# Define registry information as global variables
env:
  REGISTRY: ghcr.io
  IMAGE_BASE: ghcr.io/my-org/my-app

jobs:
  build-and-push:
    services:
      - docker
    steps:
      # 1. Source code checkout
      - name: checkout
        uses: "collabops/checkout@v2"
        with:
          repo-url: "https://<collabops-host>/<workspace>/<repository>.git"

      # 2. Registry login — creates .docker/config.json
      - name: registry-login
        uses: "collabops/docker-login@v1"
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ secrets.REGISTRY_USERNAME }}
          password: ${{ secrets.REGISTRY_PASSWORD }}

      # 3. Dynamically generate image tags based on branch
      - name: prepare-tags
        id: tags                    # Identifier for referencing from other Steps
        image: debian:bookworm-slim
        env:
          COLLABOPS_REF: ${{ collabops.ref }}
          COMMIT_SHA: ${{ collabops.sha }}
          IMAGE_BASE: ${{ env.IMAGE_BASE }}
        run: |
          set -eu

          # refs/heads/main → main
          # refs/heads/hotfix/v1.2 → hotfix-v1.2
          REF_TAG=$(echo "${COLLABOPS_REF}" | sed 's|refs/heads/||' | sed 's/\//-/g')

          # Tag strategy per branch
          if echo "${COLLABOPS_REF}" | grep -q 'refs/heads/hotfix/'; then
            # Hotfix branch: branch name tag + SHA tag
            echo "tag1=${IMAGE_BASE}:${REF_TAG}" >> $COLLABOPS_OUTPUT
            echo "tag2=${IMAGE_BASE}:${COMMIT_SHA}" >> $COLLABOPS_OUTPUT
          else
            # Main branch: SHA tag + latest tag
            echo "tag1=${IMAGE_BASE}:${COMMIT_SHA}" >> $COLLABOPS_OUTPUT
            echo "tag2=${IMAGE_BASE}:latest" >> $COLLABOPS_OUTPUT
          fi

      # 4. Build & push with generated tags — uses the credentials above automatically
      - name: build-push
        uses: "collabops/docker-build-push@v1"
        with:
          tags: |
            ${{ steps.tags.outputs.tag1 }}
            ${{ steps.tags.outputs.tag2 }}

      # 5. Verify results
      - name: verify-push
        image: debian:bookworm-slim
        run: |
          echo "Push complete:"
          echo "  Tag1: ${{ steps.tags.outputs.tag1 }}"
          echo "  Tag2: ${{ steps.tags.outputs.tag2 }}"

Tag Results by Branch

Branchtag1tag2
mainmy-app:&lt;commit-sha&gt;my-app:latest
hotfix/v1.2my-app:hotfix-v1.2my-app:&lt;commit-sha&gt;

Key Points

You must specify id: tags to reference outputs via $\{\{ steps.tags.outputs.* \}\}.

Multiple values can be stored in $COLLABOPS_OUTPUT in key=value format.

Shell conditionals are used to branch the tag strategy per branch.

Output values can only be referenced by subsequent Steps within the same Job.

Without a collabops/docker-login@v1 step before the push, the registry returns denied — substitute gcloud-docker-auth for GCP and aws-ecr-auth for AWS.

Table of Contents