Description:
Problem
When using the workflow template to build and push Docker images, the build fails with the error:
Root Cause
The GitHub Actions workflow uses ${{ github.repository }} directly in Docker image tags. However, Docker registry conventions require repository names to be lowercase. When a GitHub username contains uppercase letters (e.g., "Patechoc"), this causes the build to fail.
Solution
The workflow should NOT convert the repository name to lowercase before building the Docker image, but only the full path/URL to the image artifact.
Use this as example:
# filename: templates/python-basic-webserver/.github/workflows/urbalurba-build-and-push.yaml
#
# GitHub Actions workflow for building and pushing Docker images with unique tags
# and updating Kubernetes manifests for GitOps with ArgoCD
#
# This workflow solves the problem of ArgoCD not detecting new image builds
# when using the same image tag (like "latest"). Instead, it:
#
# 1. Generates a unique tag using commit SHA and timestamp
# 2. Builds and pushes the image with this unique tag
# 3. Updates the Kubernetes manifest with the new tag
# 4. Commits the updated manifest back to the repository
#
# The workflow includes safeguards to prevent infinite build loops:
# - Ignores changes to files in the manifests/ directory
# - Adds [ci-skip] to commit messages for automated changes
# - Checks if the commit was made by GitHub Actions
#
# REQUIREMENTS:
# - Repository needs write permissions for GitHub token (for pushing changes back)
# - Kubernetes manifests must be in a "manifests" directory with deployment.yaml
# - Image reference in deployment.yaml should follow the pattern:
# image: ghcr.io/username/repo-name:tag
name: Build and Push
on:
push:
branches: [main]
paths-ignore:
- 'manifests/**' # Ignore changes to manifest files to prevent workflow loops
permissions:
contents: write # Needed for pushing manifest changes back to repository
packages: write # Needed for pushing to GitHub Container Registry
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
token: ${{ secrets.GITHUB_TOKEN }} # Use token for pushing changes
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.11' # Using Python 3.11
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
- name: Generate unique tag
id: tag
run: |
# Create a unique tag using commit SHA and timestamp
# This ensures each build has a unique, traceable identifier
TIMESTAMP=$(date +%Y%m%d%H%M%S)
echo "IMAGE_TAG=${GITHUB_SHA::7}-${TIMESTAMP}" >> $GITHUB_ENV
- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract GitHub username and repository name
run: |
# Extract username and repo name from the full repository name
# This is used for correctly formatting the image reference
REPO_FULL_NAME="${{ github.repository }}"
echo "GITHUB_USERNAME=$(echo $REPO_FULL_NAME | cut -d'/' -f1)" >> $GITHUB_ENV
echo "REPO_NAME=$(echo $REPO_FULL_NAME | cut -d'/' -f2)" >> $GITHUB_ENV
# Lowercase version for Docker image URL (Docker requires lowercase)
echo "DOCKER_IMAGE_URL=$(echo $REPO_FULL_NAME | tr '[:upper:]' '[:lower:]')" >> $GITHUB_ENV
- name: Build and push Docker image
run: |
# Build and push with the unique tag
echo "Building and pushing image with tag: ${{ env.IMAGE_TAG }}"
docker build -t ghcr.io/${{ env.DOCKER_IMAGE_URL }}:${{ env.IMAGE_TAG }} .
docker push ghcr.io/${{ env.DOCKER_IMAGE_URL }}:${{ env.IMAGE_TAG }}
# Also update latest tag for reference
echo "Updating latest tag to point to the new image"
docker tag ghcr.io/${{ env.DOCKER_IMAGE_URL }}:${{ env.IMAGE_TAG }} ghcr.io/${{ env.DOCKER_IMAGE_URL }}:latest
docker push ghcr.io/${{ env.DOCKER_IMAGE_URL }}:latest
- name: Update Kubernetes manifest
run: |
# Skip this step if this is already an automated commit
# This prevents infinite loops of workflow runs
if [ "$(git log -1 --pretty=format:'%an')" = "GitHub Actions" ]; then
echo "Skipping manifest update as this is an automated commit"
exit 0
fi
echo "Updating deployment.yaml with new image tag: ${{ env.IMAGE_TAG }}"
# Update the image tag in the deployment manifest (using lowercase image URL for Docker)
sed -i "s|image: ghcr.io/.*:.*|image: ghcr.io/${{ env.DOCKER_IMAGE_URL }}:${{ env.IMAGE_TAG }}|" manifests/deployment.yaml
# Configure Git for the commit
git config --global user.name "GitHub Actions"
git config --global user.email "github-actions@github.com"
# Commit and push the changes with a skip tag to prevent loops
git add manifests/deployment.yaml
git commit -m "[ci-skip] Update deployment image to ${{ env.IMAGE_TAG }}"
echo "Pushing updated manifest to repository"
git push
Use the lowercase version in Docker commands:
Impact
This affects any repository where the owner's GitHub username contains uppercase letters, making the template incompatible with those accounts.
Description:
Problem
When using the workflow template to build and push Docker images, the build fails with the error:
Root Cause
The GitHub Actions workflow uses ${{ github.repository }} directly in Docker image tags. However, Docker registry conventions require repository names to be lowercase. When a GitHub username contains uppercase letters (e.g., "Patechoc"), this causes the build to fail.
Solution
The workflow should NOT convert the repository name to lowercase before building the Docker image, but only the full path/URL to the image artifact.
Use this as example:
Use the lowercase version in Docker commands:
Impact
This affects any repository where the owner's GitHub username contains uppercase letters, making the template incompatible with those accounts.