Skip to content
Merged
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
120 changes: 120 additions & 0 deletions .github/workflows/_test-service-pipeline.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
on:
pull_request:
branches:
- main
paths:
- ".github/workflows/_test-service-pipeline.yaml"
- ".github/workflows/service-pipeline.yaml"
- "tests/service-pipeline/**"

jobs:
test_build:
name: Test Build Stage
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v6

- name: Prepare image metadata
id: meta
run: |
SERVICE="test-service-pipeline"
SHORT_SHA="${GITHUB_SHA:0:7}"

TAGS="${SHORT_SHA}"
DOCKER_TAGS="${SERVICE}:${SHORT_SHA}"

if [ "${{ github.event_name }}" = "pull_request" ]; then
PR_TAG="pr-${{ github.event.pull_request.number }}"
TAGS="${TAGS}
${PR_TAG}"
DOCKER_TAGS="${DOCKER_TAGS},${SERVICE}:${PR_TAG}"
fi

echo "sha=${SHORT_SHA}" >> $GITHUB_OUTPUT
echo "tags<<EOF" >> $GITHUB_OUTPUT
echo "${TAGS}" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
echo "docker_tags=${DOCKER_TAGS}" >> $GITHUB_OUTPUT

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Build image
uses: docker/build-push-action@v6
with:
context: ./tests/service-pipeline
file: ./tests/service-pipeline/Dockerfile
tags: ${{ steps.meta.outputs.docker_tags }}
outputs: type=docker,dest=/tmp/test-service-pipeline.tar
cache-from: type=gha
cache-to: type=gha,mode=max

- name: Upload artifact
uses: actions/upload-artifact@v5
with:
name: test-service-pipeline-image
path: /tmp/test-service-pipeline.tar
retention-days: 1

- name: Verify artifact
run: |
docker load --input /tmp/test-service-pipeline.tar
docker run --rm test-service-pipeline:${{ steps.meta.outputs.sha }} | grep "service-pipeline test"
echo "✅ Build stage works correctly"

test_setup:
name: Test Setup Stage
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v6

- name: Load configuration
id: config
uses: DND-IT/action-config@v1
with:
config-path: tests/service-pipeline/matrix-config.yaml

- name: Validate matrix output
run: |
MATRIX='${{ steps.config.outputs.matrix }}'
echo "Matrix output: ${MATRIX}"

if [ -z "$MATRIX" ] || [ "$MATRIX" = "null" ]; then
echo "❌ Matrix output is empty"
exit 1
fi

echo "✅ Setup stage works correctly"

test_build_with_secrets:
name: Test Build with Secrets
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v6

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Build image with secrets
uses: docker/build-push-action@v6
with:
context: ./tests/service-pipeline
file: ./tests/service-pipeline/secrets.Dockerfile
tags: test-service-pipeline-secrets:latest
outputs: type=docker,dest=/tmp/test-secrets.tar
secrets: |
SECRET_TOKEN=my-secret-value
build-args: |
CUSTOM_ARG=hello-from-build-arg

- name: Verify secret was mounted
run: |
docker load --input /tmp/test-secrets.tar
OUTPUT=$(docker run --rm test-service-pipeline-secrets:latest)
echo "Output: ${OUTPUT}"
echo "${OUTPUT}" | grep "my-secret-value" || { echo "❌ Secret not mounted"; exit 1; }
echo "${OUTPUT}" | grep "hello-from-build-arg" || { echo "❌ Build arg not passed"; exit 1; }
echo "✅ Secrets and build args work correctly"
97 changes: 70 additions & 27 deletions .github/workflows/gitops-image-tag.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,13 @@ on:
type: string
required: true
image_tag_keys:
description: 'Newline-separated list of keys to update (e.g., webapp.image.tag)'
description: 'Newline-separated list of keys to update (e.g., webapp.image.tag). Ignored when image_name is set.'
type: string
default: 'webapp.image_tag'
default: ''
image_name:
description: 'Image name to search for (e.g., social-media). Finds all image blocks where the repository ends with this name and updates their tag. Takes precedence over image_tag_keys.'
type: string
default: ''
values_files:
description: 'Newline-separated list of file paths to update'
type: string
Expand Down Expand Up @@ -58,50 +62,87 @@ jobs:

- name: Update Helm values files
run: |
IMAGE_TAG="${{ inputs.image_tag }}"
IMAGE_NAME="${{ inputs.image_name }}"

