---
title: "CI/CD Pipeline"
linkTitle: "CI/CD"
weight: 40
description: >
  Automated testing and container build process.
---

## Overview

Our documentation uses a continuous integration and deployment pipeline to ensure quality and automate deployment.

{{< likec4-view view="cicdPipeline" project="documentation-platform" >}}

## GitHub Actions Workflow

The CI/CD pipeline is defined in `.github/workflows/test.yml` and runs on:

- **Pushes to `main` branch**
- **Pull requests to `main` branch**

### Workflow Steps

#### 1. Checkout Code

```yaml
- uses: actions/checkout@v4
  with:
    submodules: recursive
    fetch-depth: 0
```

- Clones repository with full history
- Includes Git submodules (Hugo modules)

#### 2. Setup Hugo

```yaml
- name: Setup Hugo
  uses: peaceiris/actions-hugo@v3
  with:
    hugo-version: 'latest'
    extended: true
```

- Installs Hugo Extended
- Uses latest stable version

#### 3. Setup Node.js

```yaml
- name: Setup Node
  uses: actions/setup-node@v4
  with:
    node-version: '24'
    cache: 'npm'
```

- Installs Node.js v24
- Caches npm dependencies for faster builds

#### 4. Install Dependencies

```bash
npm ci
go install github.com/wjdp/htmltest@latest
```

- Installs npm packages (markdownlint, htmlvalidate)
- Installs htmltest for link checking

#### 5. Run Tests

```bash
npm run test:build
npm run test:markdown
npm run test:html
```

- Validates Hugo build
- Lints Markdown files
- Validates HTML output

#### 6. Link Checking

```yaml
- name: Run link checker
  run: htmltest
  continue-on-error: true
```

- Checks all links
- Continues even if links fail (soft requirement)

#### 7. Upload Results

```yaml
- name: Upload htmltest results
  uses: actions/upload-artifact@v4
  if: always()
  with:
    name: htmltest-report
    path: tmp/.htmltest/
```

- Uploads link check report
- Available for download from GitHub Actions

## Container Build Process

After tests pass, a container image is built:

```bash
task build:oci-image
```

### Build Process

1. **Reads version information** from `.env.versions`:
   - `NODE_VERSION`
   - `GO_VERSION`
   - `HUGO_VERSION`

2. **Builds Docker image** using `Dockerfile`:
   - Multi-stage build
   - Hugo generates static site
   - Nginx serves the content

3. **Tags image** with:
   - `latest`
   - Git commit SHA (short)

### Dockerfile Structure

```dockerfile
# Build stage
FROM node:${NODE_VERSION} as builder
# Install Hugo, build dependencies
# Run: hugo --gc --minify
# Output: public/ directory

# Runtime stage
FROM nginx:alpine
# Copy public/ to /usr/share/nginx/html/
# Configure Nginx
```

### Testing the Container

```bash
task test:oci-image
```

This:

1. Builds the image
2. Starts container on port 8080
3. Tests HTTP endpoint
4. Cleans up container

## Package.json Scripts

The `package.json` defines test scripts:

```json
{
  "scripts": {
    "test:build": "hugo --gc --minify --logLevel info",
    "test:markdown": "markdownlint 'content/**/*.md'",
    "test:html": "htmlvalidate 'public/**/*.html'"
  }
}
```

## Running CI Locally

Simulate the CI environment locally:

```bash
task ci
```

This runs the same tests as GitHub Actions.

## Monitoring CI Results

### Successful Build

✅ All tests pass → Ready to deploy

### Failed Build

❌ Tests fail:

1. Click on the failed workflow in GitHub Actions
2. Expand the failed step
3. Read the error message
4. Fix locally: `task test:<specific-test>`
5. Commit and push fix

### Viewing Artifacts

1. Go to GitHub Actions
2. Click on workflow run
3. Scroll to "Artifacts" section
4. Download `htmltest-report`

## Best Practices

1. **Don't push to main directly** - Use feature branches and PRs
2. **Wait for CI before merging** - Green checkmark required
3. **Fix broken builds immediately** - Don't let main stay red
4. **Review CI logs** - Understand why tests fail
5. **Update dependencies** - Keep versions current in `.env.versions`

## Continuous Deployment

After successful CI:

1. Container image is built
2. Image is pushed to registry
3. Deployment process begins (see [Publishing](../publishing/))

## Troubleshooting

### Tests pass locally but fail in CI

**Possible causes:**

- Different Hugo version
- Different Node.js version
- Missing dependencies
- Environment-specific issues

**Solution:** Check versions in `.env.versions` and ensure local matches CI

### Build timeouts

**Possible causes:**

- Link checker taking too long
- Large number of external links

**Solution:**

- Use `continue-on-error: true` for link checks
- Configure `.htmltest.yml` to skip slow checks

### Cache issues

**Solution:** Clear GitHub Actions cache:

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

Update the cache key to force refresh.

## Next Steps

Learn about [deployment to Edge environment](../publishing/).
