Files
jovies/.gitea/workflows/build.yml
Mayne0213 52712a4d32 PERF(app): optimize kubectl installation
- Check if kubectl already exists first
- Use specific version instead of querying stable.txt
- Show download progress
- Skip installation if already present

This should significantly reduce setup time if kubectl
is already included in the runner image
2025-12-28 18:04:14 +09:00

290 lines
10 KiB
YAML
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

name: Build Docker Image
on:
push:
branches: [main, develop]
tags:
- 'v*'
workflow_dispatch:
env:
REGISTRY: gitea0213.kro.kr
IMAGE_NAME: ${{ github.repository }}
jobs:
build-and-push:
runs-on: ubuntu-24.04-arm
permissions:
contents: write
packages: write
outputs:
image-tag: ${{ steps.meta.outputs.tags }}
image-digest: ${{ steps.build.outputs.digest }}
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup kubectl
run: |
if command -v kubectl &> /dev/null; then
echo "✅ kubectl already installed"
kubectl version --client
else
echo "📥 Installing kubectl..."
# Use specific version to avoid querying stable.txt
KUBECTL_VERSION="v1.31.0"
curl -LO "https://dl.k8s.io/release/${KUBECTL_VERSION}/bin/linux/arm64/kubectl" &
DOWNLOAD_PID=$!
# Show progress
while kill -0 $DOWNLOAD_PID 2>/dev/null; do
echo -n "."
sleep 1
done
wait $DOWNLOAD_PID
echo ""
chmod +x kubectl
sudo mv kubectl /usr/local/bin/
kubectl version --client
fi
- name: Setup kubeconfig from Secret
env:
KUBECONFIG_B64: ${{ secrets.KUBECONFIG }}
run: |
if [ -z "$KUBECONFIG_B64" ]; then
echo "❌ KUBECONFIG secret not set"
echo "Please add KUBECONFIG to Gitea repository secrets"
exit 1
fi
echo "📝 KUBECONFIG secret found (length: ${#KUBECONFIG_B64})"
mkdir -p $HOME/.kube
# Clean up the base64 string (remove all whitespace and newlines)
CLEAN_B64=$(echo "$KUBECONFIG_B64" | tr -d '[:space:]')
echo "After cleanup: ${#CLEAN_B64} chars"
# Try decoding
if echo "$CLEAN_B64" | base64 -d > $HOME/.kube/config 2>/dev/null; then
echo "✅ Successfully decoded kubeconfig"
elif echo "$CLEAN_B64" | base64 --decode > $HOME/.kube/config 2>/dev/null; then
echo "✅ Successfully decoded kubeconfig (with --decode)"
else
echo "❌ Both base64 decode methods failed"
echo "Trying to save as-is (maybe already decoded)..."
echo "$KUBECONFIG_B64" > $HOME/.kube/config
fi
chmod 600 $HOME/.kube/config
# Verify it's valid YAML
if head -1 $HOME/.kube/config | grep -q "apiVersion"; then
echo "✅ Kubeconfig appears valid"
else
echo "⚠️ Kubeconfig may not be valid, first line:"
head -1 $HOME/.kube/config
fi
# Test connection
kubectl cluster-info
kubectl get nodes -o wide
- name: Lowercase repository name
id: lowercase
run: |
echo "repo=$(echo ${{ github.repository }} | tr '[:upper:]' '[:lower:]')" >> $GITHUB_OUTPUT
- name: Extract metadata (tags, labels)
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ steps.lowercase.outputs.repo }}
tags: |
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=sha,prefix={{branch}}-sha-,format=long
type=raw,value=latest,enable={{is_default_branch}}
- name: Create registry credentials in Kubernetes
run: |
# Ensure namespace exists
kubectl get namespace kaniko-builds 2>/dev/null || kubectl create namespace kaniko-builds
# Create/update registry secret
kubectl create secret docker-registry kaniko-registry-creds \
--docker-server=${{ env.REGISTRY }} \
--docker-username=bluemayne \
--docker-password=${{ secrets.GITEAREGISTRY }} \
--namespace=kaniko-builds \
--dry-run=client -o yaml | kubectl apply -f -
- name: Build and push with Kaniko Job
id: build
run: |
TAGS="${{ steps.meta.outputs.tags }}"
# Prepare destination arguments
DESTINATIONS=""
while IFS= read -r tag; do
DESTINATIONS="$DESTINATIONS\n - --destination=$tag"
done <<< "$TAGS"
# Create unique build name
BUILD_NAME="kaniko-build-${{ github.run_number }}-$(date +%s)"
echo "📦 Building image: ${BUILD_NAME}"
echo "Tags: $TAGS"
# Generate Kaniko Job from template
sed -e "s|KANIKO_BUILD_NAME|${BUILD_NAME}|g" \
-e "s|GIT_REPO_URL|https://gitea0213.kro.kr/${{ github.repository }}.git|g" \
-e "s|GIT_SHA|${{ github.sha }}|g" \
-e "s|CACHE_REPO|${{ env.REGISTRY }}/${{ steps.lowercase.outputs.repo }}/cache|g" \
-e "s|# DESTINATIONS will be added here|${DESTINATIONS}|g" \
deploy/kaniko/job.yaml > /tmp/kaniko-job.yaml
# Apply Job
kubectl apply -f /tmp/kaniko-job.yaml
# Wait for completion
echo "⏳ Waiting for Kaniko Job to complete..."
kubectl wait --for=condition=complete --timeout=600s job/${BUILD_NAME} -n kaniko-builds || {
echo "❌ Job failed or timed out"
POD=$(kubectl get pods -n kaniko-builds -l job-name=${BUILD_NAME} -o jsonpath='{.items[0].metadata.name}')
echo "📋 Logs:"
kubectl logs -n kaniko-builds ${POD} --all-containers=true || true
kubectl delete job ${BUILD_NAME} -n kaniko-builds || true
exit 1
}
echo "✅ Image built successfully"
# Get digest
POD=$(kubectl get pods -n kaniko-builds -l job-name=${BUILD_NAME} -o jsonpath='{.items[0].metadata.name}')
DIGEST=$(kubectl logs -n kaniko-builds ${POD} -c kaniko 2>/dev/null | grep -oP 'digest: \K[a-zA-Z0-9:]+' | tail -1 || echo "unknown")
echo "digest=${DIGEST}" >> $GITHUB_OUTPUT
# Cleanup
kubectl delete job ${BUILD_NAME} -n kaniko-builds || true
- name: Extract SHA tag
id: extract-tag
run: |
# Extract the SHA-based tag from the tags list
TAGS="${{ steps.meta.outputs.tags }}"
echo "All tags:"
echo "$TAGS"
echo "---"
# Get commit SHA (full 40 characters)
COMMIT_SHA="${{ github.sha }}"
# Get current branch name
BRANCH_NAME="${{ github.ref_name }}"
echo "Branch: $BRANCH_NAME"
# Method 1: Extract the full SHA tag from docker/metadata-action output
# docker/metadata-action creates: <branch>-sha-<full-40-char-sha>
SHA_TAG=$(echo "$TAGS" | grep -oE "${BRANCH_NAME}-sha-[a-f0-9]{40}" | head -n 1)
# Method 2: If not found, try to extract any branch-sha- tag (fallback)
if [ -z "$SHA_TAG" ]; then
SHA_TAG=$(echo "$TAGS" | grep -oE "${BRANCH_NAME}-sha-[a-f0-9]+" | head -n 1)
if [ -n "$SHA_TAG" ]; then
echo "⚠️ Found SHA tag (may not be full 40 chars): $SHA_TAG"
fi
fi
# Method 3: Fallback to commit SHA directly (construct the tag)
if [ -z "$SHA_TAG" ]; then
SHA_TAG="${BRANCH_NAME}-sha-$COMMIT_SHA"
echo "⚠️ Could not extract from tags, using commit SHA: $SHA_TAG"
fi
if [ -z "$SHA_TAG" ]; then
echo "❌ ERROR: Failed to extract SHA tag"
exit 1
fi
echo "sha-tag=$SHA_TAG" >> $GITHUB_OUTPUT
echo "✅ Extracted SHA tag: $SHA_TAG"
- name: Update kustomization with new image tag
env:
GITEA_TOKEN: ${{ secrets.GITEAREGISTRYTOKEN }}
run: |
git config --global user.name "gitea-actions[bot]"
git config --global user.email "gitea-actions[bot]@users.noreply.gitea.com"
# Validate that SHA_TAG is not empty
SHA_TAG="${{ steps.extract-tag.outputs.sha-tag }}"
if [ -z "$SHA_TAG" ]; then
echo "❌ ERROR: SHA_TAG is empty, cannot update kustomization"
exit 1
fi
# Determine overlay based on branch
BRANCH_NAME="${{ github.ref_name }}"
if [ "$BRANCH_NAME" = "main" ]; then
OVERLAY="prod"
elif [ "$BRANCH_NAME" = "develop" ]; then
OVERLAY="dev"
else
echo "⚠️ Unknown branch: $BRANCH_NAME, skipping kustomization update"
exit 0
fi
KUSTOMIZATION_FILE="deploy/k8s/overlays/$OVERLAY/kustomization.yaml"
# Check if kustomization file has images section
if grep -q "images:" "$KUSTOMIZATION_FILE"; then
echo "📝 Updating $KUSTOMIZATION_FILE with tag: $SHA_TAG"
# Update kustomization.yaml with new image tag
# Handle both cases: newTag: (with value) and newTag: (empty)
sed -i.bak "s|newTag:.*|newTag: $SHA_TAG|" "$KUSTOMIZATION_FILE"
# Verify the update was successful
if grep -q "newTag: $SHA_TAG" "$KUSTOMIZATION_FILE"; then
echo "✅ Successfully updated kustomization.yaml"
rm -f "$KUSTOMIZATION_FILE.bak"
else
echo "❌ ERROR: Failed to update kustomization.yaml"
cat "$KUSTOMIZATION_FILE"
exit 1
fi
# Commit and push if there are changes
if git diff --quiet; then
echo "No changes to commit"
else
git add "$KUSTOMIZATION_FILE"
git commit -m "Update $OVERLAY image to $SHA_TAG"
git push
echo "✅ Kustomization updated with new image tag: $SHA_TAG"
fi
else
echo " $OVERLAY overlay uses base image (latest tag), skipping kustomization update"
echo " Image built with tag: $SHA_TAG"
fi
- name: Display image information
run: |
echo "✅ Image built and pushed successfully!"
echo "📦 Image tags:"
echo "${{ steps.meta.outputs.tags }}"
echo "🔖 SHA tag: ${{ steps.extract-tag.outputs.sha-tag }}"
echo "🔖 Digest: ${{ steps.build.outputs.digest }}"
echo ""
echo "🚀 Kustomization updated with new image tag"
echo " ArgoCD will automatically detect and deploy this new image"
echo " Monitor deployment at your ArgoCD dashboard"