Patrick de Ruiter ee7f6bc7d8
All checks were successful
CI Pipeline / lint (push) Successful in 19s
CI Pipeline / build (push) Successful in 41s
CI Pipeline / test (push) Successful in 1m3s
CI Pipeline / security-scan (push) Successful in 1m15s
CI Pipeline / autotag (push) Successful in 17s
CI Pipeline / push (push) Has been skipped
CI Pipeline / update-cd (push) Has been skipped
fix: Handle missing initial tag in autotag step
2025-12-26 01:52:00 +01:00

277 lines
8.7 KiB
YAML

name: CI Pipeline
on:
push:
branches:
- main
tags:
- 'v*'
pull_request:
branches:
- main
env:
REGISTRY: ${{ vars.REGISTRY_URL }}
IMAGE_NAME: enterprise-openldap
jobs:
# Stage 1: Lint Dockerfile
lint:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Lint Dockerfile with hadolint
run: |
docker run --rm -i hadolint/hadolint < Dockerfile || {
echo "::warning::Dockerfile linting found issues (non-blocking)"
}
# Stage 2: Build image
build:
runs-on: ubuntu-latest
needs: lint
outputs:
image_tag: ${{ steps.version.outputs.VERSION }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Determine version tag
id: version
run: |
if [[ "$GITHUB_REF" == refs/tags/v* ]]; then
VERSION="${GITHUB_REF#refs/tags/v}"
else
VERSION="$(echo "$GITHUB_SHA" | cut -c1-7)"
fi
echo "VERSION=$VERSION" >> $GITHUB_OUTPUT
echo "Building version: $VERSION"
- name: Build Docker image
run: |
docker build -t ${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }} .
docker tag ${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }} ${{ env.IMAGE_NAME }}:test
- name: Save image for subsequent jobs
run: |
mkdir -p /tmp/images
docker save ${{ env.IMAGE_NAME }}:test -o /tmp/images/image.tar
- name: Upload image artifact
uses: actions/upload-artifact@v3
with:
name: docker-image
path: /tmp/images/image.tar
retention-days: 1
# Stage 3: Integration tests
test:
runs-on: ubuntu-latest
needs: build
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Download image artifact
uses: actions/download-artifact@v3
with:
name: docker-image
path: /tmp/images
- name: Load Docker image
run: |
docker load -i /tmp/images/image.tar
- name: Run integration tests
run: |
chmod +x tests/test-container.sh
./tests/test-container.sh
env:
IMAGE_NAME: ${{ env.IMAGE_NAME }}:test
CONTAINER_NAME: openldap-ci-test
# Stage 4: Security scan
security-scan:
runs-on: ubuntu-latest
needs: build
steps:
- name: Download image artifact
uses: actions/download-artifact@v3
with:
name: docker-image
path: /tmp/images
- name: Load Docker image
run: |
docker load -i /tmp/images/image.tar
- name: Scan image with Trivy
run: |
docker run --rm \
-v /var/run/docker.sock:/var/run/docker.sock \
aquasec/trivy:latest image \
--severity HIGH,CRITICAL \
--exit-code 0 \
--no-progress \
${{ env.IMAGE_NAME }}:test
- name: Scan for critical vulnerabilities (blocking)
run: |
docker run --rm \
-v /var/run/docker.sock:/var/run/docker.sock \
aquasec/trivy:latest image \
--severity CRITICAL \
--exit-code 1 \
--no-progress \
--ignore-unfixed \
${{ env.IMAGE_NAME }}:test || {
echo "::error::Critical vulnerabilities found!"
exit 1
}
# Stage 5: Auto-tag (only on main branch, not on tags or PRs)
autotag:
runs-on: ubuntu-latest
needs: [test, security-scan]
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
outputs:
new_tag: ${{ steps.autotag.outputs.new_tag }}
version: ${{ steps.autotag.outputs.version }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0 # Need full history for autotag
- name: Configure git
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
- name: Run autotag
id: autotag
run: |
# Check if any tags exist
CURRENT_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "")
if [ -z "$CURRENT_TAG" ]; then
echo "No existing tags found, starting at v0.1.0"
NEW_TAG="v0.1.0"
else
echo "Current tag: $CURRENT_TAG"
# Download autotag
AUTOTAG_VERSION="1.3.9"
curl -sL "https://github.com/autotag-dev/autotag/releases/download/v${AUTOTAG_VERSION}/autotag_linux_amd64" -o /tmp/autotag
chmod +x /tmp/autotag
# Calculate next version based on commits
# autotag looks for #major, #minor in commit messages, defaults to patch
NEW_TAG=$(/tmp/autotag -n -b main 2>&1 || echo "")
# Check if autotag returned an error or empty result
if [ -z "$NEW_TAG" ] || echo "$NEW_TAG" | grep -qi "error"; then
echo "Autotag failed or returned error, using fallback"
# Fallback: increment patch version
CURRENT_VERSION="${CURRENT_TAG#v}"
MAJOR=$(echo $CURRENT_VERSION | cut -d. -f1)
MINOR=$(echo $CURRENT_VERSION | cut -d. -f2)
PATCH=$(echo $CURRENT_VERSION | cut -d. -f3)
NEW_PATCH=$((PATCH + 1))
NEW_TAG="v${MAJOR}.${MINOR}.${NEW_PATCH}"
fi
fi
echo "New tag will be: $NEW_TAG"
echo "new_tag=$NEW_TAG" >> $GITHUB_OUTPUT
echo "version=${NEW_TAG#v}" >> $GITHUB_OUTPUT
- name: Create and push tag
run: |
NEW_TAG="${{ steps.autotag.outputs.new_tag }}"
# Check if tag already exists
if git rev-parse "$NEW_TAG" >/dev/null 2>&1; then
echo "Tag $NEW_TAG already exists, skipping"
exit 0
fi
echo "Creating tag: $NEW_TAG"
git tag -a "$NEW_TAG" -m "Release $NEW_TAG (auto-generated)"
git push origin "$NEW_TAG"
echo "Successfully pushed tag: $NEW_TAG"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Stage 6: Push to registry (only on tags)
push:
runs-on: ubuntu-latest
needs: [test, security-scan]
if: startsWith(github.ref, 'refs/tags/v')
outputs:
version: ${{ steps.version.outputs.VERSION }}
full_image: ${{ steps.version.outputs.FULL_IMAGE }}
steps:
- name: Download image artifact
uses: actions/download-artifact@v3
with:
name: docker-image
path: /tmp/images
- name: Load Docker image
run: |
docker load -i /tmp/images/image.tar
- name: Determine version and tags
id: version
run: |
VERSION="${GITHUB_REF#refs/tags/v}"
# For releases, tag with version, major.minor, and latest
MAJOR=$(echo $VERSION | cut -d. -f1)
MINOR=$(echo $VERSION | cut -d. -f2)
TAGS="${VERSION},${MAJOR}.${MINOR},latest"
echo "VERSION=$VERSION" >> $GITHUB_OUTPUT
echo "TAGS=$TAGS" >> $GITHUB_OUTPUT
echo "FULL_IMAGE=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${VERSION}" >> $GITHUB_OUTPUT
- name: Log in to Docker Registry
run: |
echo "${{ secrets.REGISTRY_PASSWORD }}" | docker login ${{ env.REGISTRY }} -u "${{ secrets.REGISTRY_USERNAME }}" --password-stdin
- name: Tag and push images
run: |
IFS=',' read -ra TAGS <<< "${{ steps.version.outputs.TAGS }}"
for TAG in "${TAGS[@]}"; do
docker tag ${{ env.IMAGE_NAME }}:test ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:$TAG
docker push ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:$TAG
echo "Pushed: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:$TAG"
done
- name: Logout from registry
if: always()
run: docker logout ${{ env.REGISTRY }} || true
# Stage 7: Update CD pipeline (trigger deployment)
update-cd:
runs-on: ubuntu-latest
needs: push
if: startsWith(github.ref, 'refs/tags/v')
steps:
- name: Trigger CD pipeline
run: |
echo "=============================================="
echo " Ready to update CD pipeline"
echo "=============================================="
echo "New version: ${{ needs.push.outputs.version }}"
echo "Full image: ${{ needs.push.outputs.full_image }}"
echo ""
echo "TODO: Add step to update version in CD repository"
echo "This could be:"
echo " - Update docker-compose.yml in infra repo"
echo " - Update Helm values"
echo " - Trigger ArgoCD sync"
echo "=============================================="