Lewati ke konten
Kembali ke Blog

CI/CD untuk Hugo: GitHub Actions dan Deployment Otomatis

· · 7 menit baca

Continuous Integration dan Continuous Deployment (CI/CD) adalah practices yang essential untuk workflow pengembangan modern. Untuk Hugo sites, CI/CD dapat mengautomasi build process, testing, dan deployment, memungkinkan developer fokus pada content dan development tanpa manual overhead. Panduan ini akan membahas cara setup CI/CD pipeline yang robust untuk Hugo dengan GitHub Actions.

Implementasi CI/CD untuk Hugo sites memberikan banyak keuntungan: automated testing sebelum deployment, consistent build environment, faster iteration cycles, dan rollback capability jika ada issues.

Memahami GitHub Actions untuk Hugo

GitHub Actions adalah CI/CD platform yang terintegrasi dengan GitHub, memungkinkan workflow automation berdasarkan events di repository.

Struktur GitHub Actions

GitHub Actions menggunakan workflow files dalam format YAML yang disimpan di .github/workflows/:

name: Hugo CI/CD

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

jobs: build: runs-on: ubuntu-latest steps:

  • uses: actions/checkout@v4

Workflow Basic Build

Setup Hugo dan Build

# .github/workflows/hugo-build.yml
name: Build Hugo Site

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

jobs: build: runs-on: ubuntu-latest steps:

  • name: Checkout uses: actions/checkout@v4 with: submodules: true fetch-depth: 0
  - name: Setup Hugo
    uses: peaceiris/actions-hugo@v2
    with:
      hugo-version: '0.139.2'
      extended: true

  - name: Build
    run: hugo --minify

  - name: Upload build artifacts
    uses: actions/upload-artifact@v4
    with:
      name: hugo-build
      path: public/
      retention-days: 7

Deployment Workflows

Deploy ke GitHub Pages

# .github/workflows/gh-pages.yml
name: Deploy to GitHub Pages

on: push: branches: [main] workflow_dispatch:

permissions: contents: read pages: write id-token: write

concurrency: group: "pages" cancel-in-progress: false

jobs: deploy: environment: name: github-pages url: ${{ steps.deployment.outputs.page_url }} runs-on: ubuntu-latest steps:

  • name: Checkout uses: actions/checkout@v4 with: submodules: true fetch-depth: 0
  - name: Setup Hugo
    uses: peaceiris/actions-hugo@v2
    with:
      hugo-version: '0.139.2'
      extended: true

  - name: Build
    run: hugo --minify

  - name: Setup Pages
    uses: actions/configure-pages@v4

  - name: Upload artifact
    uses: actions/upload-pages-artifact@v3
    with:
      path: public/

  - name: Deploy to GitHub Pages
    id: deployment
    uses: actions/deploy-pages@v4

Deploy ke Cloudflare Pages

# .github/workflows/cloudflare-pages.yml
name: Deploy to Cloudflare Pages

on: push: branches: [main] workflow_dispatch:

jobs: deploy: runs-on: ubuntu-latest steps:

  • name: Checkout uses: actions/checkout@v4 with: submodules: true
  - name: Setup Hugo
    uses: peaceiris/actions-hugo@v2
    with:
      hugo-version: '0.139.2'
      extended: true

  - name: Build
    run: hugo --minify

  - name: Deploy to Cloudflare Pages
    uses: cloudflare/pages-action@v1
    with:
      apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
      accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
      projectName: my-hugo-site
      directory: public
      gitHubToken: ${{ secrets.GITHUB_TOKEN }}

Deploy ke Netlify

# .github/workflows/netlify.yml
name: Deploy to Netlify

on: push: branches: [main] workflow_dispatch:

jobs: deploy: runs-on: ubuntu-latest steps:

  • name: Checkout uses: actions/checkout@v4 with: submodules: true
  - name: Setup Hugo
    uses: peaceiris/actions-hugo@v2
    with:
      hugo-version: '0.139.2'
      extended: true

  - name: Build
    run: hugo --minify

  - name: Deploy to Netlify
    uses: nwtgck/actions-netlify@v3
    with:
      publish-dir: './public'
      production-branch: main
      github-token: ${{ secrets.GITHUB_TOKEN }}
      deploy-message: "Deploy from GitHub Actions"
      enable-pull-request-comment: true
      enable-commit-comment: true
    env:
      NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
      NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }}

Automated Testing

Lighthouse CI

# .github/workflows/lighthouse.yml
name: Lighthouse CI

on: [push]

jobs: lighthouse: runs-on: ubuntu-latest steps:

  • uses: actions/checkout@v4
  - name: Setup Hugo
    uses: peaceiris/actions-hugo@v2
    with:
      hugo-version: '0.139.2'
      extended: true

  - name: Build Hugo
    run: hugo --minify

  - name: Run Lighthouse CI
    uses: treosh/lighthouse-ci-action@v11
    with:
      urls: |
        https://example.com
        https://example.com/posts
      budgetPath: ./lighthouse-budget.json

Lighthouse budget configuration:

{
  "ci": {
    "assert": {
      "assertions": {
        "categories:performance": ["error", { "minScore": 0.9 }],
        "categories:accessibility": ["error", { "minScore": 0.9 }],
        "categories:best-practices": ["error", { "minScore": 0.9 }],
        "categories:seo": ["error", { "minScore": 0.9 }]
      }
    }
  }
}

