Skip to main content

Implementasi Workflow untuk Docusaurus

Pengenalan

Pada bagian ini, kita akan membahas implementasi workflow Gitea Actions untuk project Docusaurus. Workflow ini mencakup proses build, test, containerization, dan deployment ke Kubernetes.

Struktur Workflow

Directory Structure

.gitea/
└── workflows/
├── build.yml # Build dan test aplikasi
├── docker.yml # Build dan push Docker image
└── deploy.yml # Deploy ke Kubernetes

1. Build Workflow

File: .gitea/workflows/build.yml

Workflow ini bertanggung jawab untuk:

  • Checkout source code
  • Install dependencies
  • Build aplikasi Docusaurus
  • Upload build artifacts
name: Build and Test

on:
push:
branches:
- main
- develop
pull_request:
branches:
- main
- develop

jobs:
build:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v3
with:
fetch-depth: 0

- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '20'
cache: 'npm'

- name: Install dependencies
run: npm ci

- name: Run type check
run: npm run typecheck

- name: Build application
run: npm run build
env:
NODE_ENV: production

- name: Upload build artifacts
uses: actions/upload-artifact@v3
with:
name: docusaurus-build
path: build/
retention-days: 7

- name: Build size report
run: |
echo "## Build Size Report" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "```" >> $GITHUB_STEP_SUMMARY
du -sh build/ >> $GITHUB_STEP_SUMMARY
echo "```" >> $GITHUB_STEP_SUMMARY

lint:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v3

- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '20'
cache: 'npm'

- name: Install dependencies
run: npm ci

- name: Run ESLint
run: npm run lint --if-present
continue-on-error: true

Penjelasan Build Workflow

Triggers

on:
push:
branches:
- main
- develop
  • Workflow berjalan otomatis saat ada push ke branch main atau develop
  • Juga berjalan pada pull request

Build Job

  • Checkout code: Mengambil source code dari repository
  • Setup Node.js: Install Node.js 20 dengan caching npm
  • Install dependencies: npm ci untuk clean install
  • Type check: Validasi TypeScript
  • Build: Compile aplikasi Docusaurus
  • Upload artifacts: Simpan hasil build untuk job berikutnya

Environment Variables

  • NODE_ENV=production: Optimize build untuk production

2. Docker Workflow

File: .gitea/workflows/docker.yml

Workflow untuk build dan push Docker image ke container registry.

name: Docker Build and Push

on:
push:
branches:
- main
tags:
- 'v*'
workflow_dispatch:

env:
REGISTRY: docker.io
IMAGE_NAME: ${{ gitea.repository_owner }}/gitea-docs

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

steps:
- name: Checkout code
uses: actions/checkout@v3

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

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

- 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=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=sha,prefix={{branch}}-
type=raw,value=latest,enable={{is_default_branch}}

- name: Build and push Docker image
uses: docker/build-push-action@v4
with:
context: .
file: ./Dockerfile
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache
cache-to: type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache,mode=max
platforms: linux/amd64,linux/arm64

- name: Image digest
run: echo ${{ steps.docker_build.outputs.digest }}

- name: Scan image for vulnerabilities
uses: aquasecurity/trivy-action@master
with:
image-ref: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
format: 'sarif'
output: 'trivy-results.sarif'
continue-on-error: true

- name: Upload scan results
uses: github/codeql-action/upload-sarif@v2
with:
sarif_file: 'trivy-results.sarif'
continue-on-error: true

Penjelasan Docker Workflow

Multi-platform Build

platforms: linux/amd64,linux/arm64

Build image untuk multiple architectures (AMD64 dan ARM64)

Image Tagging Strategy

  • branch name: Untuk tracking per branch
  • sha: Unique identifier dari commit
  • semver: Semantic versioning untuk releases
  • latest: Tag untuk main branch

Docker Layer Caching

cache-from: type=registry,ref=...
cache-to: type=registry,ref=...

Mempercepat build dengan cache layers di registry

Security Scanning

  • Trivy scan untuk detect vulnerabilities
  • Output SARIF format untuk integration dengan security tools

3. Deployment Workflow

File: .gitea/workflows/deploy.yml

Workflow untuk deploy aplikasi ke Kubernetes cluster.

name: Deploy to Kubernetes

on:
workflow_run:
workflows: ["Docker Build and Push"]
types:
- completed
branches:
- main
workflow_dispatch:
inputs:
environment:
description: 'Deployment environment'
required: true
default: 'staging'
type: choice
options:
- staging
- production

env:
REGISTRY: docker.io
IMAGE_NAME: ${{ gitea.repository_owner }}/gitea-docs

jobs:
deploy:
runs-on: ubuntu-latest
if: ${{ github.event.workflow_run.conclusion == 'success' }}

environment:
name: ${{ inputs.environment || 'staging' }}
url: https://${{ inputs.environment || 'staging' }}.example.com

steps:
- name: Checkout code
uses: actions/checkout@v3

- name: Setup kubectl
uses: azure/setup-kubectl@v3
with:
version: 'v1.28.0'