# Validate inputs
if [ -z "${{ inputs.image_tag }}" ]; then
if [ -z "$IMAGE_TAG" ]; then
echo "Error: image_tag input cannot be empty"
exit 1
fi
if [ -z "${{ inputs.values_files }}" ]; then
echo "Error: values_files input cannot be empty"
exit 1
fi
if [ -z "$IMAGE_NAME" ] && [ -z "${{ inputs.image_tag_keys }}" ]; then
echo "Error: either image_name or image_tag_keys must be provided"
exit 1
fi

echo "Files to update:"
echo "${{ inputs.values_files }}"
echo ""
echo "Keys to update:"
echo "${{ inputs.image_tag_keys }}"

if [ -n "$IMAGE_NAME" ]; then
echo ""
echo "Image name to search for: $IMAGE_NAME"
else
echo ""
echo "Keys to update:"
echo "${{ inputs.image_tag_keys }}"
fi

# Process each file (newline-separated)
while IFS= read -r file; do
# Skip empty lines
[ -z "$file" ] && continue

echo ""
echo "Updating $file with image tag: ${{ inputs.image_tag }}"

# Update each key in the file
while IFS= read -r key; do
[ -z "$key" ] && continue

# Check if key exists before updating
if yq e ".$key" "$file" >/dev/null 2>&1 && [ "$(yq e ".$key" "$file")" != "null" ]; then
echo " Setting $key = ${{ inputs.image_tag }}"
# Get current value to check if update is needed
current_value=$(yq e ".$key" "$file")
if [ "$current_value" != "${{ inputs.image_tag }}" ]; then
# Use sed to replace the value while preserving formatting
sed -i "s|${key##*.}: .*|${key##*.}: ${{ inputs.image_tag }}|" "$file"
echo "Updating $file with image tag: $IMAGE_TAG"

if [ -n "$IMAGE_NAME" ]; then
# --- IMAGE NAME SEARCH MODE ---
# Find all dot-notation paths to tag fields where sibling repository ends with the image name
TAG_PATHS=$(yq '
(.. | select(has("repository") and has("tag")) | select(.repository | test("'"${IMAGE_NAME}"'$"))).tag | path | "." + join(".")
' "$file" 2>/dev/null)

if [ -z "$TAG_PATHS" ]; then
echo " No image blocks matching '$IMAGE_NAME' found in $file, skipping"
continue
fi

while IFS= read -r tag_path; do
[ -z "$tag_path" ] && continue
current_value=$(yq "$tag_path" "$file")
if [ "$current_value" = "$IMAGE_TAG" ]; then
echo " $tag_path already up to date"
continue
fi
LINE=$(yq "$tag_path | line" "$file")
sed -i "${LINE}s|tag: .*|tag: \"${IMAGE_TAG}\"|" "$file"
echo " $tag_path = $IMAGE_TAG (line $LINE)"
done <<< "$TAG_PATHS"
else
# --- EXPLICIT KEYS MODE ---
while IFS= read -r key; do
[ -z "$key" ] && continue

# Check if key exists before updating
if yq e ".$key" "$file" >/dev/null 2>&1 && [ "$(yq e ".$key" "$file")" != "null" ]; then
echo " Setting $key = $IMAGE_TAG"
current_value=$(yq e ".$key" "$file")
if [ "$current_value" != "$IMAGE_TAG" ]; then
# Use yq to find the exact line, then sed to preserve formatting
LINE=$(yq ".$key | line" "$file")
sed -i "${LINE}s|${key##*.}: .*|${key##*.}: \"${IMAGE_TAG}\"|" "$file"
else
echo " Value already up to date"
fi
else
echo " Value already up to date"
echo " Key $key not found in $file, skipping"
fi
else
echo " Key $key not found in $file, skipping"
exit 1
fi
done <<< "${{ inputs.image_tag_keys }}"
done <<< "${{ inputs.image_tag_keys }}"
fi
done <<< "${{ inputs.values_files }}"

- name: Generate PR details
Expand All @@ -127,9 +168,11 @@ jobs:
${{ inputs.image_tag }}
```

**Image**: `${{ inputs.image_name || 'N/A' }}`

**Keys to update**:
```
${{ inputs.image_tag_keys }}
${{ inputs.image_tag_keys || 'auto-detected via image_name' }}
```

**Files to update**:
Expand Down
Loading
Loading