Skip to main content

Deployment Workflow

This guide covers the day-to-day workflow for managing infrastructure with Pulumi.

Daily Operations

1. Select Environment

Always start by selecting your target environment:

cd infra
source env.sh dev # or test, prod

2. Preview Changes

Review what Pulumi will do before applying:

pulumi preview

Example output:

Previewing update (dev):
Type Name Plan
+ pulumi:pulumi:Stack serko-northsky-dev create
+ ├─ serko:gcp:Network network create
+ │ ├─ gcp:compute:Network vpc create
+ │ ├─ gcp:compute:Subnetwork gke-subnet create
+ │ └─ gcp:compute:Subnetwork private-subnet create
...

Resources:
+ 45 to create

3. Apply Changes

Deploy the infrastructure:

pulumi up

Pulumi will show the preview again and ask for confirmation:

Do you want to perform this update? [Use arrows to move, type to filter]
> yes
no
details

4. View Outputs

After deployment, view the stack outputs:

pulumi stack output

Example outputs:

Current stack outputs (15):
OUTPUT VALUE
artifactRegistryUrl us-central1-docker.pkg.dev/serko-northsky-dev/serko-northsky
clusterEndpoint 34.123.45.67
databaseUrl [secret]
environment dev
gkeClusterName serko-northsky-cluster
projectId serko-northsky-dev
...

Common Operations

Update a Single Resource

To update only specific resources:

# Preview changes to network only
pulumi preview --target 'urn:pulumi:dev::serko-northsky::serko:gcp:Network::network'

# Apply changes to network only
pulumi up --target 'urn:pulumi:dev::serko-northsky::serko:gcp:Network::network'

Refresh State

Sync Pulumi state with actual GCP resources:

pulumi refresh

Use this when:

  • Resources were modified outside Pulumi
  • State seems out of sync
  • After importing existing resources

View Resource Details

# List all resources in stack
pulumi stack --show-urns

# Export full state (JSON)
pulumi stack export

Access Secret Outputs

# View secret value
pulumi stack output databaseUrl --show-secrets

Importing Existing Resources

To import existing GCP resources into Pulumi:

1. Use Import Script

./scripts/import-existing.sh dev

This script imports common resources like:

  • VPC networks
  • Subnets
  • GKE clusters
  • Storage buckets

2. Manual Import

# Import a specific resource
pulumi import gcp:compute/network:Network vpc projects/PROJECT_ID/global/networks/serko-northsky-vpc

3. Update Code

After import, ensure your Pulumi code matches the imported resource configuration.

Destroying Infrastructure

Warning

Destroying infrastructure is irreversible. Always verify you're targeting the correct environment.

Preview Destruction

pulumi destroy --preview-only

Destroy Resources

pulumi destroy

Delete Stack

After destroying resources, remove the stack:

pulumi stack rm dev

Troubleshooting

Authentication Errors

error: getting credentials: exec: executable gcloud not found

Solution: Ensure gcloud is installed and env.sh was sourced:

source env.sh dev
gcloud auth list # Verify authentication

State Lock Errors

error: the stack is currently locked

Solution: Another operation may be in progress. If not, unlock:

pulumi cancel

Resource Already Exists

error: resource already exists

Solution: Import the existing resource:

pulumi import gcp:compute/network:Network vpc projects/PROJECT/global/networks/NAME

Dependency Errors

error: resource depends on a resource that failed

Solution: Fix the failing resource first, or use --target to update specific resources.

CI/CD Integration

GitHub Actions Example

name: Infrastructure Deploy

on:
push:
branches: [main]
paths:
- 'infra/pulumi/**'

jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'

- name: Install Pulumi
uses: pulumi/actions@v5

- name: Setup GCP Auth
uses: google-github-actions/auth@v2
with:
credentials_json: ${{ secrets.GCP_SA_KEY }}

- name: Install Dependencies
run: |
cd infra/pulumi
pnpm install --ignore-workspace

- name: Deploy
run: |
cd infra/pulumi
pulumi login gs://serko-northsky-pulumi-state
pulumi stack select prod
pulumi up --yes
env:
PULUMI_CONFIG_PASSPHRASE: ${{ secrets.PULUMI_PASSPHRASE }}

Required Secrets

SecretDescription
GCP_SA_KEYService account JSON key
PULUMI_PASSPHRASEPassphrase for encrypted config

Best Practices

Always Preview First

Never run pulumi up without reviewing the preview, especially in production.

Use Targeted Updates

When making small changes, use --target to limit the blast radius.

Protect Production

  • Require approval for production deployments
  • Use separate service accounts per environment
  • Enable deletion protection on critical resources

Version Control

  • Commit all configuration changes
  • Use meaningful commit messages
  • Review infrastructure changes in PRs

Monitor Deployments

  • Check GCP Console after deployments
  • Verify application connectivity
  • Monitor for any error alerts