Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# More info: https://docs.docker.com/engine/reference/builder/#dockerignore-file
# Ignore build and test binaries.
bin/
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/internal/api/** linguist-generated=true
11 changes: 11 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,14 @@ updates:
schedule:
# Check for updates to GitHub Actions every week
interval: "weekly"
- package-ecosystem: "gomod"
directory: "/"
schedule:
# Check for updates to Go modules every week
interval: "weekly"
groups:
go-dependencies:
patterns:
- "*"
commit-message:
prefix: "NO-ISSUE"
167 changes: 167 additions & 0 deletions .github/workflows/build-image.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
name: Build container image

on:
workflow_dispatch:
pull_request:
push:
branches:
- main

concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true

env:
# Use docker.io for Docker Hub if empty
REGISTRY: ghcr.io
# github.repository as <account>/<repo>
IMAGE_NAME: ${{ github.repository }}


jobs:
test:
name: Run Tests
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v6

- name: Set up Go
uses: actions/setup-go@v6
with:
go-version-file: 'go.mod'

- name: Install kind
uses: helm/kind-action@v1
with:
install_only: true

- name: Run all tests
run: make test

build:
needs: test
runs-on: ubuntu-latest
permissions:
contents: read
packages: write

steps:
- name: Checkout repository
uses: actions/checkout@v6

# Login against a Docker registry except on PR
# https://github.com/docker/login-action
- name: Log into registry ${{ env.REGISTRY }}
if: github.event_name != 'pull_request'
uses: docker/login-action@v4
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

# Extract metadata (tags, labels) for Docker
# https://github.com/docker/metadata-action
- name: Extract Docker metadata
id: meta
uses: docker/metadata-action@v6
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=semver,pattern=v{{version}}
type=semver,pattern=v{{major}}.{{minor}}
type=semver,pattern=v{{major}}
type=ref,event=branch
type=ref,event=pr
type=ref,event=tag
type=sha
type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', 'main') }}


# Build and push Docker image with Buildx (don't push on PR)
# https://github.com/docker/build-push-action
- name: Build and push Docker image
id: build-operator
uses: docker/build-push-action@v7
with:
context: .
file: Containerfile
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}

# Extract the commit SHA tag for manifest generation
- name: Extract commit SHA tag
id: sha-tag
if: github.event_name != 'pull_request'
run: |
# Extract the sha tag from the metadata output
FULL_SHA_TAG=$(echo "${{ steps.meta.outputs.tags }}" | grep -E "sha-[0-9a-f]{7}" | head -n1)
SHA_TAG=$(echo "$FULL_SHA_TAG" | sed "s/.*://")
echo "sha-tag=$SHA_TAG" >> $GITHUB_OUTPUT
echo "full-sha-tag=$FULL_SHA_TAG" >> $GITHUB_OUTPUT
echo "manifest-tag=$SHA_TAG-manifests" >> $GITHUB_OUTPUT
echo "Using SHA tag: $SHA_TAG"
echo "Full SHA tag: $FULL_SHA_TAG"
echo "Manifest tag: $SHA_TAG-manifests"

# Set up Go for kustomize operations
- name: Set up Go for manifest generation
if: github.event_name != 'pull_request'
uses: actions/setup-go@v6
with:
go-version-file: 'go.mod'

# Generate manifests with kustomize pointing to the SHA-tagged image
- name: Generate manifests with kustomize
if: github.event_name != 'pull_request'
run: |
# Install kustomize
make kustomize

# Create dist directory
mkdir -p dist

# Set the manager image to the SHA-tagged version
cd config/manager && ../../bin/kustomize edit set image controller=${{ steps.sha-tag.outputs.full-sha-tag }}

# Generate the complete manifest
cd ../..
./bin/kustomize build config/default > dist/install.yaml

echo "Generated manifest with image: ${{ steps.sha-tag.outputs.full-sha-tag }}"
echo "Manifest content preview:"
head -20 dist/install.yaml

# Create Dockerfile for manifest container
- name: Create manifest container Dockerfile
if: github.event_name != 'pull_request'
run: |
cat > Dockerfile.manifests << 'EOF'
FROM scratch
COPY dist/install.yaml /manifests/install.yaml
EOF

echo "Created Dockerfile.manifests:"
cat Dockerfile.manifests

# Extract metadata for manifest container
- name: Extract manifest container metadata
id: meta-manifests
if: github.event_name != 'pull_request'
uses: docker/metadata-action@v6
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=raw,value=${{ steps.sha-tag.outputs.manifest-tag }}

# Build and push manifest container
- name: Build and push manifest container
if: github.event_name != 'pull_request'
uses: docker/build-push-action@v7
with:
context: .
file: Dockerfile.manifests
push: true
tags: ${{ steps.meta-manifests.outputs.tags }}
labels: ${{ steps.meta-manifests.outputs.labels }}
13 changes: 13 additions & 0 deletions .github/workflows/pre-commit.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,16 @@ jobs:
with:
python-version: "3.13"
- uses: pre-commit/action@v3.0.1
with:
extra_args: -c .pre-commit-config-ci.yaml

golangci-lint:
name: lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/setup-go@v6
with:
go-version: stable
- name: golangci-lint
uses: golangci/golangci-lint-action@v9
36 changes: 36 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
bin/*
main
Dockerfile.cross
Dockerfile.manifests
dist/

# Test binary, built with `go test -c`
*.test

# Output of the go coverage tool, specifically when used with LiteIDE
*.out

# Go workspace file
go.work

# Kubernetes Generated files - skip generated files, except for vendored files
!vendor/**/zz_generated.*

