or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

asset-management.mdautomation.mdconfiguration.mddynamic-resources.mdindex.mdlogging-diagnostics.mdoutput-system.mdprovider-development.mdresource-management.mdruntime-operations.mdstack-references.mdutilities.md

automation.mddocs/

0

# Automation

1

2

Pulumi's Automation API enables programmatic management of Pulumi stacks and workspaces, allowing you to build custom deployment tools, CI/CD integrations, and infrastructure management applications.

3

4

## Core Workspace Classes

5

6

```typescript { .api }

7

abstract class Workspace {

8

abstract workDir: string;

9

abstract pulumiHome?: string;

10

abstract program?: PulumiFn;

11

abstract envVars: { [key: string]: string };

12

abstract secretsProvider?: string;

13

abstract projectSettings(): Promise<ProjectSettings>;

14

abstract saveProjectSettings(settings: ProjectSettings): Promise<void>;

15

abstract stackSettings(stackName: string): Promise<StackSettings>;

16

abstract saveStackSettings(stackName: string, settings: StackSettings): Promise<void>;

17

abstract serializeArgsForOp(stackName: string): Promise<string[]>;

18

abstract postCommandCallback(stackName: string): Promise<void>;

19

}

20

21

class LocalWorkspace extends Workspace {

22

static create(args?: LocalWorkspaceOptions): Promise<LocalWorkspace>;

23

static createStack(args: LocalProgramArgs): Promise<Stack>;

24

static selectStack(args: LocalProgramArgs): Promise<Stack>;

25

static createOrSelectStack(args: LocalProgramArgs): Promise<Stack>;

26

27

workDir: string;

28

pulumiHome?: string;

29

program?: PulumiFn;

30

envVars: { [key: string]: string };

31

secretsProvider?: string;

32

33

constructor(opts?: LocalWorkspaceOptions);

34

35

projectSettings(): Promise<ProjectSettings>;

36

saveProjectSettings(settings: ProjectSettings): Promise<void>;

37

stackSettings(stackName: string): Promise<StackSettings>;

38

saveStackSettings(stackName: string, settings: StackSettings): Promise<void>;

39

installPlugin(name: string, version: string, kind?: string): Promise<void>;

40

removePlugin(name: string, versionRange?: string, kind?: string): Promise<void>;

41

listPlugins(): Promise<PluginInfo[]>;

42

exportStack(stackName: string): Promise<Deployment>;

43

importStack(stackName: string, state: Deployment): Promise<void>;

44

whoAmI(): Promise<string>;

45

pulumiVersion(): Promise<string>;

46

}

47

```

48

49

## Stack Management

50

51

```typescript { .api }

52

class Stack {

53

readonly name: string;

54

readonly workspace: Workspace;

55

56

constructor(name: string, workspace: Workspace);

57

58

// Core operations

59

up(opts?: UpOptions): Promise<UpResult>;

60

preview(opts?: PreviewOptions): Promise<PreviewResult>;

61

refresh(opts?: RefreshOptions): Promise<RefreshResult>;

62

destroy(opts?: DestroyOptions): Promise<DestroyResult>;

63

64

// Import/Export operations

65

import(opts: ImportOptions): Promise<ImportResult>;

66

export(): Promise<Deployment>;

67

68

// Configuration management

69

getConfig(key: string): Promise<ConfigValue>;

70

getAllConfig(): Promise<{ [key: string]: ConfigValue }>;

71

setConfig(key: string, value: ConfigValue): Promise<void>;

72

setAllConfig(config: { [key: string]: ConfigValue }): Promise<void>;

73

removeConfig(key: string): Promise<void>;

74

removeAllConfig(keys: string[]): Promise<void>;

75

76

// Stack information

77

outputs(): Promise<OutputMap>;

78

history(pageSize?: number, page?: number): Promise<UpdateSummary[]>;

79

info(): Promise<StackSummary>;

80

81

// Stack lifecycle

82

rename(newName: string): Promise<void>;

83

cancel(): Promise<void>;

84

}

85

```

86

87

## Operation Options and Results

88

89

