Add GitHub Actions CI/CD workflows and documentation

- Add Docker image build and push workflow (multi-arch: amd64, arm64)
- Add Helm chart release workflow with GitHub Pages publishing
- Add comprehensive release workflow for version tags
- Add PR validation workflow (tests, linting, validation)
- Update Chart.yaml and values.yaml with GitHub URLs
- Update image repository to use ghcr.io
- Add detailed CI/CD documentation and setup guides

Workflows provide:
- Automated Docker image builds to GitHub Container Registry
- Automated Helm chart releases to GitHub Pages
- Complete release automation with version tagging
- PR validation with tests and linting

Helm repository will be available at:
https://vegardengen.github.io/unifi-network-operator

Docker images available at:
ghcr.io/vegardengen/unifi-network-operator
This commit is contained in:
2025-10-25 21:27:29 +02:00
parent ea68bed9c2
commit c4f7cf63fa
10 changed files with 1387 additions and 3 deletions

264
.github/README.md vendored Normal file
View File

@@ -0,0 +1,264 @@
# GitHub Workflows Documentation
This directory contains GitHub Actions workflows for automating the build, test, and release process of the UniFi Network Operator.
## Workflows Overview
### 1. Docker Build and Push (`docker-build-push.yaml`)
**Triggers:**
- Push to `main` branch
- Push to `feature/**` branches
- Push of tags starting with `v*`
- Pull requests to `main`
- Manual dispatch
**What it does:**
- Runs Go tests with coverage
- Builds multi-architecture Docker images (amd64, arm64)
- Pushes images to GitHub Container Registry (ghcr.io)
- Creates tags based on branch/tag names
**Image naming:**
- `ghcr.io/vegardengen/unifi-network-operator:main` - Latest from main branch
- `ghcr.io/vegardengen/unifi-network-operator:feature-xyz` - Feature branch builds
- `ghcr.io/vegardengen/unifi-network-operator:v1.0.0` - Version tags
- `ghcr.io/vegardengen/unifi-network-operator:latest` - Latest stable release
### 2. Helm Chart Release (`helm-release.yaml`)
**Triggers:**
- Push to `main` branch with changes in `helm/` directory
- Manual dispatch
**What it does:**
- Packages the Helm chart
- Creates GitHub releases for chart versions
- Publishes chart to GitHub Pages
- Updates the Helm repository index
**Chart repository:** https://vegardengen.github.io/unifi-network-operator
### 3. Full Release (`release.yaml`)
**Triggers:**
- Push of version tags (e.g., `v1.0.0`, `v1.2.3`)
- Manual dispatch with version input
**What it does:**
1. Builds and pushes multi-arch Docker images
2. Updates Chart.yaml and values.yaml with release version
3. Packages and releases Helm chart
4. Creates GitHub release with release notes
5. Attaches Helm chart package to release
**Pre-release detection:** Automatically marks releases as pre-release if tag contains `alpha`, `beta`, or `rc`
### 4. PR Validation (`pr-validation.yaml`)
**Triggers:**
- Pull requests to `main` branch
- Manual dispatch
**What it does:**
- Validates Go code formatting
- Runs `go vet`
- Executes tests with race detection
- Uploads coverage to Codecov
- Lints Helm chart
- Validates rendered Kubernetes manifests
- Test builds Docker image
## Setup Requirements
### 1. Enable GitHub Pages
1. Go to repository Settings → Pages
2. Source: Deploy from a branch
3. Branch: `gh-pages` / `/ (root)`
4. Save
The Helm chart will be available at: https://vegardengen.github.io/unifi-network-operator
### 2. Enable GitHub Packages
GitHub Container Registry is enabled by default. Images are automatically pushed to:
`ghcr.io/vegardengen/unifi-network-operator`
To pull images:
```bash
docker pull ghcr.io/vegardengen/unifi-network-operator:latest
```
### 3. Configure Secrets (Optional)
The workflows use `GITHUB_TOKEN` which is automatically provided. Additional secrets you might want to add:
- `CODECOV_TOKEN` - For uploading coverage reports (optional)
### 4. Branch Protection (Recommended)
Configure branch protection for `main`:
1. Go to Settings → Branches → Branch protection rules
2. Add rule for `main`
3. Enable:
- Require pull request reviews
- Require status checks to pass (select PR Validation workflow)
- Require branches to be up to date
## Usage
### Creating a Release
#### Method 1: Using Git Tags (Recommended)
```bash
# Create and push a version tag
git tag -a v1.0.0 -m "Release v1.0.0"
git push github v1.0.0
```
This automatically:
1. Builds Docker images for `v1.0.0` and `latest`
2. Packages Helm chart with version `1.0.0`
3. Creates GitHub release
4. Publishes to Helm repository
#### Method 2: Manual Dispatch
1. Go to Actions → Release workflow
2. Click "Run workflow"
3. Enter the version tag (e.g., `v1.0.0`)
4. Click "Run workflow"
### Installing from the Helm Repository
Once the release workflow completes:
```bash
# Add the Helm repository
helm repo add unifi-network-operator https://vegardengen.github.io/unifi-network-operator
# Update repository cache
helm repo update
# Install the operator
helm install unifi-network-operator unifi-network-operator/unifi-network-operator \
--namespace unifi-network-operator-system \
--create-namespace \
--set unifi.url="https://your-unifi-controller:8443" \
--set unifi.password="your-password"
```
### Using Development Builds
Feature branch builds are automatically pushed:
```bash
# Use a specific feature branch build
helm install unifi-network-operator ./helm/unifi-network-operator \
--set image.repository=ghcr.io/vegardengen/unifi-network-operator \
--set image.tag=feature-xyz
```
## Workflow Files
- [`docker-build-push.yaml`](workflows/docker-build-push.yaml) - Docker image CI/CD
- [`helm-release.yaml`](workflows/helm-release.yaml) - Helm chart publishing
- [`release.yaml`](workflows/release.yaml) - Complete release process
- [`pr-validation.yaml`](workflows/pr-validation.yaml) - PR checks
- [`cr.yaml`](cr.yaml) - Chart Releaser configuration
## Versioning Strategy
### Docker Images
- `latest` - Latest stable release from main branch
- `vX.Y.Z` - Specific version tag
- `X.Y.Z` - Version without 'v' prefix
- `X.Y` - Major.minor version
- `X` - Major version only
- `main` - Latest commit on main branch
- `feature-name` - Feature branch builds
### Helm Charts
- Chart version follows semantic versioning (X.Y.Z)
- AppVersion matches Docker image tag
- Both are automatically updated during release
## Troubleshooting
### Docker Build Fails
Check:
- Dockerfile syntax
- Go dependencies in go.mod
- Build context includes all necessary files
### Helm Release Fails
Check:
- Chart.yaml is valid
- All template files are valid YAML
- No syntax errors in templates
- Version in Chart.yaml is unique
### GitHub Pages Not Updating
1. Check workflow completed successfully
2. Verify `gh-pages` branch exists
3. Check Pages is enabled in repository settings
4. Wait a few minutes for CDN propagation
### Images Not Accessible
Public images require:
1. Repository → Settings → Packages
2. Find the package
3. Package settings → Change visibility → Public
## Best Practices
1. **Always test locally first:**
```bash
make helm-lint
make helm-template
docker build -t test .
```
2. **Use semantic versioning:**
- Major (X): Breaking changes
- Minor (Y): New features, backward compatible
- Patch (Z): Bug fixes
3. **Create release notes:**
- Describe what changed
- Highlight breaking changes
- Document upgrade path
4. **Test releases in a dev environment:**
- Use pre-release tags (`v1.0.0-beta1`)
- Validate before promoting to stable
## Monitoring
### Check Workflow Status
- Go to repository → Actions
- View workflow runs
- Check logs for failures
### View Published Artifacts
- **Docker images:** https://github.com/vegardengen/unifi-network-operator/pkgs/container/unifi-network-operator
- **Helm charts:** https://github.com/vegardengen/unifi-network-operator/releases
- **Chart repository:** https://vegardengen.github.io/unifi-network-operator
## Support
For issues with workflows:
1. Check the Actions tab for detailed logs
2. Review the workflow YAML files
3. Consult GitHub Actions documentation
4. Open an issue in the repository

