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
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
| Secret | Description |
|---|---|
GCP_SA_KEY | Service account JSON key |
PULUMI_PASSPHRASE | Passphrase 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