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.
npx claudepluginhub openstack-k8s-operators/devskills --plugin openstack-k8s-agent-tools[file.go]This skill is limited to using the following tools:
This skill applies and enforces Go code style best practices for openstack-k8s-operators operators, following openstack-k8s-operators conventions and gopls modernize recommendations.
Mandates invoking relevant skills via tools before any response in coding sessions. Covers access, priorities, and adaptations for Claude Code, Copilot CLI, Gemini CLI.
Share bugs, ideas, or general feedback.
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