244
.github/SETUP.md vendored Normal file
View File

@@ -0,0 +1,244 @@
# GitHub Actions Setup Guide
Quick guide to get the CI/CD workflows running for the UniFi Network Operator.
## Prerequisites
- Repository pushed to GitHub
- Admin access to the repository
## Step-by-Step Setup
### 1. Enable GitHub Container Registry
Images will be pushed to `ghcr.io/vegardengen/unifi-network-operator`
**Make the package public (after first push):**
1. Go to your GitHub profile → Packages
2. Find `unifi-network-operator`
3. Package settings → Change visibility → Public
4. Confirm by typing the package name
### 2. Enable GitHub Pages
**Set up GitHub Pages for Helm chart hosting:**
1. Go to repository **Settings****Pages**
2. Under "Build and deployment":
- **Source:** Deploy from a branch
- **Branch:** `gh-pages` / `/ (root)`
- Click **Save**
3. Wait for initial deployment (workflow will create the branch)
Your Helm repository will be available at:
```
https://vegardengen.github.io/unifi-network-operator
```
### 3. Configure Repository Permissions
**Allow workflows to create releases:**
1. Go to **Settings****Actions****General**
2. Scroll to "Workflow permissions"
3. Select **Read and write permissions**
4. Check **Allow GitHub Actions to create and approve pull requests**
5. Click **Save**
### 4. Set Up Branch Protection (Optional but Recommended)
**Protect the main branch:**
1. Go to **Settings****Branches**
2. Click **Add branch protection rule**
3. Branch name pattern: `main`
4. Enable:
- ☑ Require a pull request before merging
- ☑ Require status checks to pass before merging
- Search and select: `lint-and-test`, `helm-lint`, `docker-build`
- ☑ Require branches to be up to date before merging
5. Click **Create** or **Save changes**
### 5. Test the Workflows
**Test PR validation:**
```bash
# Create a test branch
git checkout -b test-workflows
# Make a small change
echo "# Test" >> README.md
# Commit and push
git add README.md
git commit -m "Test workflows"
git push github test-workflows
# Create a PR on GitHub
# Check Actions tab to see PR validation running
```
**Test Docker build:**
```bash
# Push to main branch (after PR is merged)
git checkout main
git pull github main
git push github main
# Check Actions → Docker Build and Push workflow
```
**Test full release:**
```bash
# Create and push a version tag
git tag -a v0.1.0 -m "First release"
git push github v0.1.0
# Check Actions → Release workflow
# This will:
# 1. Build Docker images
# 2. Package Helm chart
# 3. Create GitHub release
# 4. Publish to Helm repository
```
### 6. Verify Everything Works
**Check Docker image:**
```bash
# Pull the image
docker pull ghcr.io/vegardengen/unifi-network-operator:v0.1.0
# Verify it works
docker run --rm ghcr.io/vegardengen/unifi-network-operator:v0.1.0 --version
```
**Check Helm repository:**
```bash
# Add the Helm repo
helm repo add unifi-network-operator https://vegardengen.github.io/unifi-network-operator
# Update
helm repo update
# Search for charts
helm search repo unifi-network-operator
# Show chart info
helm show chart unifi-network-operator/unifi-network-operator
```
## Optional: Add Codecov Integration
**For test coverage reports:**
1. Go to https://codecov.io
2. Sign in with GitHub
3. Add your repository
4. Copy the token
5. Go to repository **Settings****Secrets and variables****Actions**
6. Click **New repository secret**
- Name: `CODECOV_TOKEN`
- Value: [paste token]
7. Click **Add secret**
## Troubleshooting
### Workflow Fails with "Resource not accessible by integration"
**Fix:** Enable read and write permissions (see Step 3 above)
### Docker Image Push Fails with "Permission denied"
**Fix:**
1. Go to package settings
2. Add repository access
3. Or change package visibility to public
### Helm Chart Not Appearing on GitHub Pages
**Check:**
1. `gh-pages` branch was created
2. Pages is enabled in settings
3. Workflow completed successfully
4. Wait 5-10 minutes for CDN
**Manually create gh-pages branch if needed:**
```bash
git checkout --orphan gh-pages
git rm -rf .
echo "# Helm Charts" > README.md
git add README.md
git commit -m "Initialize gh-pages"
git push github gh-pages
```
### Release Workflow Fails
**Common issues:**
- Chart version already exists → Bump version in Chart.yaml
- Invalid YAML → Run `make helm-lint` locally first
- Missing permissions → Check Step 3
## Next Steps
Once everything is working:
1. **Update README.md** with installation instructions:
```markdown
## Installation
### Using Helm
```bash
helm repo add unifi-network-operator https://vegardengen.github.io/unifi-network-operator
helm repo update
helm install unifi-network-operator unifi-network-operator/unifi-network-operator \
--namespace unifi-network-operator-system \
--create-namespace \
--set unifi.url="https://your-controller:8443" \
--set unifi.password="your-password"
```
```
2. **Add badges to README.md:**
```markdown
![Build Status](https://github.com/vegardengen/unifi-network-operator/workflows/Build%20and%20Push%20Docker%20Image/badge.svg)
![Helm Release](https://github.com/vegardengen/unifi-network-operator/workflows/Release%20Helm%20Chart/badge.svg)
```
3. **Create your first official release:**
```bash
git tag -a v0.1.0 -m "Initial release"
git push github v0.1.0
```
4. **Monitor the Actions tab** to ensure everything completes successfully
## Workflow Files Summary
| File | Purpose | Trigger |
|------|---------|---------|
| `docker-build-push.yaml` | Build and push Docker images | Push to main, tags, PRs |
| `helm-release.yaml` | Publish Helm chart to GitHub Pages | Push to main (helm changes) |
| `release.yaml` | Complete release process | Version tags (v*) |
| `pr-validation.yaml` | Validate PRs | Pull requests to main |
## Getting Help
- **GitHub Actions Docs:** https://docs.github.com/en/actions
- **Helm Chart Releaser:** https://github.com/helm/chart-releaser-action
- **GitHub Container Registry:** https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-container-registry
## Configuration Files
- [`.github/cr.yaml`](cr.yaml) - Chart Releaser configuration
- [`.github/README.md`](README.md) - Detailed workflow documentation
- [`workflows/`](workflows/) - All workflow definitions

