Skip to content

Commit 83a1f48

Browse files
stubbiclaude
andcommitted
feat: initial Paperclip Kubernetes operator
Kubernetes operator for deploying and managing Paperclip instances - the open-source AI agent orchestration platform. Includes: - PaperclipInstance CRD (paperclip.paperclip.ai/v1alpha1) with ~30 configuration sections covering image, database, auth, storage, networking, security, scaling, observability, and backup - Pure resource builders for StatefulSet, Service, Database, PVC, Ingress, NetworkPolicy, RBAC, HPA, and PDB - Full reconciliation controller using controllerutil.CreateOrUpdate - Managed PostgreSQL mode with auto-generated credentials - Helm chart for operator deployment - GitHub Actions CI/CD (lint, test, security scan, build, release) - 18 passing unit tests for all resource builders - Sample CRs for basic and production deployments Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
0 parents  commit 83a1f48

80 files changed

Lines changed: 15410 additions & 0 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.devcontainer/devcontainer.json

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{
2+
"name": "Kubebuilder DevContainer",
3+
"image": "golang:1.24",
4+
"features": {
5+
"ghcr.io/devcontainers/features/docker-in-docker:2": {},
6+
"ghcr.io/devcontainers/features/git:1": {}
7+
},
8+
9+
"runArgs": ["--network=host"],
10+
11+
"customizations": {
12+
"vscode": {
13+
"settings": {
14+
"terminal.integrated.shell.linux": "/bin/bash"
15+
},
16+
"extensions": [
17+
"ms-kubernetes-tools.vscode-kubernetes-tools",
18+
"ms-azuretools.vscode-docker"
19+
]
20+
}
21+
},
22+
23+
"onCreateCommand": "bash .devcontainer/post-install.sh"
24+
}
25+