- name: Configure kubectl
run: |
mkdir -p $HOME/.kube
echo "${{ secrets.KUBE_CONFIG }}" | base64 -d > $HOME/.kube/config
chmod 600 $HOME/.kube/config

- name: Verify cluster connection
run: |
kubectl cluster-info
kubectl get nodes

- name: Set image tag
id: image
run: |
if [ "${{ github.ref }}" == "refs/heads/main" ]; then
echo "tag=latest" >> $GITHUB_OUTPUT
else
echo "tag=${{ github.sha }}" >> $GITHUB_OUTPUT
fi

- name: Update deployment image
run: |
kubectl set image deployment/gitea-docs \
gitea-docs=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.image.outputs.tag }} \
-n gitea-docs-${{ inputs.environment || 'staging' }}

- name: Apply Kubernetes manifests
run: |
kubectl apply -f k8s/ \
-n gitea-docs-${{ inputs.environment || 'staging' }}

- name: Wait for rollout
run: |
kubectl rollout status deployment/gitea-docs \
-n gitea-docs-${{ inputs.environment || 'staging' }} \
--timeout=5m

- name: Verify deployment
run: |
kubectl get pods -n gitea-docs-${{ inputs.environment || 'staging' }}
kubectl get services -n gitea-docs-${{ inputs.environment || 'staging' }}

- name: Run smoke tests
run: |
ENDPOINT="https://${{ inputs.environment || 'staging' }}.example.com"

echo "Testing endpoint: $ENDPOINT"

# Health check
curl -f $ENDPOINT/health || exit 1

# Homepage check
STATUS=$(curl -o /dev/null -s -w "%{http_code}" $ENDPOINT)
if [ $STATUS -ne 200 ]; then
echo "Smoke test failed with status: $STATUS"
exit 1
fi

echo "Smoke tests passed!"

- name: Rollback on failure
if: failure()
run: |
echo "Deployment failed, initiating rollback..."
kubectl rollout undo deployment/gitea-docs \
-n gitea-docs-${{ inputs.environment || 'staging' }}
kubectl rollout status deployment/gitea-docs \
-n gitea-docs-${{ inputs.environment || 'staging' }}

notify:
runs-on: ubuntu-latest
needs: deploy
if: always()

steps:
- name: Send notification
run: |
STATUS="${{ needs.deploy.result }}"
ENV="${{ inputs.environment || 'staging' }}"

if [ "$STATUS" == "success" ]; then
MESSAGE="✅ Deployment to $ENV succeeded!"
else
MESSAGE="❌ Deployment to $ENV failed!"
fi

# Send to webhook (Slack, Discord, etc.)
curl -X POST ${{ secrets.WEBHOOK_URL }} \
-H 'Content-Type: application/json' \
-d "{\"text\":\"$MESSAGE\"}"

Penjelasan Deployment Workflow

Trigger Conditions

workflow_run:
workflows: ["Docker Build and Push"]
types: [completed]
  • Otomatis berjalan setelah Docker workflow selesai
  • Manual trigger dengan workflow_dispatch

Environment Strategy

  • Staging: Auto-deploy dari main branch
  • Production: Manual approval required

Deployment Steps

  1. Setup kubectl: Install Kubernetes CLI
  2. Configure access: Setup kubeconfig dari secrets
  3. Update image: Set image tag terbaru
  4. Apply manifests: Deploy Kubernetes resources
  5. Wait rollout: Monitor deployment progress
  6. Smoke tests: Basic health checks
  7. Rollback: Auto-rollback jika gagal

Rollback Strategy

kubectl rollout undo deployment/gitea-docs

Automatic rollback ke revision sebelumnya jika deployment gagal

4. Complete Pipeline Workflow

File: .gitea/workflows/pipeline.yml

Workflow lengkap yang menggabungkan semua tahapan.

name: Complete CI/CD Pipeline

on:
push:
branches:
- main
- develop
pull_request:
branches:
- main

jobs:
# Stage 1: Build dan Test
build:
name: Build Application
runs-on: ubuntu-latest
outputs:
version: ${{ steps.version.outputs.version }}

steps:
- uses: actions/checkout@v3

- uses: actions/setup-node@v3
with:
node-version: '20'
cache: 'npm'

- name: Get version
id: version
run: |
VERSION=$(node -p "require('./package.json').version")
echo "version=$VERSION" >> $GITHUB_OUTPUT

- run: npm ci
- run: npm run typecheck
- run: npm run build

- uses: actions/upload-artifact@v3
with:
name: build-${{ github.sha }}
path: build/

# Stage 2: Security Scan
security:
name: Security Scan
runs-on: ubuntu-latest
needs: build

steps:
- uses: actions/checkout@v3

- name: Run dependency check
run: npm audit --audit-level=moderate
continue-on-error: true

- name: Run SAST scan
uses: aquasecurity/trivy-action@master
with:
scan-type: 'fs'
scan-ref: '.'
format: 'sarif'
output: 'trivy-results.sarif'

# Stage 3: Docker Build
docker:
name: Build Docker Image
runs-on: ubuntu-latest
needs: [build, security]
if: github.ref == 'refs/heads/main'
outputs:
image-tag: ${{ steps.meta.outputs.tags }}