```typescript { .api }

90

interface UpOptions {

91

parallel?: number;

92

message?: string;

93

expectNoChanges?: boolean;

94

diff?: boolean;

95

replace?: string[];

96

target?: string[];

97

targetDependents?: boolean;

98

policyPacks?: string[];

99

policyPackConfigs?: { [key: string]: PolicyPackConfig };

100

refresh?: boolean;

101

userAgent?: string;

102

colorMode?: "always" | "never" | "raw" | "auto";

103

continueOnError?: boolean;

104

}

105

106

interface UpResult {

107

stdout: string;

108

stderr: string;

109

summary: UpdateSummary;

110

outputs: OutputMap;

111

}

112

113

interface PreviewOptions {

114

parallel?: number;

115

message?: string;

116

expectNoChanges?: boolean;

117

diff?: boolean;

118

replace?: string[];

119

target?: string[];

120

targetDependents?: boolean;

121

policyPacks?: string[];

122

policyPackConfigs?: { [key: string]: PolicyPackConfig };

123

refresh?: boolean;

124

userAgent?: string;

125

colorMode?: "always" | "never" | "raw" | "auto";

126

}

127

128

interface PreviewResult {

129

stdout: string;

130

stderr: string;

131

summary: UpdateSummary;

132

changeSummary: { [key: string]: number };

133

}

134

135

interface DestroyOptions {

136

parallel?: number;

137

message?: string;

138

target?: string[];

139

targetDependents?: boolean;

140

refresh?: boolean;

141

userAgent?: string;

142

colorMode?: "always" | "never" | "raw" | "auto";

143

continueOnError?: boolean;

144

}

145

146

interface DestroyResult {

147

stdout: string;

148

stderr: string;

149

summary: UpdateSummary;

150

}

151

```

152

153

## Configuration Types

154

155

```typescript { .api }

156

interface LocalWorkspaceOptions {

157

workDir?: string;

158

pulumiHome?: string;

159

program?: PulumiFn;

160

envVars?: { [key: string]: string };

161

secretsProvider?: string;

162

kubeconfig?: string;

163

projectSettings?: ProjectSettings;

164

stackSettings?: { [key: string]: StackSettings };

165

repo?: GitRepo;

166

}

167

168

interface LocalProgramArgs {

169

stackName: string;

170

workDir?: string;

171

program?: PulumiFn;

172

opts?: LocalWorkspaceOptions;

173

}

174

175

interface InlineProgramArgs {

176

stackName: string;

177

projectName: string;

178

program: PulumiFn;

179

opts?: LocalWorkspaceOptions;

180

}

181

182

type PulumiFn = () => Promise<void> | void;

183

184

interface ProjectSettings {

185

name: string;

186

runtime: ProjectRuntimeInfo;

187

main?: string;

188

description?: string;

189

author?: string;

190

website?: string;

191

license?: string;

192

config?: { [key: string]: ProjectConfigType };

193

template?: ProjectTemplate;

194

backend?: ProjectBackend;

195

options?: ProjectOptions;

196

plugins?: PluginOptions;

197

}

198

199

interface StackSettings {

200

secretsProvider?: string;

201

encryptedKey?: string;

202

encryptionSalt?: string;

203

config?: { [key: string]: ConfigValue };

204

}

205

206

interface ConfigValue {

207

value: string;

208

secret?: boolean;

209

}

210

211

type OutputMap = { [key: string]: OutputValue };

212

213

interface OutputValue {

214

value: any;

215

secret: boolean;

216

}

217

```

218

219

## Event System

220

221