6
.github/cr.yaml vendored Normal file
View File

@@ -0,0 +1,6 @@
# Chart Releaser configuration
owner: vegardengen
git-repo: unifi-network-operator
charts-repo-url: https://vegardengen.github.io/unifi-network-operator
# Skip packaging if the chart version already exists
skip-existing: true

View File

@@ -0,0 +1,92 @@
name: Build and Push Docker Image
on:
push:
branches:
- main
- 'feature/**'
tags:
- 'v*'
pull_request:
branches:
- main
workflow_dispatch:
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
build-and-push:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
id-token: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version-file: 'go.mod'
cache: true
- name: Run tests
run: |
go test -v ./... -coverprofile=coverage.out
go tool cover -func=coverage.out
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to Container Registry
if: github.event_name != 'pull_request'
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v5
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=semver,pattern={{major}}
type=sha,prefix={{branch}}-
type=raw,value=latest,enable={{is_default_branch}}
- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
context: .
file: ./Dockerfile
platforms: linux/amd64,linux/arm64
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
build-args: |
VERSION=${{ github.ref_name }}
COMMIT=${{ github.sha }}
BUILD_DATE=${{ github.event.head_commit.timestamp }}
- name: Upload coverage reports
if: github.event_name == 'pull_request'
uses: actions/upload-artifact@v4
with:
name: coverage-report
path: coverage.out
retention-days: 7