steps:
- uses: actions/checkout@v3

- uses: docker/setup-buildx-action@v2

- uses: docker/login-action@v2
with:
registry: docker.io
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}

- name: Build and push
id: docker_build
uses: docker/build-push-action@v4
with:
context: .
push: true
tags: |
docker.io/${{ gitea.repository_owner }}/gitea-docs:latest
docker.io/${{ gitea.repository_owner }}/gitea-docs:${{ needs.build.outputs.version }}
docker.io/${{ gitea.repository_owner }}/gitea-docs:${{ github.sha }}

# Stage 4: Deploy to Staging
deploy-staging:
name: Deploy to Staging
runs-on: ubuntu-latest
needs: docker
if: github.ref == 'refs/heads/main'
environment:
name: staging
url: https://staging.example.com

steps:
- uses: actions/checkout@v3

- name: Deploy to Kubernetes
run: |
# Setup kubectl
mkdir -p $HOME/.kube
echo "${{ secrets.KUBE_CONFIG }}" | base64 -d > $HOME/.kube/config

# Deploy
kubectl set image deployment/gitea-docs \
gitea-docs=docker.io/${{ gitea.repository_owner }}/gitea-docs:${{ github.sha }} \
-n gitea-docs-staging

# Wait for rollout
kubectl rollout status deployment/gitea-docs -n gitea-docs-staging

# Stage 5: Integration Tests
integration-tests:
name: Integration Tests
runs-on: ubuntu-latest
needs: deploy-staging

steps:
- uses: actions/checkout@v3

- name: Run integration tests
run: |
# Wait for application to be ready
sleep 30

# Run tests against staging
curl -f https://staging.example.com/health
curl -f https://staging.example.com/

echo "✅ Integration tests passed"

# Stage 6: Deploy to Production
deploy-production:
name: Deploy to Production
runs-on: ubuntu-latest
needs: [integration-tests]
if: github.ref == 'refs/heads/main'
environment:
name: production
url: https://docs.example.com

steps:
- uses: actions/checkout@v3

- name: Deploy to Production
run: |
# Setup kubectl
mkdir -p $HOME/.kube
echo "${{ secrets.KUBE_CONFIG_PROD }}" | base64 -d > $HOME/.kube/config

# Deploy with canary strategy
kubectl set image deployment/gitea-docs \
gitea-docs=docker.io/${{ gitea.repository_owner }}/gitea-docs:${{ github.sha }} \
-n gitea-docs-production

# Wait and monitor
kubectl rollout status deployment/gitea-docs -n gitea-docs-production

- name: Smoke tests
run: |
curl -f https://docs.example.com/health
curl -f https://docs.example.com/

Secrets Configuration

Required Secrets

Tambahkan secrets di Gitea Repository Settings → Secrets:

Secret NameDescriptionExample
DOCKER_USERNAMEDocker Hub usernamemyusername
DOCKER_PASSWORDDocker Hub password/tokendckr_pat_xxxxx
KUBE_CONFIGKubernetes config (base64)base64 encoded kubeconfig
KUBE_CONFIG_PRODProduction K8s configbase64 encoded kubeconfig
WEBHOOK_URLNotification webhookhttps://hooks.slack.com/...

Generate base64 kubeconfig

cat ~/.kube/config | base64 -w 0

Workflow Best Practices

1. Job Dependencies

needs: [build, test]

Ensure proper execution order

2. Conditional Execution

if: github.ref == 'refs/heads/main'

Control when jobs run

3. Matrix Testing

strategy:
matrix:
node-version: [18, 20, 22]

Test multiple versions

4. Caching

- uses: actions/cache@v3
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}

Speed up builds

5. Artifacts

- uses: actions/upload-artifact@v3
with:
name: build-artifacts
path: build/

Share data between jobs

Monitoring Workflows

View Workflow Runs

  1. Navigate ke repository di Gitea
  2. Click tab Actions
  3. View workflow runs, logs, dan artifacts

Workflow Status Badge

Tambahkan di README.md:

![CI/CD Pipeline](https://gitea.example.com/username/repo/workflows/pipeline.yml/badge.svg)

Troubleshooting

Workflow Tidak Berjalan

Cek:

  • Gitea Actions enabled di repository settings
  • Runner tersedia dan online
  • Workflow file syntax valid
  • Branch protection rules

Build Failures

Debug steps:

- name: Debug
run: |
echo "GitHub context:"
echo "${{ toJSON(github) }}"

echo "Environment variables:"
env | sort

Permission Issues

Fix:

permissions:
contents: read
packages: write

Kesimpulan

Implementasi workflow Gitea Actions untuk Docusaurus mencakup:

  • ✅ Automated build dan testing
  • ✅ Docker image creation
  • ✅ Multi-stage deployment
  • ✅ Security scanning
  • ✅ Automatic rollback
  • ✅ Notification system

Pipeline ini memberikan foundation yang solid untuk continuous delivery dengan reliability dan security yang tinggi.

Next: Konfigurasi Kubernetes manifests untuk deployment.