```typescript { .api }

222

interface EngineEvent {

223

sequence: number;

224

timestamp: number;

225

}

226

227

interface CancelEvent extends EngineEvent {

228

type: "cancelEvent";

229

}

230

231

interface DiagnosticEvent extends EngineEvent {

232

type: "diagnosticEvent";

233

urn?: string;

234

prefix: string;

235

message: string;

236

color: string;

237

severity: "debug" | "info" | "warning" | "error";

238

streamId?: number;

239

ephemeral?: boolean;

240

}

241

242

interface PreludeEvent extends EngineEvent {

243

type: "preludeEvent";

244

config: { [key: string]: string };

245

}

246

247

interface SummaryEvent extends EngineEvent {

248

type: "summaryEvent";

249

maybeCorrupt: boolean;

250

durationSeconds: number;

251

resourceChanges?: { [key: string]: number };

252

policyPacks?: PolicyPackRunInfo[];

253

}

254

255

interface ResourcePreEvent extends EngineEvent {

256

type: "resourcePreEvent";

257

metadata: StepEventMetadata;

258

}

259

260

interface ResOutputsEvent extends EngineEvent {

261

type: "resOutputsEvent";

262

metadata: StepEventMetadata;

263

}

264

265

interface ResOpFailedEvent extends EngineEvent {

266

type: "resOpFailedEvent";

267

metadata: StepEventMetadata;

268

}

269

```

270

271

## Usage Examples

272

273

### Basic Stack Operations

274

275

```typescript

276

import * as pulumi from "@pulumi/pulumi";

277

import { LocalWorkspace } from "@pulumi/pulumi/automation";

278

279

// Create inline program

280

const program = async () => {

281

const bucket = new pulumi.aws.s3.Bucket("my-bucket");

282

return { bucketName: bucket.id };

283

};

284

285

// Create and deploy stack

286

const stack = await LocalWorkspace.createStack({

287

stackName: "dev",

288

projectName: "my-project",

289

program,

290

});

291

292

// Configure stack

293

await stack.setConfig("aws:region", { value: "us-east-1" });

294

295

// Deploy

296

const upResult = await stack.up();

297

console.log(`Update succeeded. Outputs: ${JSON.stringify(upResult.outputs)}`);

298

```

299

300

### Workspace from Existing Project

301

302

```typescript

303

import { LocalWorkspace, Stack } from "@pulumi/pulumi/automation";

304

305

// Create workspace from existing Pulumi project

306

const workspace = await LocalWorkspace.create({

307

workDir: "./my-pulumi-project",

308

});

309

310

// Select existing stack

311

const stack = await Stack.select("production", workspace);

312

313

// Preview changes

314

const previewResult = await stack.preview();

315

console.log(`Preview completed: ${previewResult.changeSummary}`);

316

317

// Apply if changes look good

318

if (previewResult.changeSummary.create > 0) {

319

const upResult = await stack.up();

320

console.log("Deployment completed");

321

}

322

```

323

324

### Configuration Management

325

326

```typescript

327

import { LocalWorkspace, Stack } from "@pulumi/pulumi/automation";

328

329

const workspace = await LocalWorkspace.create({

330

workDir: "./project",

331

});

332

333

const stack = await Stack.select("staging", workspace);

334

335

// Set multiple configuration values

336

await stack.setAllConfig({

337

"app:environment": { value: "staging" },

338

"app:replica-count": { value: "3" },

339

"app:database-password": { value: "secret123", secret: true },

340

"aws:region": { value: "us-west-2" },

341

});

342

343

// Get configuration

344

const config = await stack.getAllConfig();

345

console.log("Current configuration:", config);

346

347

// Remove configuration

348

await stack.removeConfig("app:old-setting");

349

```

350

351

### Event Monitoring

352

353

```typescript

354

import { LocalWorkspace, Stack } from "@pulumi/pulumi/automation";

355

356

const stack = await Stack.select("production", workspace);

357

358

// Monitor deployment events

359

const upResult = await stack.up({

360

onOutput: (out: string) => {

361

console.log(`Output: ${out}`);

362

},

363

onEvent: (event) => {

364

if (event.type === "diagnosticEvent") {

365

console.log(`${event.severity}: ${event.message}`);

366

} else if (event.type === "resourcePreEvent") {

367

console.log(`Starting ${event.metadata.op} on ${event.metadata.type}`);

368

}

369

},

370

});

371

```

372

373

### Stack History and Rollback

374

375

