agentleFS
diriendirien/claude-skills/pulumi-go/SKILL.md

pulumi-go

Skill13 starsChanged 8 months agoMITView on GitHub

Creates Pulumi infrastructure-as-code projects in Go, configures OIDC authentication, integrates with Pulumi ESC for centralized secrets and configuration management, and builds multi-language component resources. Use when setting up Pulumi Go projects, writing infrastructure code with Go, configuring OIDC for Pulumi, using Pulumi ESC with Go, automating cloud infrastructure with Golang, creating reusable Pulumi components in Go, or working with pulumi-go-provider. Also use when the user mentions Pulumi with Go/Golang, AWS/Azure/GCP infrastructure in Go, or Go-based ComponentResource patterns.

1 other project uses a version of this.

Adopted by

Most recently taken up by

  • Other versions1 project uses a version of this.

    Word for word · 1

    1. dirien/yet-another-agent-harness★ 19100% same

    Edited · 0

    None found.

    Wrote their own version · 0

    None found.

    How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.

  • In this repository9 other files it gives its agents.

The file

Show its rules and text

We split this skill into the rules it gives an agent

13 rules. About 0 are common, 9 are distinctive, and 4 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈9

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 4

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  • could be automatic: a setting could enforce it
  1. Very specific:

    Check ESC environment values: pulumi env open myorg/myproject-dev

    line 255
  2. Very specific:

    Verify stack config: pulumi config

    line 256
  3. Distinctive:

    Error recovery: If deployment fails:

    line 268
  4. Distinctive:

    Check error logs for resource-specific issues

    line 269
  5. Very specific:

    Verify credentials and permissions: pulumi env open myorg/myproject-dev --format shell

    line 270
  6. Distinctive:

    Create reusable components in Go for consumption from any Pulumi language.

    line 303
  7. Distinctive:

    Use Pulumi ESC for all secrets — never commit secrets to stack config files

    line 411
  8. Distinctive:

    Use dynamic secrets with short TTLs when possible

    line 413
  9. Distinctive:

    Use Component Resources for reusable infrastructure patterns

    line 417
  10. Distinctive:

    Keep stack-specific config in ESC environments

    line 419
  11. Distinctive:

    Use stack references for cross-stack dependencies

    line 420
  12. Very specific:

    Always run pulumi preview before pulumi up and review changes carefully

    line 423
  13. Distinctive:

    Use ESC environment versioning and tags for releases

    line 424

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Pulumi Go Skill

Development Workflow

1. Project Setup

# Create new Go project
pulumi new go

# Or with a cloud-specific template
pulumi new aws-go
pulumi new azure-go
pulumi new gcp-go

2. Pulumi ESC Integration

Link ESC environment to stack:

# Create ESC environment
pulumi env init myorg/myproject-dev

# Edit environment
pulumi env edit myorg/myproject-dev

# Link to Pulumi stack
pulumi config env add myorg/myproject-dev

ESC environment definition (YAML):

values:
  # Static configuration
  pulumiConfig:
    aws:region: us-west-2
    myapp:instanceType: t3.medium

  # Dynamic OIDC credentials for AWS
  aws:
    login:
      fn::open::aws-login:
        oidc:
          roleArn: arn:aws:iam::123456789:role/pulumi-oidc
          sessionName: pulumi-deploy

  # Pull secrets from AWS Secrets Manager
  secrets:
    fn::open::aws-secrets:
      region: us-west-2
      login: ${aws.login}
      get:
        dbPassword:
          secretId: prod/database/password

  # Expose to environment variables
  environmentVariables:
    AWS_ACCESS_KEY_ID: ${aws.login.accessKeyId}
    AWS_SECRET_ACCESS_KEY: ${aws.login.secretAccessKey}
    AWS_SESSION_TOKEN: ${aws.login.sessionToken}

3. Go Patterns

Basic resource creation:

package main

import (
    "github.com/pulumi/pulumi-aws/sdk/v6/go/aws/s3"
    "github.com/pulumi/pulumi/sdk/v3/go/pulumi"
    "github.com/pulumi/pulumi/sdk/v3/go/pulumi/config"
)

func main() {
    pulumi.Run(func(ctx *pulumi.Context) error {
        // Get configuration from ESC
        cfg := config.New(ctx, "")
        instanceType := cfg.Require("instanceType")

        // Create resources with proper tagging
        bucket, err := s3.NewBucket(ctx, "my-bucket", &s3.BucketArgs{
            Versioning: &s3.BucketVersioningArgs{
                Enabled: pulumi.Bool(true),
            },
            ServerSideEncryptionConfiguration: &s3.BucketServerSideEncryptionConfigurationArgs{
                Rule: &s3.BucketServerSideEncryptionConfigurationRuleArgs{
                    ApplyServerSideEncryptionByDefault: &s3.BucketServerSideEncryptionConfigurationRuleApplyServerSideEncryptionByDefaultArgs{
                        SseAlgorithm: pulumi.String("AES256"),
                    },
                },
            },
            Tags: pulumi.StringMap{
                "Environment": pulumi.String(ctx.Stack()),
                "ManagedBy":   pulumi.String("Pulumi"),
            },
        })
        if err != nil {
            return err
        }

        // Export outputs
        ctx.Export("bucketName", bucket.ID())
        ctx.Export("bucketArn", bucket.Arn)

        return nil
    })
}

