⚠ This page is served via a proxy. Original site: https://github.com
This service does not collect credentials or authentication data.
Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
# 🚀 GitHub Action for GitOps

This GitHub Action can be used for our GitOps workflow. The GitHub Action will build and push the Docker image for your service and deploys
This GitHub Action can be used for our GitOps workflow. The GitHub Action will build and push the Docker image for your
service and deploys
the new version at your Kubernetes clusters.

## Requirement

When you want to use this GitHub Action your GitHub repository should have a `dev` and `master` / `main` branch and it should use tags for
When you want to use this GitHub Action your GitHub repository should have a `dev` and `master` / `main` branch and it
should use tags for
releases.

- For the `dev` branch we will change the files specified under `gitops-dev`.
Expand Down Expand Up @@ -119,6 +121,7 @@ jobs:
| `docker-build-secrets` | List of secrets to expose to the build (e.g., key=string, GIT_AUTH_TOKEN=mytoken) | |
| `docker-build-secret-files` | List of secret files to expose to the build (e.g., key=filename, MY_SECRET=./secret.txt) | |
| `docker-build-target` | Sets the target stage to build like: "runtime" | |
| `docker-build-platforms` | Sets the target platforms for build | linux/amd64 |
| `docker-build-provenance` | Generate [provenance](https://docs.docker.com/build/attestations/slsa-provenance/) attestation for the build | `false` |
| `docker-disable-retagging` | Disables retagging of existing images and run a new build instead | `false` |
| `gitops-organization` | GitHub Organization for GitOps | `Staffbase` |
Expand All @@ -140,7 +143,8 @@ jobs:

## Contributing

Please read [CONTRIBUTING.md](CONTRIBUTING.md) for details on our code of conduct, and the process for submitting pull requests to us.
Please read [CONTRIBUTING.md](CONTRIBUTING.md) for details on our code of conduct, and the process for submitting pull
requests to us.

## License

Expand All @@ -161,4 +165,5 @@ This project is licensed under the Apache-2.0 License - see the [LICENSE.md](LIC

## Releasing new versions

Go to the release overview page and publish the draft release with a new version number. Make sure to update the floating version commit.
Go to the release overview page and publish the draft release with a new version number. Make sure to update the
floating version commit.
58 changes: 51 additions & 7 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ inputs:
docker-build-target:
description: "Sets the target stage to build"
required: false
docker-build-platforms:
description: "Sets the target platforms for build"
required: false
default: 'linux/amd64'
docker-build-provenance:
description: "Generate provenance attestation for the build"
required: false
Expand Down Expand Up @@ -151,6 +155,34 @@ runs:
echo "tag=$TAG" >> $GITHUB_OUTPUT
echo "tag_list=$TAG_LIST" >> $GITHUB_OUTPUT

- name: Verify Architecture Match
shell: bash
if: steps.preparation.outputs.build == 'true'
run: |
RUNNER_ARCH="${{ runner.arch }}" # X64 (AMD64) or ARM64
TARGET_PLATFORMS="${{ inputs.docker-build-platforms }}"

echo "Runner CPU Architecture: $RUNNER_ARCH"
echo "Requested Build Platforms: $TARGET_PLATFORMS"

# Check for AMD64 mismatch (Runner is X64, but user requests ONLY arm64, OR user requests multi-arch which requires emulation)
if [[ "$RUNNER_ARCH" == "X64" ]]; then
if [[ "$TARGET_PLATFORMS" == *"linux/arm64"* ]]; then
echo "::error::Runner is X64 (Intel/AMD) but build includes 'linux/arm64'. This requires emulation. Aborting strictly."
exit 1
fi
fi

# Check for ARM64 mismatch
if [[ "$RUNNER_ARCH" == "ARM64" ]]; then
if [[ "$TARGET_PLATFORMS" == *"linux/amd64"* ]]; then
echo "::error::Runner is ARM64 (Apple Silicon/Graviton) but build includes 'linux/amd64'. This requires emulation. Aborting strictly."
exit 1
fi
fi

echo "Architecture match verified for native build ✅"

- name: Set up Docker Buildx
if: inputs.docker-username != '' && inputs.docker-password != ''
uses: docker/setup-buildx-action@v3
Expand All @@ -177,7 +209,7 @@ runs:
tags: ${{ steps.preparation.outputs.tag_list }}
secrets: ${{ inputs.docker-build-secrets }}
secret-files: ${{ inputs.docker-build-secret-files }}
platforms: linux/amd64
platforms: ${{ inputs.docker-build-platforms }}
cache-from: type=gha
cache-to: type=gha,mode=max
provenance: ${{ inputs.docker-build-provenance }}
Expand All @@ -189,27 +221,38 @@ runs:
shell: bash
run: |
CHECK_EXISTING_TAGS="master-${GITHUB_SHA::8} main-${GITHUB_SHA::8}"
CONTENT_TYPE="application/vnd.docker.distribution.manifest.v2+json"
# Accept both single-arch manifests and multi-arch manifest lists/indexes
ACCEPT_HEADER="application/vnd.docker.distribution.manifest.v2+json, application/vnd.docker.distribution.manifest.list.v2+json, application/vnd.oci.image.manifest.v1+json, application/vnd.oci.image.index.v1+json"

echo "CHECK_EXISTING_TAGS: ${CHECK_EXISTING_TAGS}"
echo "RELEASE_TAG: ${RELEASE_TAG:1}"
echo "Check if an image already exists for ${{ inputs.docker-image }}:main|master-${GITHUB_SHA::8} 🐋 ⬇"

foundImage=false
DETECTED_CONTENT_TYPE=""
DIGEST=""

end=$((SECONDS+300))
while [ $SECONDS -lt $end ]; do

MANIFEST=""
for tag in $CHECK_EXISTING_TAGS; do
MANIFEST=$(curl -H "Accept: ${CONTENT_TYPE}" -u '${{ inputs.docker-username }}:${{ inputs.docker-password }}' "${{ inputs.docker-registry-api }}${{ inputs.docker-image}}/manifests/${tag}")
# Dump headers to file to extract Content-Type and Digest later
MANIFEST=$(curl -s -D headers.txt -H "Accept: ${ACCEPT_HEADER}" -u '${{ inputs.docker-username }}:${{ inputs.docker-password }}' "${{ inputs.docker-registry-api }}${{ inputs.docker-image}}/manifests/${tag}")

if [[ $MANIFEST == *"errors"* ]]; then
echo "No image found for ${{ inputs.docker-image }}:${tag} 🚫"
continue
else
echo "Image found for ${{ inputs.docker-image }}:${tag} 🐋 ⬇"
foundImage=true

# Extract the Content-Type returned by registry
DETECTED_CONTENT_TYPE=$(grep -i "^Content-Type:" headers.txt | cut -d' ' -f2 | tr -d '\r')

# Extract the correct digest from headers (works for lists and single images)
DIGEST=$(grep -i "^Docker-Content-Digest:" headers.txt | cut -d' ' -f2 | tr -d '\r')

break 2
fi
done
Expand All @@ -223,11 +266,12 @@ runs:
fi

echo "Retagging image with release version and :latest tags for ${{ inputs.docker-image }} 🏷"
curl --fail-with-body -X PUT -H "Content-Type: ${CONTENT_TYPE}" -u '${{ inputs.docker-username }}:${{ inputs.docker-password }}' -d "${MANIFEST}" "${{ inputs.docker-registry-api }}${{ inputs.docker-image}}/manifests/${{ steps.preparation.outputs.tag }}"
curl --fail-with-body -X PUT -H "Content-Type: ${CONTENT_TYPE}" -u '${{ inputs.docker-username }}:${{ inputs.docker-password }}' -d "${MANIFEST}" "${{ inputs.docker-registry-api }}${{ inputs.docker-image}}/manifests/${{ steps.preparation.outputs.latest }}"
echo "Using Content-Type: ${DETECTED_CONTENT_TYPE}"

# Use the detected Content-Type to PUT the manifest back
curl --fail-with-body -X PUT -H "Content-Type: ${DETECTED_CONTENT_TYPE}" -u '${{ inputs.docker-username }}:${{ inputs.docker-password }}' -d "${MANIFEST}" "${{ inputs.docker-registry-api }}${{ inputs.docker-image}}/manifests/${{ steps.preparation.outputs.tag }}"
curl --fail-with-body -X PUT -H "Content-Type: ${DETECTED_CONTENT_TYPE}" -u '${{ inputs.docker-username }}:${{ inputs.docker-password }}' -d "${MANIFEST}" "${{ inputs.docker-registry-api }}${{ inputs.docker-image}}/manifests/${{ steps.preparation.outputs.latest }}"

# Get the digest of the image
DIGEST=$(echo $MANIFEST | jq .config.digest | tr -d '"')
echo "digest=$DIGEST" >> $GITHUB_OUTPUT

- name: Checkout GitOps Repository
Expand Down