```typescript

376

import { LocalWorkspace, Stack } from "@pulumi/pulumi/automation";

377

378

const stack = await Stack.select("production", workspace);

379

380

// Get deployment history

381

const history = await stack.history();

382

console.log(`Found ${history.length} deployments`);

383

384

// Find last successful deployment

385

const lastSuccessful = history.find(h => h.result === "succeeded");

386

387

if (lastSuccessful) {

388

console.log(`Last successful deployment: ${lastSuccessful.version}`);

389

390

// Rollback to previous version (manual process)

391

// This would typically involve:

392

// 1. Export the target state

393

// 2. Import it as the current state

394

// 3. Run refresh to sync

395

}

396

```

397

398

### Multi-Stack Management

399

400

```typescript

401

import { LocalWorkspace, Stack } from "@pulumi/pulumi/automation";

402

403

const workspace = await LocalWorkspace.create({

404

workDir: "./infrastructure",

405

});

406

407

const environments = ["dev", "staging", "production"];

408

409

for (const env of environments) {

410

const stack = await Stack.select(env, workspace);

411

412

// Environment-specific configuration

413

const envConfig = {

414

"app:environment": { value: env },

415

"app:replica-count": { value: env === "production" ? "5" : "2" },

416

"aws:region": { value: env === "production" ? "us-east-1" : "us-west-2" },

417

};

418

419

await stack.setAllConfig(envConfig);

420

421

// Deploy with environment-specific options

422

const upResult = await stack.up({

423

parallel: env === "production" ? 1 : 10, // More careful in prod

424

message: `Automated deployment to ${env}`,

425

});

426

427

console.log(`${env} deployment completed`);

428

}

429

```

430

431

### Custom Deployment Tool

432

433

```typescript

434

import { LocalWorkspace, Stack } from "@pulumi/pulumi/automation";

435

436

class DeploymentManager {

437

private workspace: LocalWorkspace;

438

439

constructor(private projectPath: string) {}

440

441

async initialize() {

442

this.workspace = await LocalWorkspace.create({

443

workDir: this.projectPath,

444

});

445

}

446

447

async deployToEnvironment(environment: string, config: Record<string, any>) {

448

const stack = await Stack.createOrSelect(environment, this.workspace);

449

450

// Apply configuration

451

const configValues = Object.entries(config).reduce((acc, [key, value]) => {

452

acc[key] = typeof value === "object" && value.secret

453

? { value: value.value, secret: true }

454

: { value: String(value) };

455

return acc;

456

}, {} as Record<string, any>);

457

458

await stack.setAllConfig(configValues);

459

460

// Preview first

461

console.log(`Previewing changes for ${environment}...`);

462

const previewResult = await stack.preview();

463

464

if (previewResult.changeSummary.create === 0 &&

465

previewResult.changeSummary.update === 0 &&

466

previewResult.changeSummary.delete === 0) {

467

console.log("No changes required");

468

return;

469

}

470

471

// Confirm deployment

472

console.log("Changes detected:", previewResult.changeSummary);

473

474

// Deploy

475

console.log(`Deploying to ${environment}...`);

476

const upResult = await stack.up();

477

478

console.log("Deployment completed successfully");

479

console.log("Outputs:", upResult.outputs);

480

481

return upResult;

482

}

483

484

async listStacks() {

485

const stacks = await this.workspace.listStacks();

486

return stacks.map(s => ({

487

name: s.name,

488

current: s.current,

489

lastUpdate: s.lastUpdate,

490

resourceCount: s.resourceCount,

491

}));

492

}

493

}

494

495

// Usage

496

const manager = new DeploymentManager("./my-infrastructure");

497

await manager.initialize();

498

499

await manager.deployToEnvironment("staging", {

500

"app:environment": "staging",

501

"app:database-password": { value: "secret123", secret: true },

502

"aws:region": "us-west-2",

503

});

504

```

505

506

## Best Practices

507

508

- Use inline programs for simple, dynamic infrastructure

509

- Leverage existing projects for complex, version-controlled infrastructure

510

- Always preview changes before applying in production environments

511

- Use configuration management for environment-specific settings

512

- Monitor deployment events for better observability

513

- Implement proper error handling and rollback strategies

514

- Use parallel deployment settings appropriate for your environment

515

- Store sensitive configuration as secrets

516

- Implement proper access controls for production deployments