# CIcd Gitops

> 🚀 **Automated Deployment**: Panduan komprehensif untuk CI/CD pipelines dan GitOps workflows di Kubernetes.

***

## 📋 **Daftar Isi**

### **🔄 CI/CD Concepts**

* [Continuous Integration Overview](#continuous-integration-overview)
* [Continuous Deployment Strategies](#continuous-deployment-strategies)
* [GitOps Principles](#gitops-principles)
* [Pipeline as Code](#pipeline-as-code)

### **🚀 CI/CD Platforms**

* [GitHub Actions](#github-actions)
* [GitLab CI/CD](#gitlab-cicd)
* [Jenkins X](#jenkins-x)
* [Tekton Pipelines](#tekton-pipelines)
* [Azure DevOps](#azure-devops)

### **🔧 GitOps Tools**

* [ArgoCD](#argocd)
* [Flux CD](#flux-cd)
* [Rancher Fleet](#rancher-fleet)
* [Kustomize Integration](#kustomize-integration)

### **📦 Container Registries**

* [Docker Hub](#docker-hub)
* [Amazon ECR](#amazon-ecr)
* [Google GCR](#google-gcr)
* [Azure ACR](#azure-acr)
* [Harbor Registry](#harbor-registry)

### **🔍 Pipeline Best Practices**

* [Image Security Scanning](#image-security-scanning)
* [Multi-Environment Deployment](#multi-environment-deployment)
* [Rollback Strategies](#rollback-strategies)
* [Monitoring & Alerting](#monitoring--alerting)

***

## 🔄 **CI/CD Concepts**

### Continuous Integration Overview

**📖 Konsep Dasar** Continuous Integration (CI) adalah praktik mengintegrasikan perubahan kode secara berkala ke dalam shared repository, diikuti dengan automated build dan test.

**🎯 CI Workflow Components**

```yaml
# Typical CI Pipeline Steps
1. Code Commit
2. Trigger Pipeline
3. Build Application
4. Run Tests
5. Security Scan
6. Build Docker Image
7. Push to Registry
8. Deploy to Environment
```

**⚙️ CI Pipeline Template**

```yaml
# Generic CI Pipeline Structure
stages:
  - validate
  - test
  - build
  - security
  - deploy

variables:
  DOCKER_REGISTRY: "your-registry.com"
  APP_NAME: "my-app"
  DOCKERFILE: "Dockerfile"
```

### Continuous Deployment Strategies

**🎯 Deployment Strategies**

1. **Blue-Green Deployment**

```yaml
# Blue-Green Strategy
stages:
  - deploy:blue
  - health_check:blue
  - switch_traffic
  - deploy:green
  - cleanup:blue
```

2. **Canary Deployment**

```yaml
# Canary Strategy
stages:
  - deploy:canary
  - monitor:canary
  - gradual_rollout
  - full_deployment
```

3. **Rolling Update**

```yaml
# Rolling Update Strategy
stages:
  - deploy:rolling
  - health_check
  - monitor_rollout
```

### GitOps Principles

**🔄 GitOps Core Principles**

1. **Declarative Configuration**
   * Semua configuration disimpan dalam Git
   * State definition secara eksplisit
2. **Versioned & Immutable**
   * Semua perubahan tercatat di Git
   * Immutable history
3. **Pulled Automatically**
   * Agent pull changes dari Git
   * Automated synchronization
4. **Continuously Reconciled**
   * Continuous monitoring dan repair
   * Self-healing capabilities

**📋 GitOps Workflow**

```yaml
# GitOps Workflow
Developer Push → Git Repository → Automated Pipeline →
Build & Test → Image Registry → GitOps Tool → Kubernetes Cluster
```

### Pipeline as Code

**📝 Pipeline Configuration**

```yaml
# .gitlab-ci.yml
stages:
  - build
  - test
  - deploy

variables:
  DOCKER_DRIVER: overlay2
  DOCKER_TLS_CERTDIR: "/certs"

services:
  - docker:dind

build:
  stage: build
  script:
    - docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
    - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
```

***

## 🚀 **CI/CD Platforms**

### GitHub Actions

**🔧 Workflow Configuration**

```yaml
# .github/workflows/deploy.yml
name: Deploy to Kubernetes

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

env:
  REGISTRY: ghcr.io
  IMAGE_NAME: ${{ github.repository }}

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3

    - name: Set up Node.js
      uses: actions/setup-node@v3
      with:
        node-version: '18'
        cache: 'npm'

    - name: Install dependencies
      run: npm ci

    - name: Run tests
      run: npm test

    - name: Run linting
      run: npm run lint

  build:
    needs: test
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write

    steps:
    - uses: actions/checkout@v3

    - name: Log in to Container Registry
      uses: docker/login-action@v2
      with:
        registry: ${{ env.REGISTRY }}
        username: ${{ github.actor }}
        password: ${{ secrets.GITHUB_TOKEN }}

    - name: Extract metadata
      id: meta
      uses: docker/metadata-action@v4
      with:
        images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
        tags: |
          type=ref,event=branch
          type=ref,event=pr
          type=sha

    - name: Build and push Docker image
      uses: docker/build-push-action@v4
      with:
        context: .
        push: true
        tags: ${{ steps.meta.outputs.tags }}
        labels: ${{ steps.meta.outputs.labels }}

  deploy:
    needs: build
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'

    steps:
    - uses: actions/checkout@v3

    - name: Configure kubectl
      uses: azure/k8s-set-context@v1
      with:
        method: kubeconfig
        kubeconfig: ${{ secrets.KUBE_CONFIG }}

    - name: Deploy to Kubernetes
      run: |
        sed -i "s|IMAGE_TAG|${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}|g" k8s/deployment.yaml
        kubectl apply -f k8s/
        kubectl rollout status deployment/my-app
```

**🔧 Advanced GitHub Actions**

```yaml
# Multi-environment deployment
name: Multi-Environment Deploy

on:
  push:
    branches: [ main, develop ]

environments:
  production:
    url: https://app.example.com
  staging:
    url: https://staging.example.com

jobs:
  deploy:
    runs-on: ubuntu-latest
    environment: ${{ github.ref == 'refs/heads/main' && 'production' || 'staging' }}

    steps:
    - name: Deploy
      run: |
        if [ "${{ github.ref }}" = "refs/heads/main" ]; then
          echo "Deploying to production"
          kubectl apply -f k8s/production/
        else
          echo "Deploying to staging"
          kubectl apply -f k8s/staging/
        fi
```

### GitLab CI/CD

**🔧 GitLab CI Configuration**

```yaml
# .gitlab-ci.yml
stages:
  - build
  - test
  - security
  - deploy-staging
  - deploy-production

variables:
  DOCKER_DRIVER: overlay2
  DOCKER_TLS_CERTDIR: "/certs"
  KUBERNETES_NAMESPACE: production

cache:
  paths:
    - node_modules/

# Build stage
build:
  stage: build
  image: docker:20.10.16
  services:
    - docker:20.10.16-dind
  before_script:
    - echo $CI_REGISTRY_PASSWORD | docker login -u $CI_REGISTRY_USER --password-stdin $CI_REGISTRY
  script:
    - docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
    - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
  only:
    - main
    - develop

# Test stage
test:
  stage: test
  image: node:18-alpine
  script:
    - npm ci
    - npm run test
    - npm run test:coverage
  coverage: '/Coverage: \d+\.\d+%/'
  artifacts:
    reports:
      coverage_report:
        coverage_format: cobertura
        path: coverage/cobertura-coverage.xml
  only:
    - main
    - develop

# Security scanning
security:
  stage: security
  image: aquasec/trivy:latest
  script:
    - trivy image --exit-code 0 --severity HIGH,CRITICAL $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
  only:
    - main
    - develop

# Deploy to staging
deploy_staging:
  stage: deploy-staging
  image: bitnami/kubectl:latest
  environment:
    name: staging
    url: https://staging.example.com
  script:
    - kubectl config use-context $KUBE_CONTEXT_STAGING
    - sed -i "s|IMAGE_TAG|$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA|g" k8s/deployment.yaml
    - kubectl apply -f k8s/
    - kubectl rollout status deployment/my-app -n staging
  only:
    - develop

# Deploy to production
deploy_production:
  stage: deploy-production
  image: bitnami/kubectl:latest
  environment:
    name: production
    url: https://app.example.com
  script:
    - kubectl config use-context $KUBE_CONTEXT_PRODUCTION
    - sed -i "s|IMAGE_TAG|$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA|g" k8s/deployment.yaml
    - kubectl apply -f k8s/
    - kubectl rollout status deployment/my-app -n production
  when: manual
  only:
    - main
```

### Jenkins X

**🚀 Jenkins X Setup**

```bash
# Create Jenkins X cluster
jx create cluster eks --cluster-name=jx-cluster --region=us-west-2

# Import existing project
jx import --dir=my-app --batch-mode

# Create new project
jx create spring --name=web-app --package-name=com.example.webapp
```

**🔧 Jenkins X Pipeline**

```groovy
// Jenkinsfile
pipeline {
  agent any
  stages {
    stage('Build') {
      steps {
        sh 'mvn clean install'
      }
    }

    stage('Test') {
      steps {
        sh 'mvn test'
        junit 'target/surefire-reports/*.xml'
      }
    }

    stage('Build Image') {
      steps {
        sh 'jx step build -t $DOCKER_REGISTRY/$ORG/$APP_NAME:$BUILD_NUMBER'
      }
    }

    stage('Deploy to Staging') {
      steps {
        sh 'jx step helm install'
      }
    }

    stage('Promote to Production') {
      when {
        branch 'main'
      }
      steps {
        sh 'jx promote --app $APP_NAME --version $BUILD_NUMBER --env production'
      }
    }
  }
}
```

### Tekton Pipelines

**🚀 Tekton Installation**

```bash
# Install Tekton
kubectl apply -f https://storage.googleapis.com/tekton-releases/latest/release.yaml

# Install Tekton CLI
curl -L https://github.com/tektoncd/cli/releases/download/v0.28.0/tkn_0.28.0_Linux_x86_64.tar.gz -o tkn.tar.gz
tar -xvf tkn.tar.gz
sudo mv tkn /usr/local/bin/
```

**🔧 Tekton Pipeline**

```yaml
# pipeline.yaml
apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
  name: build-and-deploy
spec:
  workspaces:
  - name: shared-workspace
  - name: dockerconfig
    description: Includes a docker config.json
  params:
  - name: git-url
    type: string
    description: git url to clone
  - name: git-revision
    type: string
    description: git revision to checkout (branch, tag, sha)
    default: main
  - name: image-to-build
    type: string
    description: name of the image to build
  - name: image-to-deploy
    type: string
    description: name of the image to deploy

  tasks:
  - name: fetch-repo
    taskRef:
      name: git-clone
    workspaces:
    - name: output
      workspace: shared-workspace
    params:
    - name: url
      value: $(params.git-url)
    - name: revision
      value: $(params.git-revision)

  - name: build-image
    taskRef:
      name: buildah
    runAfter: ["fetch-repo"]
    workspaces:
    - name: source
      workspace: shared-workspace
    params:
    - name: IMAGE
      value: $(params.image-to-build)

  - name: deploy
    taskRef:
      name: kubectl-deploy
    runAfter: ["build-image"]
    workspaces:
    - name: source
      workspace: shared-workspace
    params:
    - name: script
      value: |
        kubectl apply -f k8s/
        kubectl rollout status deployment/my-app
```

**🔧 Tekton Task**

```yaml
# task.yaml
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
  name: git-clone
spec:
  workspaces:
  - name: output
    description: The git repo will be cloned onto the volume backing this workspace
  params:
  - name: url
    description: Repository URL to clone from
    type: string
  - name: revision
    description: Revision to checkout (branch, tag, sha)
    type: string
    default: main
  steps:
  - name: clone
    image: gcr.io/tekton-releases/github.com/tektoncd/pipeline/cmd/git-init:v0.28.3
    script: |
      #!/bin/sh
      CHECKOUT_DIR="$(workspaces.output.path)"
      mkdir -p ${CHECKOUT_DIR}
      /ko-app/git-init \
        -url "$(params.url)" \
        -revision "$(params.revision)" \
        -path "${CHECKOUT_DIR}"
      cd "${CHECKOUT_DIR}"
      # Create a symlink to the repo path as this is what most tasks expect
      ln -s "${CHECKOUT_DIR}" "${CHECKOUT_DIR}/src"
```

### Azure DevOps

**🔧 Azure Pipeline Configuration**

```yaml
# azure-pipelines.yml
trigger:
  branches:
    include:
    - main
    - develop

variables:
  dockerRegistryServiceConnection: 'my-acr-connection'
  imageRepository: 'my-app'
  containerRegistry: 'myregistry.azurecr.io'
  dockerfilePath: '$(Build.SourcesDirectory)/Dockerfile'
  tag: '$(Build.BuildId)'

stages:
- stage: Build
  displayName: Build stage
  jobs:
  - job: Build
    displayName: Build job
    pool:
      vmImage: 'ubuntu-latest'
    steps:
    - task: Docker@2
      displayName: Build and push an image to container registry
      inputs:
        command: buildAndPush
        repository: $(imageRepository)
        dockerfile: $(dockerfilePath)
        containerRegistry: $(dockerRegistryServiceConnection)
        tags: |
          $(tag)
          latest
    - task: PublishBuildArtifacts@1
      inputs:
        PathtoPublish: 'k8s'
        ArtifactName: 'k8s-manifests'
        publishLocation: 'Container'

- stage: Deploy
  displayName: Deploy stage
  dependsOn: Build
  condition: succeeded()
  jobs:
  - deployment: Deploy
    displayName: Deploy job
    pool:
      vmImage: 'ubuntu-latest'
    environment: 'production'
    strategy:
      runOnce:
        deploy:
          steps:
          - task: DownloadBuildArtifacts@0
            inputs:
              buildType: 'current'
              downloadType: 'single'
              artifactName: 'k8s-manifests'
              downloadPath: '$(System.ArtifactsDirectory)'
          - task: KubernetesManifest@0
            displayName: Deploy to Kubernetes cluster
            inputs:
              action: 'deploy'
              kubernetesServiceConnection: 'my-k8s-connection'
              namespace: 'production'
              manifests: '$(System.ArtifactsDirectory)/k8s-manifests/deployment.yaml'
              containers: '$(containerRegistry)/$(imageRepository):$(tag)'
```

***

## 🔧 **GitOps Tools**

### ArgoCD

**🚀 ArgoCD Installation**

```bash
# Create namespace
kubectl create namespace argocd

# Install ArgoCD
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml

# Access ArgoCD UI
kubectl port-forward svc/argocd-server -n argocd 8080:443

# Get initial password
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d; echo
```

**🔧 ArgoCD Application**

```yaml
# application.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: my-app
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/mycompany/k8s-manifests
    targetRevision: HEAD
    path: production
  destination:
    server: https://kubernetes.default.svc
    namespace: production
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
    - CreateNamespace=true
    retry:
      limit: 5
      backoff:
        duration: 5s
        factor: 2
        maxDuration: 3m

# Application with Helm
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: my-helm-app
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/mycompany/helm-charts
    targetRevision: HEAD
    path: my-app
    helm:
      valueFiles:
      - values-prod.yaml
      parameters:
      - name: image.tag
        value: v1.2.3
  destination:
    server: https://kubernetes.default.svc
    namespace: production
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
```

**🔧 ArgoCD App of Apps**

```yaml
# app-of-apps.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: app-of-apps
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/mycompany/k8s-manifests
    targetRevision: HEAD
    path: apps
  destination:
    server: https://kubernetes.default.svc
    namespace: argocd
  syncPolicy:
    automated:
      prune: true
      selfHeal: true

# apps/frontend-app.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: frontend-app
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/mycompany/k8s-manifests
    targetRevision: HEAD
    path: apps/frontend
  destination:
    server: https://kubernetes.default.svc
    namespace: frontend
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
```

### Flux CD

**🚀 Flux Installation**

```bash
# Install Flux CLI
curl -s https://fluxcd.io/install.sh | bash

# Bootstrap GitOps
flux bootstrap github \
  --owner=mycompany \
  --repository=k8s-manifests \
  --path=clusters/production \
  --personal \
  --private
```

**🔧 Flux Configuration**

```yaml
# clusters/production/flux-system/gotk-components.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- github.com/fluxcd/flux2/manifests/install?ref=v0.36.0

# clusters/production/flux-system/gotk-sync.yaml
apiVersion: kustomize.toolkit.fluxcd.io/v1beta2
kind: Kustomization
metadata:
  name: flux-system
  namespace: flux-system
spec:
  interval: 10m0s
  sourceRef:
    kind: GitRepository
    name: flux-system
  path: ./clusters/production
  prune: true
  wait: true
  timeout: 5m

# clusters/production/apps.yaml
apiVersion: kustomize.toolkit.fluxcd.io/v1beta2
kind: Kustomization
metadata:
  name: apps
  namespace: flux-system
spec:
  interval: 10m0s
  sourceRef:
    kind: GitRepository
    name: flux-system
  path: ./apps/production
  prune: true
  wait: true
  timeout: 5m
```

**🔧 Flux HelmRelease**

```yaml
# apps/production/my-app.yaml
apiVersion: helm.toolkit.fluxcd.io/v2beta1
kind: HelmRelease
metadata:
  name: my-app
  namespace: production
spec:
  interval: 5m
  chart:
    spec:
      chart: my-app
      version: "1.2.3"
      sourceRef:
        kind: HelmRepository
        name: my-charts
        namespace: flux-system
  values:
    image:
      repository: myregistry/my-app
      tag: v1.2.3
    replicaCount: 3
    resources:
      limits:
        cpu: 500m
        memory: 512Mi
      requests:
        cpu: 250m
        memory: 256Mi
```

### Rancher Fleet

**🚀 Fleet Installation**

```bash
# Install Rancher Fleet
kubectl apply -f https://raw.githubusercontent.com/rancher/fleet/main/examples/install.yaml

# Install Fleet CLI
curl -sfL https://raw.githubusercontent.com/rancher/fleet/main/scripts/install.sh | sh
```

**🔧 Fleet GitRepo Configuration**

```yaml
# gitrepo.yaml
apiVersion: fleet.cattle.io/v1alpha1
kind: GitRepo
metadata:
  name: my-apps
  namespace: fleet-default
spec:
  repo: https://github.com/mycompany/k8s-manifests
  branch: main
  paths:
  - production
  clientSecretName: git-auth
  targets:
  - clusterSelector:
      matchLabels:
        env: production
  - clusterSelector:
      matchLabels:
        env: staging
      paths:
      - staging

# GitRepo with Helm charts
apiVersion: fleet.cattle.io/v1alpha1
kind: GitRepo
metadata:
  name: helm-apps
  namespace: fleet-default
spec:
  repo: https://github.com/mycompany/helm-charts
  branch: main
  paths:
  - charts/my-app
  targets:
  - clusterSelector:
      matchLabels:
        env: production
  helm:
    valuesFiles:
    - values-production.yaml
    values:
      image:
        tag: v1.2.3
```

### Kustomize Integration

**🔧 Kustomize Structure**

```yaml
# base/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

resources:
- deployment.yaml
- service.yaml
- configmap.yaml

commonLabels:
  app: my-app

images:
- name: my-app
  newTag: v1.0.0

replicas:
- name: my-app
  count: 2

# overlays/production/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

bases:
- ../../base

namespace: production

patchesStrategicMerge:
- production-deployment.yaml

images:
- name: my-app
  newTag: v1.2.3

replicas:
- name: my-app
  count: 5

# overlays/staging/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

bases:
- ../../base

namespace: staging

patchesStrategicMerge:
- staging-deployment.yaml

images:
- name: my-app
  newTag: v1.2.3

replicas:
- name: my-app
  count: 2
```

***

## 📦 **Container Registries**

### Docker Hub

**🔧 Docker Hub Configuration**

```yaml
# .github/workflows/docker-hub.yml
name: Build and Push to Docker Hub

on:
  push:
    branches: [ main ]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3

    - name: Log in to Docker Hub
      uses: docker/login-action@v2
      with:
        username: ${{ secrets.DOCKER_USERNAME }}
        password: ${{ secrets.DOCKER_PASSWORD }}

    - name: Build and push
      uses: docker/build-push-action@v4
      with:
        context: .
        push: true
        tags: |
          myusername/my-app:latest
          myusername/my-app:${{ github.sha }}
```

### Amazon ECR

**🔧 Amazon ECR Configuration**

```yaml
# .github/workflows/ecr.yml
name: Build and Push to ECR

on:
  push:
    branches: [ main ]

env:
  AWS_REGION: us-west-2
  ECR_REGISTRY: ${{ secrets.AWS_ACCOUNT_ID }}.dkr.ecr.${{ env.AWS_REGION }}.amazonaws.com
  ECR_REPOSITORY: my-app
  IMAGE_TAG: ${{ github.sha }}

jobs:
  build:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write

    steps:
    - uses: actions/checkout@v3

    - name: Configure AWS credentials
      uses: aws-actions/configure-aws-credentials@v2
      with:
        aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
        aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
        aws-region: ${{ env.AWS_REGION }}

    - name: Log in to Amazon ECR
      id: login-ecr
      uses: aws-actions/amazon-ecr-login@v1

    - name: Build and push Docker image
      uses: docker/build-push-action@v4
      with:
        context: .
        push: true
        tags: ${{ env.ECR_REGISTRY }}/${{ env.ECR_REPOSITORY }}:${{ env.IMAGE_TAG }}
        cache-from: type=gha
        cache-to: type=gha,mode=max
```

### Google GCR

**🔧 Google GCR Configuration**

```yaml
# .github/workflows/gcr.yml
name: Build and Push to GCR

on:
  push:
    branches: [ main ]

jobs:
  build:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write

    steps:
    - uses: actions/checkout@v3

    - name: Authenticate to Google Cloud
      uses: google-github-actions/auth@v1
      with:
        credentials_json: ${{ secrets.GCP_CREDENTIALS }}

    - name: Set up Google Cloud CLI
      uses: google-github-actions/setup-gcloud@v1
      with:
        project_id: ${{ secrets.GCP_PROJECT_ID }}

    - name: Configure Docker to use gcloud as a credential helper
      run: gcloud auth configure-docker

    - name: Build and push Docker image
      uses: docker/build-push-action@v4
      with:
        context: .
        push: true
        tags: gcr.io/${{ secrets.GCP_PROJECT_ID }}/my-app:${{ github.sha }}
```

### Azure ACR

**🔧 Azure ACR Configuration**

```yaml
# .github/workflows/acr.yml
name: Build and Push to ACR

on:
  push:
    branches: [ main ]

env:
  ACR_REGISTRY: myregistry.azurecr.io
  IMAGE_NAME: my-app

jobs:
  build:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write

    steps:
    - uses: actions/checkout@v3

    - name: Azure Login
      uses: azure/login@v1
      with:
        creds: ${{ secrets.AZURE_CREDENTIALS }}

    - name: Build and push to Azure Container Registry
      uses: docker/build-push-action@v4
      with:
        context: .
        push: true
        tags: ${{ env.ACR_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}
```

### Harbor Registry

**🔧 Harbor Configuration**

```yaml
# .github/workflows/harbor.yml
name: Build and Push to Harbor

on:
  push:
    branches: [ main ]

env:
  HARBOR_REGISTRY: harbor.example.com
  HARBOR_PROJECT: my-project
  IMAGE_NAME: my-app

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v3

    - name: Log in to Harbor
      uses: docker/login-action@v2
      with:
        registry: ${{ env.HARBOR_REGISTRY }}
        username: ${{ secrets.HARBOR_USERNAME }}
        password: ${{ secrets.HARBOR_PASSWORD }}

    - name: Build and push
      uses: docker/build-push-action@v4
      with:
        context: .
        push: true
        tags: |
          ${{ env.HARBOR_REGISTRY }}/${{ env.HARBOR_PROJECT }}/${{ env.IMAGE_NAME }}:latest
          ${{ env.HARBOR_REGISTRY }}/${{ env.HARBOR_PROJECT }}/${{ env.IMAGE_NAME }}:${{ github.sha }}
```

***

## 🔍 **Pipeline Best Practices**

### Image Security Scanning

**🔧 Security Scanning Integration**

```yaml
# .github/workflows/security.yml
name: Security Scanning

on:
  push:
    branches: [ main ]

jobs:
  security:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3

    - name: Build image
      run: docker build -t test-image .

    - name: Run Trivy vulnerability scanner
      uses: aquasecurity/trivy-action@master
      with:
        image-ref: 'test-image'
        format: 'sarif'
        output: 'trivy-results.sarif'

    - name: Upload Trivy scan results to GitHub Security tab
      uses: github/codeql-action/upload-sarif@v2
      with:
        sarif_file: 'trivy-results.sarif'

    - name: Run Snyk to check for vulnerabilities
      uses: snyk/actions/docker@master
      env:
        SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
      with:
        image: test-image
        args: --severity-threshold=high
```

### Multi-Environment Deployment

**🔧 Environment-Specific Configuration**

```yaml
# environments/production/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
  namespace: production
spec:
  replicas: 5
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
        env: production
    spec:
      containers:
      - name: app
        image: ${IMAGE_REGISTRY}/my-app:${IMAGE_TAG}
        ports:
        - containerPort: 8080
        env:
        - name: ENVIRONMENT
          value: "production"
        - name: LOG_LEVEL
          value: "INFO"
        resources:
          requests:
            cpu: 250m
            memory: 256Mi
          limits:
            cpu: 500m
            memory: 512Mi
        livenessProbe:
          httpGet:
            path: /health
            port: 8080
          initialDelaySeconds: 30
          periodSeconds: 10
        readinessProbe:
          httpGet:
            path: /ready
            port: 8080
          initialDelaySeconds: 5
          periodSeconds: 5

# environments/staging/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
  namespace: staging
spec:
  replicas: 2
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
        env: staging
    spec:
      containers:
      - name: app
        image: ${IMAGE_REGISTRY}/my-app:${IMAGE_TAG}
        ports:
        - containerPort: 8080
        env:
        - name: ENVIRONMENT
          value: "staging"
        - name: LOG_LEVEL
          value: "DEBUG"
        resources:
          requests:
            cpu: 100m
            memory: 128Mi
          limits:
            cpu: 200m
            memory: 256Mi
```

### Rollback Strategies

**🔧 Rollback Configuration**

```yaml
# rollback-strategy.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: my-app
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/mycompany/k8s-manifests
    targetRevision: HEAD
    path: production
  destination:
    server: https://kubernetes.default.svc
    namespace: production
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
      allowEmpty: false
    syncOptions:
    - CreateNamespace=true
    - PrunePropagationPolicy=foreground
    - PruneLast=true
    retry:
      limit: 5
      backoff:
        duration: 5s
        factor: 2
        maxDuration: 3m

# Manual rollback commands
# argocd app rollback my-app <revision>
# kubectl rollout undo deployment/my-app
```

### Monitoring & Alerting

**🔧 Pipeline Monitoring**

```yaml
# monitoring/pipeline-alerts.yaml
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
  name: pipeline-alerts
  namespace: monitoring
spec:
  groups:
  - name: pipeline
    rules:
    - alert: DeploymentFailed
      expr: kube_deployment_status_replicas_unavailable > 0
      for: 5m
      labels:
        severity: critical
      annotations:
        summary: "Deployment {{ $labels.deployment }} failed"
        description: "Deployment {{ $labels.deployment }} in namespace {{ $labels.namespace }} has unavailable replicas"

    - alert: PodCrashLooping
      expr: rate(kube_pod_container_status_restarts_total[15m]) > 0
      for: 5m
      labels:
        severity: warning
      annotations:
        summary: "Pod {{ $labels.pod }} is crash looping"
        description: "Pod {{ $labels.pod }} in namespace {{ $labels.namespace }} is restarting frequently"

    - alert: PipelineRunFailed
      expr: tekton_pipelinerun_condition{condition="Failed"} == 1
      for: 0m
      labels:
        severity: critical
      annotations:
        summary: "Pipeline {{ $labels.pipelinerun }} failed"
        description: "Pipeline {{ $labels.pipelinerun }} in namespace {{ $labels.namespace }} has failed"
```

***

## 🎯 **Best Practices**

### **🔄 CI/CD Best Practices**

1. **Pipeline Design**
   * Keep pipelines fast and reliable
   * Use parallel execution when possible
   * Implement proper error handling
2. **Security Integration**
   * Scan images for vulnerabilities
   * Use secrets management properly
   * Implement access controls
3. **Environment Management**
   * Separate configurations per environment
   * Use GitOps for consistency
   * Implement proper testing stages

### **🔧 GitOps Best Practices**

1. **Repository Structure**
   * Clear separation of environments
   * Consistent naming conventions
   * Proper documentation
2. **Change Management**
   * Use pull requests for changes
   * Implement approval workflows
   * Track changes properly
3. **Monitoring & Alerting**
   * Monitor sync status
   * Alert on drift detection
   * Track deployment metrics

### **📊 Performance Optimization**

1. **Build Optimization**
   * Use build caching
   * Optimize Docker layers
   * Parallelize builds
2. **Deployment Optimization**
   * Use progressive delivery
   * Implement proper health checks
   * Optimize resource usage

***

## 🔗 **Referensi**

### **📚 Dokumentasi Resmi**

* [GitOps Principles](https://www.weaveworks.com/what-is-gitops)
* [ArgoCD Documentation](https://argoproj.github.io/argo-cd/)
* [Flux Documentation](https://fluxcd.io/docs/)
* [GitHub Actions Documentation](https://docs.github.com/en/actions)

### **🛠️ Tool Resources**

* [Jenkins X Documentation](https://jenkins-x.io/docs/)
* [Tekton Documentation](https://tekton.dev/docs/)
* [GitLab CI/CD Documentation](https://docs.gitlab.com/ee/ci/)

### **📖 Learning Resources**

* [GitOps with ArgoCD Course](https://argoproj.github.io/argo-cd/tutorials/)
* [Kubernetes CI/CD Best Practices](https://kubernetes.io/docs/tutorials/)
* [Container Registry Security](https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/)

***

\*🔄 **Automation adalah kunci untuk scalable dan reliable deployment practices**