65
.github/workflows/helm-release.yaml vendored Normal file
View File

@@ -0,0 +1,65 @@
name: Release Helm Chart
on:
push:
branches:
- main
paths:
- 'helm/unifi-network-operator/**'
- '.github/workflows/helm-release.yaml'
workflow_dispatch:
permissions:
contents: write
pages: write
id-token: write
jobs:
release:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Configure Git
run: |
git config user.name "$GITHUB_ACTOR"
git config user.email "$GITHUB_ACTOR@users.noreply.github.com"
- name: Install Helm
uses: azure/setup-helm@v4
with:
version: v3.14.0
- name: Run chart-releaser
uses: helm/chart-releaser-action@v1.6.0
with:
charts_dir: helm
config: .github/cr.yaml
env:
CR_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
CR_SKIP_EXISTING: true
publish-pages:
needs: release
runs-on: ubuntu-latest
steps:
- name: Checkout gh-pages
uses: actions/checkout@v4
with:
ref: gh-pages
path: gh-pages
- name: Setup Pages
uses: actions/configure-pages@v4
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: ./gh-pages
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4

90
.github/workflows/pr-validation.yaml vendored Normal file
View File

@@ -0,0 +1,90 @@
name: PR Validation
on:
pull_request:
branches:
- main
workflow_dispatch:
jobs:
lint-and-test:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version-file: 'go.mod'
cache: true
- name: Run go fmt
run: |
if [ -n "$(gofmt -s -l .)" ]; then
echo "Go code is not formatted:"
gofmt -s -d .
exit 1
fi
- name: Run go vet
run: go vet ./...
- name: Run tests
run: go test -v -race -coverprofile=coverage.out ./...
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v4
with:
file: ./coverage.out
fail_ci_if_error: false
helm-lint:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install Helm
uses: azure/setup-helm@v4
with:
version: v3.14.0
- name: Lint Helm chart
run: |
helm lint helm/unifi-network-operator \
--set unifi.url="https://test.local" \
--set unifi.password="test"
- name: Template Helm chart
run: |
helm template test-release helm/unifi-network-operator \
--namespace test \
--set unifi.url="https://test.local" \
--set unifi.password="test" \
> /tmp/rendered.yaml
- name: Validate rendered manifests
run: |
# Check that the rendered output is valid YAML
kubectl --dry-run=client apply -f /tmp/rendered.yaml
docker-build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build Docker image (test only)
uses: docker/build-push-action@v5
with:
context: .
file: ./Dockerfile
platforms: linux/amd64
push: false
tags: test:latest
cache-from: type=gha
cache-to: type=gha,mode=max

