From openstack-k8s-agent-tools
Applies Go code style best practices for openstack-k8s-operators using gopls modernize and project conventions: modern syntax, controller-runtime patterns, error handling, logging, status updates, naming.
How this skill is triggered — by the user, by Claude, or both
Slash command
/openstack-k8s-agent-tools:code-style [file.go][file.go]This skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
This skill applies and enforces Go code style best practices for openstack-k8s-operators operators, following openstack-k8s-operators conventions and gopls modernize recommendations.
This skill applies and enforces Go code style best practices for openstack-k8s-operators operators, following openstack-k8s-operators conventions and gopls modernize recommendations.
Based on gopls modernize and lib-common patterns:
// Bad: Old style
var items []string = []string{}
// Good: Modern style
var items []string
// Bad: Old style
var configs map[string]interface{} = make(map[string]interface{})
// Good: Modern style
var configs = make(map[string]interface{})
// Bad: Inefficient concatenation
result := ""
for _, item := range items {
result += item + "\n"
}
// Good: Use strings.Builder
var builder strings.Builder
for _, item := range items {
builder.WriteString(item)
builder.WriteString("\n")
}
result := builder.String()
// Good: Proper error wrapping
if err := r.Get(ctx, req.NamespacedName, &instance); err != nil {
if errors.IsNotFound(err) {
return ctrl.Result{}, nil
}
return ctrl.Result{}, fmt.Errorf("failed to get instance: %w", err)
}
// Good: Structured logging with context
log := ctrl.LoggerFrom(ctx).WithValues("instance", instance.Name)
log.Info("Starting reconciliation")
// Good: Proper status condition handling
meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{
Type: "Ready",
Status: metav1.ConditionTrue,
Reason: "ReconciliationSuccessful",
Message: "Instance successfully reconciled",
})
// Bad: capitalized error string
return fmt.Errorf("Failed to create configmap")
// Good: lowercase, no punctuation, wrapped with context
return fmt.Errorf("failed to create configmap: %w", err)
// Bad: unnecessary else after error return
if err != nil {
return err
} else {
doSomething()
}
// Good: normal flow at minimal indentation
if err != nil {
return err
}
doSomething()
// Bad: discarding errors
result, _ := someFunction()
// Good: always handle errors
result, err := someFunction()
if err != nil {
return fmt.Errorf("failed to do something: %w", err)
}
// Bad: non-Go naming
MAX_RETRIES := 3
func GetOwner() string {}
appId := "123"
// Good: MixedCaps, no Get prefix, consistent initialisms
maxRetries := 3
func Owner() string {}
appID := "123"
// Bad: long receiver names
func (reconciler *GlanceReconciler) Reconcile(...) {}
func (this *GlanceReconciler) Reconcile(...) {}
// Good: short, consistent receiver (1-2 letters)
func (r *GlanceReconciler) Reconcile(...) {}
// Bad: meaningless package names
package util
package common
package helpers
// Good: descriptive, lowercase, single-word
package glance
package endpoint
package condition
// Bad: large interface defined in the implementation package
type Storage interface {
Get(key string) ([]byte, error)
Set(key string, value []byte) error
Delete(key string) error
List(prefix string) ([]string, error)
Watch(prefix string) <-chan Event
}
// Good: small interface defined by the consumer, only methods actually needed
type Reader interface {
Get(key string) ([]byte, error)
}
// Bad: returning interface
func NewStore() StoreInterface { return &store{} }
// Good: return concrete type, accept interfaces
func NewStore() *Store { return &store{} }
// Bad: context as struct field
type Server struct {
ctx context.Context
}
// Good: context as first parameter
func (s *Server) Process(ctx context.Context, req Request) error {}
// Bad: goroutine with unclear lifetime
go func() {
for {
doWork()
}
}()
// Good: clear goroutine lifecycle with context
go func() {
for {
select {
case <-ctx.Done():
return
case item := <-ch:
process(item)
}
}
}()
// Good: Consistent finalizer pattern
const FinalizerName = "operator.openstack.org/finalizer"
if instance.DeletionTimestamp != nil {
return r.handleDeletion(ctx, &instance)
}
if !controllerutil.ContainsFinalizer(&instance, FinalizerName) {
controllerutil.AddFinalizer(&instance, FinalizerName)
return ctrl.Result{}, r.Update(ctx, &instance)
}
// Good: Proper owner references
if err := ctrl.SetControllerReference(&instance, resource, r.Scheme); err != nil {
return fmt.Errorf("failed to set owner reference: %w", err)
}
// Good: Descriptive test structure
var _ = Describe("Nova Controller", func() {
Context("When creating a Nova instance", func() {
BeforeEach(func() {
// Setup
})
It("Should create required resources", func() {
// Test implementation
})
})
})
// Good: Proper interface mocking
//go:generate mockery --name=ServiceInterface --output=../mocks
type ServiceInterface interface {
CreateService(ctx context.Context, svc *corev1.Service) error
}
The skill provides automated fixes for:
# Run style analysis
gopls check <file>
# Apply modernization fixes
gopls fix -a fillstruct,unusedparam <file>
# Check with golangci-lint
golangci-lint run --enable-all
# .pre-commit-config.yaml
repos:
- repo: local
hooks:
- id: go-style-check
name: Go Style Check
entry: ./scripts/style-check.sh
language: script
files: '\.go$'
// VSCode settings for openstack-k8s-operators operators
{
"go.lintTool": "golangci-lint",
"go.lintFlags": ["--config", ".golangci.yml"],
"gopls": {
"experimentalPostfixCompletions": true,
"analyses": {
"unusedparams": true,
"shadow": true
}
}
}
Invoke /code-style to:
# Analyze entire project
/code-style analyze-project
# Fix specific file
/code-style fix-file controllers/nova_controller.go
# Check against lib-common patterns
/code-style check-libcommon
# Apply gopls modernize
/code-style modernize
npx claudepluginhub openstack-k8s-operators/devskills --plugin openstack-k8s-agent-toolsGuides creation, editing, and verification of skills for AI coding agents using test-driven development with subagent scenarios. Use when authoring or debugging skills.