# editor and IDE paraphernalia
.idea
.vscode
*.swp
*.swo
*~

# Development memory/notes (local only)
MEMORY.md

# Claude notes
CLAUDE.md
60 changes: 60 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
version: "2"
run:
allow-parallel-runners: true
linters:
default: none
enable:
- dupl
- errcheck
- ginkgolinter
- goconst
- gocyclo
- govet
- ineffassign
- lll
- misspell
# nakedret
- prealloc
- revive
- staticcheck
- unconvert
# unparam
- unused
settings:
revive:
rules:
- name: comment-spacings
staticcheck:
checks:
- all
- '-QF1008'
exclusions:
generated: lax
rules:
- linters:
- lll
path: api/*
- linters:
- dupl
- lll
path: internal/*
- linters:
- dupl
path: api/v1alpha1/clusterorder_clusterreference.go
- linters:
- dupl
path: api/v1alpha1/computeinstance_virtualmachinereference.go
paths:
- third_party$
- builtin$
- examples$
formatters:
enable:
- gofmt
- goimports
exclusions:
generated: lax
paths:
- third_party$
- builtin$
- examples$
21 changes: 21 additions & 0 deletions .pre-commit-config-ci.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0
hooks:
- id: trailing-whitespace
- id: check-merge-conflict
- id: end-of-file-fixer
- id: check-added-large-files
- id: check-case-conflict
- id: check-json
- id: check-symlinks
- id: detect-private-key

- repo: https://github.com/adrienverge/yamllint.git
rev: v1.35.1
hooks:
- id: yamllint
exclude: "^config/"
files: \.(yaml|yml)$
types: [file, yaml]
entry: yamllint --strict
10 changes: 10 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,16 @@ repos:
rev: v1.35.1
hooks:
- id: yamllint
exclude: "^config/"
files: \.(yaml|yml)$
types: [file, yaml]
entry: yamllint --strict

- repo: local
hooks:
- id: golangci-lint
pass_filenames: false
name: golangci-lint
language: system
files: \.go$
entry: bin/golangci-lint run --fix
31 changes: 31 additions & 0 deletions Containerfile
Comment thread
DanNiESh marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Build the manager binary
FROM golang:1.25 AS builder
ARG TARGETOS
ARG TARGETARCH

WORKDIR /workspace
# Copy the Go Modules manifests
COPY go.mod go.mod
COPY go.sum go.sum
# cache deps before building and copying source so that we don't need to re-download as much
# and so that source changes don't invalidate our downloaded layer
RUN go mod download

# Copy the go source
COPY . ./

# Build
# the GOARCH has not a default value to allow the binary be built according to the host where the command
# was called. For example, if we call make docker-build in a local env which has the Apple Silicon M1 SO
# the docker BUILDPLATFORM arg will be linux/arm64 when for Apple x86 it will be linux/amd64. Therefore,
# by leaving it empty we can ensure that the container and binary shipped on it will have the same platform.
RUN CGO_ENABLED=0 GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH} go build -a -o manager cmd/main.go
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why provide a default for GOOS? Shouldn't the same logic apply to GOOS that applies to GOARCH?

Copy link
Copy Markdown
Author

@DanNiESh DanNiESh Apr 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This Containerfile is generated by operator-sdk init command. By reading the comment above this command, i think GOARCH is left without an explicit fallback so it follows the build platform/host architecture. OS is constrained by runtime image, arch is meant to float with build target.


# Use distroless as minimal base image to package the manager binary
# Refer to https://github.com/GoogleContainerTools/distroless for more details
FROM gcr.io/distroless/static:nonroot
WORKDIR /
COPY --from=builder /workspace/manager .
USER 65532:65532

ENTRYPOINT ["/manager"]
Loading
Loading