222
.github/workflows/release.yaml vendored Normal file
View File

@@ -0,0 +1,222 @@
name: Release
on:
push:
tags:
- 'v*.*.*'
workflow_dispatch:
inputs:
tag:
description: 'Tag to release (e.g., v1.0.0)'
required: true
type: string
permissions:
contents: write
packages: write
pages: write
id-token: write
jobs:
# Build and push multi-arch Docker images
build-images:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version-file: 'go.mod'
- name: Run tests
run: go test -v ./...
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract version
id: version
run: |
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
VERSION="${{ github.event.inputs.tag }}"
else
VERSION="${GITHUB_REF#refs/tags/}"
fi
echo "version=${VERSION}" >> $GITHUB_OUTPUT
echo "version_no_v=${VERSION#v}" >> $GITHUB_OUTPUT
- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
context: .
file: ./Dockerfile
platforms: linux/amd64,linux/arm64
push: true
tags: |
ghcr.io/${{ github.repository }}:${{ steps.version.outputs.version }}
ghcr.io/${{ github.repository }}:${{ steps.version.outputs.version_no_v }}
ghcr.io/${{ github.repository }}:latest
labels: |
org.opencontainers.image.source=${{ github.event.repository.html_url }}
org.opencontainers.image.revision=${{ github.sha }}
org.opencontainers.image.version=${{ steps.version.outputs.version }}
cache-from: type=gha
cache-to: type=gha,mode=max
# Package and release Helm chart
release-chart:
needs: build-images
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Configure Git
run: |
git config user.name "$GITHUB_ACTOR"
git config user.email "$GITHUB_ACTOR@users.noreply.github.com"
- name: Install Helm
uses: azure/setup-helm@v4
with:
version: v3.14.0
- name: Extract version
id: version
run: |
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
VERSION="${{ github.event.inputs.tag }}"
else
VERSION="${GITHUB_REF#refs/tags/}"
fi
VERSION_NO_V="${VERSION#v}"
echo "version=${VERSION}" >> $GITHUB_OUTPUT
echo "version_no_v=${VERSION_NO_V}" >> $GITHUB_OUTPUT
- name: Update Chart.yaml version and appVersion
run: |
sed -i "s/^version:.*/version: ${{ steps.version.outputs.version_no_v }}/" helm/unifi-network-operator/Chart.yaml
sed -i "s/^appVersion:.*/appVersion: \"${{ steps.version.outputs.version }}\"/" helm/unifi-network-operator/Chart.yaml
- name: Update values.yaml image tag
run: |
sed -i "s/tag: \".*\"/tag: \"${{ steps.version.outputs.version }}\"/" helm/unifi-network-operator/values.yaml
sed -i "s|repository: .*|repository: ghcr.io/${{ github.repository }}|" helm/unifi-network-operator/values.yaml
- name: Package Helm chart
run: |
mkdir -p .cr-release-packages
helm package helm/unifi-network-operator -d .cr-release-packages
- name: Run chart-releaser
uses: helm/chart-releaser-action@v1.6.0
with:
charts_dir: helm
skip_packaging: true
config: .github/cr.yaml
env:
CR_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
- name: Upload Helm chart as artifact
uses: actions/upload-artifact@v4
with:
name: helm-chart
path: .cr-release-packages/*.tgz
retention-days: 90
# Create GitHub Release
create-release:
needs: [build-images, release-chart]
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Extract version
id: version
run: |
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
VERSION="${{ github.event.inputs.tag }}"
else
VERSION="${GITHUB_REF#refs/tags/}"
fi
echo "version=${VERSION}" >> $GITHUB_OUTPUT
- name: Download Helm chart artifact
uses: actions/download-artifact@v4
with:
name: helm-chart
path: ./artifacts
- name: Generate release notes
id: notes
run: |
cat > release_notes.md << 'EOF'
## UniFi Network Operator ${{ steps.version.outputs.version }}
### Installation
#### Using Helm
```bash
helm repo add unifi-network-operator https://vegardengen.github.io/unifi-network-operator
helm repo update
helm install unifi-network-operator unifi-network-operator/unifi-network-operator \
--namespace unifi-network-operator-system \
--create-namespace \
--set unifi.url="https://your-unifi-controller:8443" \
--set unifi.password="your-password"
```
#### Using Docker
```bash
docker pull ghcr.io/${{ github.repository }}:${{ steps.version.outputs.version }}
```
### What's Changed
See the full changelog for details of changes in this release.
### Container Images
- `ghcr.io/${{ github.repository }}:${{ steps.version.outputs.version }}`
- Available for `linux/amd64` and `linux/arm64`
### Helm Chart
- Chart version: Automatically generated
- App version: ${{ steps.version.outputs.version }}
- Repository: https://vegardengen.github.io/unifi-network-operator
EOF
cat release_notes.md
- name: Create GitHub Release
uses: softprops/action-gh-release@v1
with:
tag_name: ${{ steps.version.outputs.version }}
name: Release ${{ steps.version.outputs.version }}
body_path: release_notes.md
draft: false
prerelease: ${{ contains(steps.version.outputs.version, 'alpha') || contains(steps.version.outputs.version, 'beta') || contains(steps.version.outputs.version, 'rc') }}
files: |
./artifacts/*.tgz
token: ${{ secrets.GITHUB_TOKEN }}

399
CICD.md Normal file
View File

@@ -0,0 +1,399 @@
# CI/CD Pipeline Documentation
This document describes the continuous integration and deployment pipeline for the UniFi Network Operator.
## Overview
The CI/CD pipeline is built using GitHub Actions and provides:
- **Automated testing** on every pull request
- **Multi-architecture Docker image builds** (amd64, arm64)
- **Automated Helm chart releases** to GitHub Pages
- **Complete release automation** with version tagging
- **Public Docker images** via GitHub Container Registry
## Quick Start
### For Users
**Install the operator using Helm:**
```bash
# Add the Helm repository
helm repo add unifi-network-operator https://vegardengen.github.io/unifi-network-operator
helm repo update
# Install
helm install unifi-network-operator unifi-network-operator/unifi-network-operator \
--namespace unifi-network-operator-system \
--create-namespace \
--set unifi.url="https://your-unifi-controller:8443" \
--set unifi.password="your-password"
```
**Or use Docker directly:**
```bash
docker pull ghcr.io/vegardengen/unifi-network-operator:latest
```
### For Contributors
**Run checks locally before pushing:**
```bash
# Format code
make fmt
# Run linters
make vet
# Run tests
make test
# Lint Helm chart
make helm-lint
# Test Docker build
docker build -t test .
```
## Architecture
```
┌─────────────────────────────────────────────────────────────────┐
│ GitHub Repository │
│ vegardengen/unifi-network-operator │
└─────────────────────────────────────────────────────────────────┘
┌────────────────┼────────────────┐
│ │ │
▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌─────────────┐
│ Pull Request │ │ Push to Main │ │ Tag Push │
│ Validation │ │ │ │ (v*.*) │
└──────────────┘ └──────────────┘ └─────────────┘
│ │ │
▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌─────────────┐
│ • Go Fmt │ │ Docker Build │ │ Release │
│ • Go Vet │ │ & Push │ │ Workflow │
│ • Tests │ │ │ │ │
│ • Helm │ │ Helm Chart │ │ • Docker │
│ Lint │ │ Release │ │ • Helm │
│ • Docker │ │ │ │ • GitHub │
│ Build │ │ │ │ Release │
└──────────────┘ └──────────────┘ └─────────────┘
│ │
▼ ▼
┌───────────────────────────┐
│ GitHub Container Registry │
│ ghcr.io/vegardengen/... │
└───────────────────────────┘
┌───────────────────────────┐
│ GitHub Pages (Helm) │
│ vegardengen.github.io/ │
└───────────────────────────┘
```
## Workflows
### 1. PR Validation (`pr-validation.yaml`)
**Triggers:** Pull requests to `main`
**Steps:**
1. Code formatting check (`go fmt`)
2. Static analysis (`go vet`)
3. Unit tests with race detection
4. Coverage upload to Codecov
5. Helm chart linting
6. Template rendering validation
7. Test Docker build
**Purpose:** Ensure code quality before merging
### 2. Docker Build & Push (`docker-build-push.yaml`)
**Triggers:**
- Push to `main` or `feature/**` branches
- Push of tags starting with `v*`
- Pull requests (build only, no push)
**Steps:**
1. Run tests
2. Set up QEMU for cross-compilation
3. Set up Docker Buildx
4. Extract metadata for tags
5. Build for multiple architectures
6. Push to GitHub Container Registry
**Image Tags Created:**
- Branch builds: `main`, `feature-xyz`
- Version tags: `v1.0.0`, `1.0.0`, `1.0`, `1`
- Latest: `latest` (from main branch)
- Commit SHA: `main-abc1234`
### 3. Helm Chart Release (`helm-release.yaml`)
**Triggers:**
- Push to `main` with changes in `helm/` directory
- Manual workflow dispatch
**Steps:**
1. Package Helm chart
2. Create GitHub release for chart
3. Update Helm repository index
4. Publish to GitHub Pages
**Output:** Helm repository at `https://vegardengen.github.io/unifi-network-operator`
### 4. Complete Release (`release.yaml`)
**Triggers:**
- Push of version tags (e.g., `v1.0.0`)
- Manual workflow dispatch with version input
**Steps:**
1. **Build Phase:**
- Run tests
- Build multi-arch Docker images
- Push with version tags and `latest`
2. **Chart Phase:**
- Update Chart.yaml with version
- Update values.yaml with image tag
- Package Helm chart
- Release chart to repository
3. **Release Phase:**
- Generate release notes
- Create GitHub release
- Attach Helm chart package
- Mark as pre-release if needed
**Pre-release Detection:** Tags containing `alpha`, `beta`, or `rc` are marked as pre-releases
## Release Process
### Creating a New Release
1. **Prepare the release:**
```bash
# Ensure you're on main and up to date
git checkout main
git pull github main
# Update CHANGELOG.md with release notes
# Commit any final changes
```
2. **Create and push the tag:**
```bash
# Create an annotated tag
git tag -a v1.0.0 -m "Release v1.0.0: Description of changes"
# Push the tag
git push github v1.0.0
```
3. **Monitor the release:**
- Go to Actions tab on GitHub
- Watch the "Release" workflow
- Check for any errors
4. **Verify the release:**
```bash
# Check Docker image
docker pull ghcr.io/vegardengen/unifi-network-operator:v1.0.0
# Check Helm chart
helm repo update
helm search repo unifi-network-operator
# Check GitHub release page
# https://github.com/vegardengen/unifi-network-operator/releases
```
### Version Numbering
Follow [Semantic Versioning](https://semver.org/):
- **MAJOR** (X.0.0): Breaking changes
- **MINOR** (0.X.0): New features, backward compatible
- **PATCH** (0.0.X): Bug fixes, backward compatible
**Pre-release tags:**
- `v1.0.0-alpha.1` - Early preview
- `v1.0.0-beta.1` - Feature complete, testing
- `v1.0.0-rc.1` - Release candidate
## Artifact Locations
### Docker Images
**Repository:** `ghcr.io/vegardengen/unifi-network-operator`
**Access:**
```bash
# Pull latest
docker pull ghcr.io/vegardengen/unifi-network-operator:latest
# Pull specific version
docker pull ghcr.io/vegardengen/unifi-network-operator:v1.0.0
```
**Platforms:** `linux/amd64`, `linux/arm64`
### Helm Charts
**Repository:** `https://vegardengen.github.io/unifi-network-operator`
**Access:**
```bash
# Add repository
helm repo add unifi-network-operator https://vegardengen.github.io/unifi-network-operator
# Search charts
helm search repo unifi-network-operator
# Install
helm install my-release unifi-network-operator/unifi-network-operator
```
**Also available:** As attachments on GitHub Releases
## Configuration
### Repository Settings Required
1. **Actions Permissions:**
- Settings → Actions → General
- Workflow permissions: Read and write
- Allow GitHub Actions to create releases: ✓
2. **GitHub Pages:**
- Settings → Pages
- Source: Deploy from branch
- Branch: `gh-pages` / `/ (root)`
3. **Package Visibility (After First Push):**
- Profile → Packages → unifi-network-operator
- Package settings → Change visibility → Public
### Branch Protection (Recommended)
- Settings → Branches → Add rule for `main`
- Require pull request reviews
- Require status checks: `lint-and-test`, `helm-lint`, `docker-build`
- Require branches to be up to date
## Troubleshooting
### Common Issues
**"Resource not accessible by integration"**
- Fix: Enable read/write permissions in repository settings
**Docker push fails**
- Check package visibility settings
- Verify GITHUB_TOKEN permissions
**Helm chart not updating**
- Ensure gh-pages branch exists
- Check GitHub Pages is enabled
- Wait 5-10 minutes for CDN propagation
**Release workflow fails**
- Check Chart.yaml version is unique
- Verify all templates are valid YAML
- Review workflow logs for specific error
### Debug Locally
```bash
# Test Helm rendering
make helm-template
# Lint Helm chart
make helm-lint
# Build Docker image
docker build -t test:latest .
# Run tests
make test
# Check formatting
make fmt
make vet
```
## Monitoring
### Workflow Status
Check at: https://github.com/vegardengen/unifi-network-operator/actions
### Artifacts
- **Docker Images:** https://github.com/vegardengen/unifi-network-operator/pkgs/container/unifi-network-operator
- **Releases:** https://github.com/vegardengen/unifi-network-operator/releases
- **Helm Repository:** https://vegardengen.github.io/unifi-network-operator
### Metrics
- Build success rate
- Test coverage (via Codecov)
- Release frequency
- Download statistics (via GitHub Insights)
## Security
### Container Scanning
Consider adding:
- Trivy vulnerability scanning
- Dependabot alerts
- SBOM generation
### Secrets Management
- Use GitHub Secrets for sensitive data
- Never commit credentials
- Rotate tokens regularly
### Supply Chain Security
- Images built from source
- Signed releases (future enhancement)
- SBOM attached to releases (future enhancement)
## Future Enhancements
- [ ] Automated vulnerability scanning
- [ ] Signed container images (cosign)
- [ ] SBOM generation
- [ ] Automated changelog generation
- [ ] Release drafter for draft releases
- [ ] Automated version bumping
- [ ] Integration tests in CI
- [ ] Performance benchmarking
- [ ] Automated security scanning
## References
- [GitHub Actions Documentation](https://docs.github.com/en/actions)
- [Helm Chart Best Practices](https://helm.sh/docs/chart_best_practices/)
- [Container Best Practices](https://docs.docker.com/develop/dev-best-practices/)
- [Semantic Versioning](https://semver.org/)
## Support
For CI/CD issues:
1. Check workflow logs in Actions tab
2. Review [.github/README.md](.github/README.md) for detailed docs
3. See [.github/SETUP.md](.github/SETUP.md) for setup instructions
4. Open an issue with workflow logs attached

View File

@@ -4,13 +4,15 @@ description: A Kubernetes operator for managing UniFi network configurations
type: application
version: 0.1.0
appVersion: "latest"
home: https://github.com/yourusername/unifi-network-operator
home: https://github.com/vegardengen/unifi-network-operator
maintainers:
- name: Vegar Dengen
url: https://github.com/vegardengen
keywords:
- unifi
- network
- operator
- firewall
- ubiquiti
sources:
- https://github.com/yourusername/unifi-network-operator
- https://github.com/vegardengen/unifi-network-operator

View File

@@ -5,7 +5,7 @@ replicaCount: 1
image:
# -- Container image repository
repository: gitea.engen.priv.no/klauvsteinen/unifi-network-operator-controller
repository: ghcr.io/vegardengen/unifi-network-operator
# -- Image pull policy
pullPolicy: IfNotPresent
# -- Overrides the image tag whose default is the chart appVersion