pulumi-automation-api
Load this skill when a user asks how to run Pulumi programmatically, embed Pulumi in an application, orchestrate multiple stacks in code, build a self-service infrastructure portal, replace pulumi CLI shell scripts with code, or use the Pulumi Automation API (LocalWorkspace, createOrSelectStack, inline programs). Also load for questions about multi-stack sequencing, parallel deployments, or passing outputs between stacks via code.
Works with
---
name: pulumi-automation-api
description: Load this skill when a user asks how to run Pulumi programmatically, embed Pulumi in an application, orchestrate multiple stacks in code, build a self-service infrastructure portal, replace pulumi CLI shell scripts with code, or use the Pulumi Automation API (LocalWorkspace, createOrSelectStack, inline programs). Also load for questions about multi-stack sequencing, parallel deployments, or passing outputs between stacks via code.
license: Apache-2.0
---
# Pulumi Automation API
## When to Use This Skill
Invoke this skill when:
- Orchestrating deployments across multiple Pulumi stacks
- Embedding Pulumi operations in custom applications
- Building self-service infrastructure platforms
- Replacing fragile Bash/Makefile orchestration scripts
- Creating custom CLIs for infrastructure management
- Building web applications that provision infrastructure
## What is Automation API
Automation API provides programmatic access to Pulumi operations. Instead of running `pulumi up` from the CLI, you call functions in your code that perform the same operations.
```typescript
import * as automation from "@pulumi/pulumi/automation";
// Create or select a stack
const stack = await automation.LocalWorkspace.createOrSelectStack({
stackName: "dev",
projectName: "my-project",
program: async () => {
// Your Pulumi program here
},
});
// Run pulumi up programmatically
const upResult = await stack.up({ onOutput: console.log });
console.log(`Update summary: ${JSON.stringify(upResult.summary)}`);
```
## When to Use Automation API
### Good Use Cases
**Multi-stack orchestration:**
When you split infrastructure into multiple focused projects, Automation API helps offset the added complexity by orchestrating operations across stacks:
```text
infrastructure → platform → application
↓ ↓ ↓
(VPC) (Kubernetes) (Services)
```
Automation API ensures correct sequencing without manual intervention.
**Self-service platforms:**
Build internal tools where developers request infrastructure without learning Pulumi:
- Web portals for environment provisioning
- Slack bots that create/destroy resources
- Custom CLIs tailored to your organization
**Embedded infrastructure:**
Applications that provision their own infrastructure:
- SaaS platforms creating per-tenant resources
- Testing frameworks spinning up test environments
- CI/CD systems with dynamic infrastructure needs
**Replacing fragile scripts:**
If you have Bash scripts or Makefiles stitching together multiple `pulumi` commands, Automation API provides:
- Proper error handling
- Type safety
- Programmatic access to outputs
### When NOT to Use
- Single project with standard deployment needs
- When you don't need programmatic control over operations
## Architecture Choices
### Local Source vs Inline Source
**Local Source** - Pulumi program in separate files:
```typescript
const stack = await automation.LocalWorkspace.createOrSelectStack({
stackName: "dev",
workDir: "./infrastructure", // Points to existing Pulumi project
});
```
**When to use:**
- Different teams maintain orchestrator vs Pulumi programs
- Pulumi programs already exist
- Want independent version control and release cycles
- Platform team orchestrating application team's infrastructure
**Inline Source** - Pulumi program embedded in orchestrator:
```typescript
import * as aws from "@pulumi/aws";
const stack = await automation.LocalWorkspace.createOrSelectStack({
stackName: "dev",
projectName: "my-project",
program: async () => {
const bucket = new aws.s3.Bucket("my-bucket");
return { bucketName: bucket.id };
},
});
```
**When to use:**
- Single team owns everything
- Tight coupling between orchestration and infrastructure is desired
- Distributing as compiled binary (no source files needed)
- Simpler deployment artifact
### Language Independence
The Automation API program can use a different language than the Pulumi programs it orchestrates:
```text
Orchestrator (Go) → manages → Pulumi Program (TypeScript)
```
This enables platform teams to use their preferred language while application teams use theirs.
## Common Patterns
### Multi-Stack Orchestration
Deploy multiple stacks in dependency order:
```typescript
import * as automation from "@pulumi/pulumi/automation";
async function deploy() {
const stacks = [
{ name: "infrastructure", dir: "./infra" },
{ name: "platform", dir: "./platform" },
{ name: "application", dir: "./app" },
];
for (const stackInfo of stacks) {
console.log(`Deploying ${stackInfo.name}...`);
const stack = await automation.LocalWorkspace.createOrSelectStack({
stackName: "prod",
workDir: stackInfo.dir,
});
await stack.up({ onOutput: console.log });
console.log(`${stackInfo.name} deployed successfully`);
}
}
async function destroy() {
// Destroy in reverse order
const stacks = [
{ name: "application", dir: "./app" },
{ name: "platform", dir: "./platform" },
{ name: "infrastructure", dir: "./infra" },
];
for (const stackInfo of stacks) {
console.log(`Destroying ${stackInfo.name}...`);
const stack = await automation.LocalWorkspace.selectStack({
stackName: "prod",
workDir: stackInfo.dir,
});
await stack.destroy({ onOutput: console.log });
}
}
```
### Passing Configuration
Set stack configuration programmatically:
```typescript
const stack = await automation.LocalWorkspace.createOrSelectStack({
stackName: "dev",
workDir: "./infrastructure",
});
// Set configuration values
await stack.setConfig("aws:region", { value: "us-west-2" });
await stack.setConfig("dbPassword", { value: "secret", secret: true });
// Then deploy
await stack.up();
```
### Reading Outputs
Access stack outputs after deployment:
```typescript
const upResult = await stack.up();
// Get all outputs
const outputs = await stack.outputs();
console.log(`VPC ID: ${outputs["vpcId"].value}`);
// Or from the up result
console.log(`Outputs: ${JSON.stringify(upResult.outputs)}`);
```
### Error Handling
Handle deployment failures gracefully:
```typescript
try {
const result = await stack.up({ onOutput: console.log });
if (result.summary.result === "failed") {
console.error("Deployment failed");
process.exit(1);
}
} catch (error) {
console.error(`Deployment error: ${error}`);
throw error;
}
```
### Parallel Stack Operations
When stacks are independent, deploy in parallel:
```typescript
const independentStacks = [
{ name: "service-a", dir: "./service-a" },
{ name: "service-b", dir: "./service-b" },
{ name: "service-c", dir: "./service-c" },
];
await Promise.all(independentStacks.map(async (stackInfo) => {
const stack = await automation.LocalWorkspace.createOrSelectStack({
stackName: "prod",
workDir: stackInfo.dir,
});
return stack.up({ onOutput: (msg) => console.log(`[${stackInfo.name}] ${msg}`) });
}));
```
## Best Practices
### Separate Configuration from Code
Externalize configuration into files or environment variables:
```typescript
import * as fs from "fs";
interface DeployConfig {
stacks: Array<{ name: string; dir: string; }>;
environment: string;
}
const config: DeployConfig = JSON.parse(
fs.readFileSync("./deploy-config.json", "utf-8")
);
for (const stackInfo of config.stacks) {
const stack = await automation.LocalWorkspace.createOrSelectStack({
stackName: config.environment,
workDir: stackInfo.dir,
});
await stack.up();
}
```
This enables distributing compiled binaries without exposing source code.
### Stream Output for Long Operations
Use `onOutput` callback for real-time feedback:
```typescript
await stack.up({
onOutput: (message) => {
process.stdout.write(message);
// Or send to logging system, websocket, etc.
},
});
```
## Quick Reference
| Scenario | Approach |
| --- | --- |
| Existing Pulumi projects | Local source with workDir |
| New embedded infrastructure | Inline source with program function |
| Different teams | Local source for independence |
| Compiled binary distribution | Inline source or bundled local |
| Multi-stack dependencies | Sequential deployment in order |
| Independent stacks | Parallel deployment with Promise.all |
## Related Skills
- **pulumi-best-practices**: Code-level patterns for Pulumi programs
## References
- https://www.pulumi.com/docs/using-pulumi/automation-api/
- https://www.pulumi.com/docs/using-pulumi/automation-api/concepts-terminology/
- https://www.pulumi.com/blog/iac-recommended-practices-using-automation-api/More Deployment & CI/CD skills
azure-enterprise-infra-planner
microsoft/azure-skills
Architect and provision enterprise Azure infrastructure from workload descriptions. For cloud architects and platform engineers planning networking, identity, security, compliance, and multi-resource topologies with WAF alignment. Generates Bicep or Terraform directly (no azd). WHEN: 'plan Azure infrastructure', 'architect Azure landing zone', 'design hub-spoke network', 'plan multi-region DR topology', 'set up VNets firewalls and private endpoints', 'subscription-scope Bicep deployment', 'Azure Backup for VM workloads'. PREFER azure-prepare FOR app-centric workflows.
azure-kubernetes-app-deploy
microsoft/azure-skills
Use when deploying an existing web application or API to an already-running Azure Kubernetes Service cluster. Detects the framework, generates a Dockerfile and Kubernetes manifests, validates against AKS Deployment Safeguards, and deploys with verification. WHEN: deploy app to AKS, deploy to existing AKS cluster, containerize app for Kubernetes, generate K8s manifests for Azure, set up CI/CD for AKS, my AKS deployment is failing safeguard checks, I have a Django/Express/Spring Boot app to run on AKS. DO NOT USE FOR: creating or provisioning an AKS cluster (use azure-kubernetes), assessing migration to AKS Automatic (use azure-kubernetes-automatic-readiness), or deploying to non-AKS targets like Web Apps, Container Apps, or Functions.
finetuning
microsoft/azure-skills
Fine-tune models on Microsoft Foundry using SFT (supervised), DPO (preference), or RFT (reinforcement with graders). Covers dataset preparation, training job submission, deployment, and evaluation. USE FOR: fine-tune, SFT, DPO, RFT, training data, grader, distillation, fine-tuned model, training job, large file upload, calibrate grader, deploy fine-tuned model, evaluate fine-tuned model. DO NOT USE FOR: general model deployment without fine-tuning (use deploy-model), agent creation (use agents), prompt optimization without training (use prompt-optimizer).