Link Checker

# .github/workflows/link-checker.yml
name: Check Links

on: push: branches: [main] schedule:

  • cron: '0 0 0' # Weekly

jobs: link-check: runs-on: ubuntu-latest steps:

  • uses: actions/checkout@v4
  - name: Setup Hugo
    uses: peaceiris/actions-hugo@v2
    with:
      hugo-version: '0.139.2'

  - name: Build
    run: hugo --minify

  - name: Check links
    uses: freebroccolo/github-action-markdown-link-check@1
    with:
      use-quiet-mode: 'yes'
      use-verbose-mode: 'yes'
      config-file: '.linkcheckerrc.json'

HTML Validation

# .github/workflows/html-validator.yml
name: HTML Validation

on: push: branches: [main]

jobs: validate: runs-on: ubuntu-latest steps:

  • uses: actions/checkout@v4
  - name: Setup Hugo
    uses: peaceiris/actions-hugo@v2
    with:
      hugo-version: '0.139.2'

  - name: Build
    run: hugo --minify

  - name: Validate HTML
    run: |
      npm install -g html-validate
      html-validate public/**/*.html

Content Update Triggers

Scheduled Builds

# .github/workflows/scheduled-build.yml
name: Scheduled Content Update

on: schedule:

  • cron: '0 /4 ' # Every 4 hours

workflow_dispatch:

jobs: rebuild: runs-on: ubuntu-latest steps:

  • uses: actions/checkout@v4 with: fetch-depth: 0
  - name: Setup Hugo
    uses: peaceiris/actions-hugo@v2
    with:
      hugo-version: '0.139.2'
      extended: true

  - name: Build
    run: hugo --minify

  - name: Deploy to Production
    # Your deployment step here

Webhook-Based Rebuild

# .github/workflows/webhook.yml
name: Webhook Trigger

on: repository_dispatch: types: [content-update] workflow_dispatch:

jobs: rebuild: runs-on: ubuntu-latest steps:

  • uses: actions/checkout@v4
  - name: Setup Hugo
    uses: peaceiris/actions-hugo@v2
    with:
      hugo-version: '0.139.2'
      extended: true

  - name: Build and Deploy
    run: |
      hugo --minify
      # Deployment commands

Environment-Specific Builds

Multi-Environment Setup

# .github/workflows/multi-env.yml
name: Multi-Environment Deploy

on: push: branches: [main, develop]

jobs: build: runs-on: ubuntu-latest steps:

  • uses: actions/checkout@v4
  - name: Setup Hugo
    uses: peaceiris/actions-hugo@v2
    with:
      hugo-version: '0.139.2'
      extended: true

  - name: Build
    run: hugo --environment ${{ github.ref == 'refs/heads/main' && 'production' || 'development' }}

  - name: Upload artifact
    uses: actions/upload-artifact@v4
    with:
      name: hugo-build
      path: public/

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

  • name: Download artifact
    uses: actions/download-artifact@v4
    with:
    name: hugo-build
    path: public/
  - name: Deploy to Staging
    # Staging deployment

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

  • name: Download artifact
    uses: actions/download-artifact@v4
    with:
    name: hugo-build
    path: public/
  - name: Deploy to Production
    # Production deployment

Caching Strategies

NPM Dependencies Cache

- name: Cache Node modules
  uses: actions/cache@v4
  with:
    path: node_modules
    key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
    restore-keys: |
      ${{ runner.os }}-node-

Hugo Resources Cache

- name: Cache Hugo resources
  uses: actions/cache@v4
  with:
    path: resources
    key: ${{ runner.os }}-hugo-resources-${{ hashFiles('**/*.md') }}
    restore-keys: |
      ${{ runner.os }}-hugo-resources-

Notification dan Monitoring

Slack Notifications

- name: Notify on failure
  if: failure()
  uses: 8398a7/action-slack@v3
  with:
    status: failure
    channel: '#deployments'
    text: 'Hugo build failed!'
  env:
    SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}

Build Summary

- name: Build Summary
  if: always()
  uses: actions/github-script@v7
  with:
    script: |
      const { data } = await github.rest.repos.createCommitStatus({
        owner: context.repo.owner,
        repo: context.repo.repo,
        sha: context.sha,
        state: '${{ job.status }}' === 'success' ? 'success' : 'failure',
        target_url: '${{ env.RUN_URL }}',
        description: 'Hugo build ${{ job.status }}'
      });

Best Practices

Security

Simpan secrets dengan aman menggunakan GitHub Secrets. Jangan pernah commit sensitive data. Gunakan specific versions untuk actions. Review permissions yang diminta oleh actions.

Performance

Gunakan caching untuk mempercepat builds. Parallelize jobs jika memungkinkan. Use artifacts untuk share build outputs antar jobs.

Reliability

Implementasikan retry logic untuk network operations. Monitor build times dan optimize jika terlalu lama. Use specific Hugo version untuk consistency.

Kesimpulan

CI/CD pipeline yang well-designed adalah essential untuk Hugo sites production. Dengan GitHub Actions, Anda dapat mengautomate seluruh workflow dari code commit hingga deployment. Implementasi tips dan best practices di panduan ini akan membantu membangun pipeline yang reliable dan efficient.

Ditulis oleh

Hendra Wijaya

Tinggalkan Komentar

Email tidak akan ditampilkan.