.devcontainer/post-install.sh

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#!/bin/bash
2+
set -x
3+
4+
curl -Lo ./kind https://kind.sigs.k8s.io/dl/latest/kind-linux-amd64
5+
chmod +x ./kind
6+
mv ./kind /usr/local/bin/kind
7+
8+
curl -L -o kubebuilder https://go.kubebuilder.io/dl/latest/linux/amd64
9+
chmod +x kubebuilder
10+
mv kubebuilder /usr/local/bin/
11+
12+
KUBECTL_VERSION=$(curl -L -s https://dl.k8s.io/release/stable.txt)
13+
curl -LO "https://dl.k8s.io/release/$KUBECTL_VERSION/bin/linux/amd64/kubectl"
14+
chmod +x kubectl
15+
mv kubectl /usr/local/bin/kubectl
16+
17+
docker network create -d=bridge --subnet=172.19.0.0/24 kind
18+
19+
kind version
20+
kubebuilder version
21+
docker --version
22+
go version
23+
kubectl version --client

.dockerignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# More info: https://docs.docker.com/engine/reference/builder/#dockerignore-file
2+
# Ignore build and test binaries.
3+
bin/

.github/workflows/ci.yaml

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
9+
permissions:
10+
contents: read
11+
12+
jobs:
13+
lint:
14+
name: Lint
15+
runs-on: ubuntu-latest
16+
steps:
17+
- uses: actions/checkout@v4
18+
- uses: actions/setup-go@v5
19+
with:
20+
go-version-file: go.mod
21+
- uses: golangci/golangci-lint-action@v6
22+
with:
23+
version: v2.1.0
24+
args: --timeout=5m
25+
26+
reconcile-guard:
27+
name: Reconcile Guard
28+
runs-on: ubuntu-latest
29+
steps:
30+
- uses: actions/checkout@v4
31+
- name: Check for bare r.Update/r.Create on managed resources
32+
run: |
33+
# Find bare r.Update() or r.Create() calls that are NOT on the CR itself
34+
# and do NOT have a reconcile-guard:allow comment
35+
if grep -rn 'r\.Update\|r\.Create' internal/controller/ \
36+
| grep -v 'reconcile-guard:allow' \
37+
| grep -v '_test\.go' \
38+
| grep -v 'r\.Status()' \
39+
| grep -v 'r\.Recorder' \
40+
| grep -v 'controllerutil\.CreateOrUpdate' \
41+
| grep -v 'ensureDatabaseSecret'; then
42+
echo "ERROR: Found bare r.Update()/r.Create() calls on managed resources."
43+
echo "Use controllerutil.CreateOrUpdate instead, or add '// reconcile-guard:allow' comment."
44+
exit 1
45+
fi
46+
echo "Reconcile guard check passed."
47+
48+
test:
49+
name: Test
50+
runs-on: ubuntu-latest
51+
steps:
52+
- uses: actions/checkout@v4
53+
- uses: actions/setup-go@v5
54+
with:
55+
go-version-file: go.mod
56+
- name: Run tests
57+
run: make test
58+
59+
security-scan:
60+
name: Security Scan
61+
runs-on: ubuntu-latest
62+
steps:
63+
- uses: actions/checkout@v4
64+
- uses: actions/setup-go@v5
65+
with:
66+
go-version-file: go.mod
67+
- name: Run gosec
68+
uses: securego/gosec@master
69+
with:
70+
args: ./...
71+
- name: Run Trivy
72+
uses: aquasecurity/trivy-action@master
73+
with:
74+
scan-type: fs
75+
severity: CRITICAL,HIGH
76+
77+
build:
78+
name: Build
79+
runs-on: ubuntu-latest
80+
needs: [lint, test]
81+
steps:
82+
- uses: actions/checkout@v4
83+
- uses: actions/setup-go@v5
84+
with:
85+
go-version-file: go.mod
86+
- name: Build binary
87+
run: make build
88+
- name: Build Docker image
89+
run: make docker-build IMG=ghcr.io/paperclipai/k8s-operator:ci-${{ github.sha }}

.github/workflows/lint.yml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
name: Lint
2+
3+
on:
4+
push:
5+
pull_request:
6+
7+
jobs:
8+
lint:
9+
name: Run on Ubuntu
10+
runs-on: ubuntu-latest
11+
steps:
12+
- name: Clone the code
13+
uses: actions/checkout@v4
14+
15+
- name: Setup Go
16+
uses: actions/setup-go@v5
17+
with:
18+
go-version-file: go.mod
19+
20+
- name: Run linter
21+
uses: golangci/golangci-lint-action@v8
22+
with:
23+
version: v2.1.0

.github/workflows/release.yaml

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
name: Release
2+
3+
on:
4+
push:
5+
tags:
6+
- 'v*'
7+
8+
permissions:
9+
contents: write
10+
packages: write
11+
id-token: write
12+
13+
jobs:
14+
release:
15+
name: Release
16+
runs-on: ubuntu-latest
17+
steps:
18+
- uses: actions/checkout@v4
19+
with:
20+
fetch-depth: 0
21+
22+
- uses: actions/setup-go@v5
23+
with:
24+
go-version-file: go.mod
25+
26+
- name: Login to GHCR
27+
uses: docker/login-action@v3
28+
with:
29+
registry: ghcr.io
30+
username: ${{ github.actor }}
31+
password: ${{ secrets.GITHUB_TOKEN }}
32+
33+
- name: Set up Docker Buildx
34+
uses: docker/setup-buildx-action@v3
35+
36+
- name: Build and push multi-arch image
37+
uses: docker/build-push-action@v6
38+
with:
39+
context: .
40+
platforms: linux/amd64,linux/arm64
41+
push: true
42+
tags: |
43+
ghcr.io/paperclipai/k8s-operator:${{ github.ref_name }}
44+
ghcr.io/paperclipai/k8s-operator:latest
45+
46+
- name: Install Cosign
47+
uses: sigstore/cosign-installer@v3
48+
49+
- name: Sign image
50+
run: |
51+
cosign sign --yes ghcr.io/paperclipai/k8s-operator:${{ github.ref_name }}
52+
53+
- name: Create GitHub Release
54+
uses: softprops/action-gh-release@v2
55+
with:
56+
generate_release_notes: true

.github/workflows/test-e2e.yml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
name: E2E Tests
2+
3+
on:
4+
push:
5+
pull_request:
6+
7+
jobs:
8+
test-e2e:
9+
name: Run on Ubuntu
10+
runs-on: ubuntu-latest
11+
steps:
12+
- name: Clone the code
13+
uses: actions/checkout@v4
14+
15+
- name: Setup Go
16+
uses: actions/setup-go@v5
17+
with:
18+
go-version-file: go.mod
19+
20+
- name: Install the latest version of kind
21+
run: |
22+
curl -Lo ./kind https://kind.sigs.k8s.io/dl/latest/kind-linux-amd64
23+
chmod +x ./kind
24+
sudo mv ./kind /usr/local/bin/kind
25+
26+
- name: Verify kind installation
27+
run: kind version
28+
29+
- name: Running Test e2e
30+
run: |
31+
go mod tidy
32+
make test-e2e

.github/workflows/test.yml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
name: Tests
2+
3+
on:
4+
push:
5+
pull_request:
6+
7+
jobs:
8+
test:
9+
name: Run on Ubuntu
10+
runs-on: ubuntu-latest
11+
steps:
12+
- name: Clone the code
13+
uses: actions/checkout@v4
14+
15+
- name: Setup Go
16+
uses: actions/setup-go@v5
17+
with:
18+
go-version-file: go.mod
19+
20+
- name: Running Tests
21+
run: |
22+
go mod tidy
23+
make test

.gitignore

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Binaries for programs and plugins
2+
*.exe
3+
*.exe~
4+
*.dll
5+
*.so
6+
*.dylib
7+
bin/*
8+
Dockerfile.cross
9+
10+
# Test binary, built with `go test -c`
11+
*.test
12+
13+
# Output of the go coverage tool, specifically when used with LiteIDE
14+
*.out
15+
16+
# Go workspace file
17+
go.work
18+
19+
# Kubernetes Generated files - skip generated files, except for vendored files
20+
!vendor/**/zz_generated.*
21+
22+
# editor and IDE paraphernalia
23+
.idea
24+
.vscode
25+
*.swp
26+
*.swo
27+
*~

.golangci.yml

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
version: "2"
2+
run:
3+
allow-parallel-runners: true
4+
linters:
5+
default: none
6+
enable:
7+
- copyloopvar
8+
- dupl
9+
- errcheck
10+
- ginkgolinter
11+
- goconst
12+
- gocyclo
13+
- govet
14+
- ineffassign
15+
- lll
16+
- misspell
17+
- nakedret
18+
- prealloc
19+
- revive
20+
- staticcheck
21+
- unconvert
22+
- unparam
23+
- unused
24+
settings:
25+
revive:
26+
rules:
27+
- name: comment-spacings
28+
- name: import-shadowing
29+
exclusions:
30+
generated: lax
31+
rules:
32+
- linters:
33+
- lll
34+
path: api/*
35+
- linters:
36+
- dupl
37+
- lll
38+
path: internal/*
39+
paths:
40+
- third_party$
41+
- builtin$
42+
- examples$
43+
formatters:
44+
enable:
45+
- gofmt
46+
- goimports
47+
exclusions:
48+
generated: lax
49+
paths:
50+
- third_party$
51+
- builtin$
52+
- examples$

0 commit comments

Comments
 (0)