Component resources:

package main

import (
    "github.com/pulumi/pulumi-aws/sdk/v6/go/aws/lb"
    "github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

type WebServiceArgs struct {
    Port     pulumi.IntInput
    ImageUri pulumi.StringInput
}

type WebService struct {
    pulumi.ResourceState

    URL pulumi.StringOutput `pulumi:"url"`
}

func NewWebService(ctx *pulumi.Context, name string, args *WebServiceArgs, opts ...pulumi.ResourceOption) (*WebService, error) {
    component := &WebService{}
    err := ctx.RegisterComponentResource("custom:app:WebService", name, component, opts...)
    if err != nil {
        return nil, err
    }

    // Create child resources with pulumi.Parent(component)
    loadBalancer, err := lb.NewLoadBalancer(ctx, name+"-lb", &lb.LoadBalancerArgs{
        LoadBalancerType: pulumi.String("application"),
        // ... configuration
    }, pulumi.Parent(component))
    if err != nil {
        return nil, err
    }

    component.URL = loadBalancer.DnsName

    ctx.RegisterResourceOutputs(component, pulumi.Map{
        "url": component.URL,
    })

    return component, nil
}

Stack references for cross-stack dependencies:

package main

import (
    "github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
    pulumi.Run(func(ctx *pulumi.Context) error {
        // Reference outputs from networking stack
        networkingStack, err := pulumi.NewStackReference(ctx, "myorg/networking/prod", nil)
        if err != nil {
            return err
        }

        vpcId := networkingStack.GetStringOutput(pulumi.String("vpcId"))
        subnetIds := networkingStack.GetOutput(pulumi.String("privateSubnetIds"))

        ctx.Export("vpcId", vpcId)

        return nil
    })
}

Working with Outputs:

package main

import (
    "fmt"
    "strings"

    "github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
    pulumi.Run(func(ctx *pulumi.Context) error {
        // Apply transformation
        uppercaseName := bucket.ID().ApplyT(func(id string) string {
            return strings.ToUpper(id)
        }).(pulumi.StringOutput)

        // Combine multiple outputs
        combined := pulumi.All(bucket.ID(), bucket.Arn).ApplyT(
            func(args []interface{}) string {
                id := args[0].(string)
                arn := args[1].(string)
                return fmt.Sprintf("Bucket %s has ARN %s", id, arn)
            },
        ).(pulumi.StringOutput)

        // Conditional resources
        if ctx.Stack() == "prod" {
            _, err := cloudwatch.NewMetricAlarm(ctx, "alarm", &cloudwatch.MetricAlarmArgs{
                // ... configuration
            })
            if err != nil {
                return err
            }
        }

        return nil
    })
}

4. Using ESC with pulumi env run

# Run pulumi commands with ESC credentials
pulumi env run myorg/aws-dev -- pulumi up

# Run tests with secrets
pulumi env run myorg/test-env -- go test ./...

# Open environment and export to shell
pulumi env open myorg/myproject-dev --format shell

5. Deployment Workflow with Validation

Build and preview:

# Build Go binary first
go build -o $(basename $(pwd))

# Preview changes
pulumi preview

Validation checkpoint: Review the preview output. If changes are unexpected:

  • Check ESC environment values: pulumi env open myorg/myproject-dev
  • Verify stack config: pulumi config
  • Inspect resource diffs carefully before proceeding

Deploy:

# Deploy after validation
pulumi up

# Verify outputs
pulumi stack output

Error recovery: If deployment fails:

  1. Check error logs for resource-specific issues
  2. Verify credentials and permissions: pulumi env open myorg/myproject-dev --format shell
  3. Attempt rollback if needed: pulumi refresh (updates state without changes)
  4. Fix the issue and retry: pulumi up

For destructive changes (deletions), Pulumi will prompt for confirmation during pulumi up.

6. Error Handling

func main() {
    pulumi.Run(func(ctx *pulumi.Context) error {
        bucket, err := s3.NewBucket(ctx, "bucket", &s3.BucketArgs{})
        if err != nil {
            return fmt.Errorf("failed to create bucket: %w", err)
        }

        policy, err := s3.NewBucketPolicy(ctx, "policy", &s3.BucketPolicyArgs{
            Bucket: bucket.ID(),
            Policy: bucket.Arn.ApplyT(func(arn string) string {
                return fmt.Sprintf(`{"Version":"2012-10-17",...}`, arn)
            }).(pulumi.StringOutput),
        })
        if err != nil {
            return fmt.Errorf("failed to create bucket policy: %w", err)
        }

        return nil
    })
}

7. Multi-Language Components

Create reusable components in Go for consumption from any Pulumi language.

Project structure:

my-component/
├── PulumiPlugin.yaml
├── go.mod
├── go.sum
└── main.go

PulumiPlugin.yaml:

runtime: go

Component implementation:

package main

import (
    "context"
    "log"

    "github.com/pulumi/pulumi-aws/sdk/v6/go/aws/s3"
    "github.com/pulumi/pulumi-go-provider/infer"
    "github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

// Use Input types for all properties
type SecureBucketArgs struct {
    BucketName       pulumi.StringInput `pulumi:"bucketName"`
    EnableVersioning pulumi.BoolInput   `pulumi:"enableVersioning,optional"`
    Tags             pulumi.StringMapInput `pulumi:"tags,optional"`
}

type SecureBucket struct {
    pulumi.ResourceState

    BucketId  pulumi.StringOutput `pulumi:"bucketId"`
    BucketArn pulumi.StringOutput `pulumi:"bucketArn"`
}

func NewSecureBucket(ctx *pulumi.Context, name string, args *SecureBucketArgs, opts ...pulumi.ResourceOption) (*SecureBucket, error) {
    component := &SecureBucket{}
    err := ctx.RegisterComponentResource("myorg:storage:SecureBucket", name, component, opts...)
    if err != nil {
        return nil, err
    }

    bucket, err := s3.NewBucket(ctx, name+"-bucket", &s3.BucketArgs{
        Bucket: args.BucketName,
        Versioning: &s3.BucketVersioningArgs{
            Enabled: args.EnableVersioning,
        },
        ServerSideEncryptionConfiguration: &s3.BucketServerSideEncryptionConfigurationArgs{
            Rule: &s3.BucketServerSideEncryptionConfigurationRuleArgs{
                ApplyServerSideEncryptionByDefault: &s3.BucketServerSideEncryptionConfigurationRuleApplyServerSideEncryptionByDefaultArgs{
                    SseAlgorithm: pulumi.String("AES256"),
                },
            },
        },
        Tags: args.Tags,
    }, pulumi.Parent(component))
    if err != nil {
        return nil, err
    }

    component.BucketId = bucket.ID().ToStringOutput()
    component.BucketArn = bucket.Arn

    ctx.RegisterResourceOutputs(component, pulumi.Map{
        "bucketId":  component.BucketId,
        "bucketArn": component.BucketArn,
    })

    return component, nil
}

func main() {
    prov, err := infer.NewProviderBuilder().
        WithNamespace("myorg").
        WithComponents(
            infer.ComponentF(NewSecureBucket),
        ).
        Build()
    if err != nil {
        log.Fatal(err.Error())
    }
    _ = prov.Run(context.Background(), "go-components", "v0.0.1")
}

Publishing:

# Consume from git repository
pulumi package add github.com/myorg/my-component

# With version tag
pulumi package add github.com/myorg/my-component@v1.0.0

# Local development
pulumi package add /path/to/local/my-component

Best Practices

Security

  • Use Pulumi ESC for all secrets — never commit secrets to stack config files
  • Enable OIDC authentication instead of static credentials
  • Use dynamic secrets with short TTLs when possible
  • Apply least-privilege IAM policies

Code Organization

  • Use Component Resources for reusable infrastructure patterns
  • Leverage Go's type system for configuration validation
  • Keep stack-specific config in ESC environments
  • Use stack references for cross-stack dependencies

Deployment

  • Always run pulumi preview before pulumi up and review changes carefully
  • Use ESC environment versioning and tags for releases
  • Implement proper tagging strategy for all resources
  • Build your Go program before running Pulumi: go build -o $(basename $(pwd))

Common Commands

# Environment Commands (pulumi env)
pulumi env init <org>/<project>/<env>        # Create environment
pulumi env edit <org>/<env>                  # Edit environment
pulumi env open <org>/<env>                  # View resolved values
pulumi env run <org>/<env> -- <command>      # Run with env vars
pulumi env version tag <org>/<env> <tag>     # Tag version

# Pulumi Commands
pulumi new go                          # New project
pulumi config env add <org>/<env>     # Link ESC environment
go build -o $(basename $(pwd))         # Build Go binary
pulumi preview                         # Preview changes
pulumi up                              # Deploy
pulumi stack output                    # View outputs
pulumi destroy                         # Tear down

References

  • references/pulumi-esc.md - ESC patterns and commands
  • references/pulumi-patterns.md - Common infrastructure patterns
  • references/pulumi-go.md - Go-specific guidance
  • references/pulumi-best-practices-aws.md - AWS best practices
  • references/pulumi-best-practices-azure.md - Azure best practices
  • references/pulumi-best-practices-gcp.md - GCP best practices

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.