
Security News
GitHub Actions Adds cache-mode to Limit Cache Poisoning Risk
GitHub Actions now supports cache-mode, a least-privilege control on the Actions cache aimed at the cache poisoning technique behind recent compromises.
@egulatee/pulumi-stack-alias
Advanced tools
Producer-side stack aliasing for Pulumi using lightweight proxy stacks
Producer-side stack aliasing for Pulumi using lightweight proxy stacks. Consumers use standard StackReference (zero library dependency), while producers use this library to create alias stacks that re-export outputs from canonical stacks.
When managing infrastructure across multiple environments (dev, staging, prod), consumer projects need to reference shared infrastructure stacks. Traditional approaches either:
The aliasing decision belongs with the producer (infrastructure project), not the consumer.
Alias stacks re-export outputs from canonical stacks. Consumers use standard Pulumi StackReference with no library dependency. Producers use this library to create lightweight proxy stacks.
infrastructure/shared → canonical stack, exports real resources
infrastructure/dev → proxy stack, re-exports outputs from shared
infrastructure/staging → proxy stack, re-exports outputs from shared
infrastructure/prod → canonical stack, exports real resources
Consumer uses standard Pulumi:
const stack = new pulumi.StackReference(`org/infrastructure/${pulumi.getStack()}`);
const vpcId = stack.requireOutput("vpcId");
Zero consumer dependencies! The consumer has no knowledge of aliasing. When application/dev deploys, it reads infrastructure/dev, which is a proxy stack that re-exports outputs from infrastructure/shared.
Producer projects only:
npm install @egulatee/pulumi-stack-alias
Consumer projects: No installation needed! Use standard Pulumi StackReference.
Create alias stacks that re-export outputs from canonical stacks:
// infrastructure/index.ts
import { createStackAlias } from "@egulatee/pulumi-stack-alias";
import * as pulumi from "@pulumi/pulumi";
const config = new pulumi.Config();
const aliasTarget = config.get("aliasTarget");
if (aliasTarget) {
// This is an alias stack — re-export outputs from target
const alias = createStackAlias({
targetProject: "infrastructure",
targetStack: aliasTarget,
outputs: ["vpcId", "endpoint", "clusterName"],
});
export const vpcId = alias.vpcId;
export const endpoint = alias.endpoint;
export const clusterName = alias.clusterName;
} else {
// This is a canonical stack — create actual resources
const vpc = new aws.ec2.Vpc("main", {
cidrBlock: "10.0.0.0/16",
});
export const vpcId = vpc.id;
export const endpoint = pulumi.output("https://api.example.com");
export const clusterName = pulumi.output("my-cluster");
}
Configure your stack files:
# infrastructure/Pulumi.shared.yaml
config:
# No aliasTarget — this is the canonical stack
# infrastructure/Pulumi.dev.yaml
config:
infrastructure:aliasTarget: shared
# infrastructure/Pulumi.staging.yaml
config:
infrastructure:aliasTarget: shared
# infrastructure/Pulumi.prod.yaml
config:
# No aliasTarget — this is a canonical stack (separate from shared)
For automatic aliasing without config:
// infrastructure/index.ts
import { createConditionalAlias } from "@egulatee/pulumi-stack-alias";
const alias = createConditionalAlias({
targetProject: "infrastructure",
patterns: [
{ pattern: "*/prod", target: "prod" },
{ pattern: "*/staging", target: "shared" },
{ pattern: "*/dev", target: "shared" },
{ pattern: "*/*-ephemeral", target: "shared" },
],
defaultTarget: "shared",
outputs: ["vpcId", "endpoint", "clusterName"],
});
export const vpcId = alias.vpcId;
export const endpoint = alias.endpoint;
export const clusterName = alias.clusterName;
Simplified API for common cases:
import { createSimpleAlias } from "@egulatee/pulumi-stack-alias";
const alias = createSimpleAlias("infrastructure", "shared", ["vpcId"]);
export const vpcId = alias.vpcId;
Use standard Pulumi StackReference — no library dependency:
// application/index.ts
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
// Standard Pulumi StackReference — no special library needed!
const infraStack = new pulumi.StackReference(
`${pulumi.getOrganization()}/infrastructure/${pulumi.getStack()}`
);
const vpcId = infraStack.requireOutput("vpcId");
const endpoint = infraStack.requireOutput("endpoint");
const subnet = new aws.ec2.Subnet("app-subnet", {
vpcId: vpcId,
cidrBlock: "10.0.1.0/24",
});
The consumer has zero knowledge of aliasing. When application/dev deploys:
infrastructure/dev (a proxy stack)infrastructure/shared)# Deploy canonical stacks (creates real resources)
pulumi up --stack shared
pulumi up --stack prod
# Deploy alias stacks (creates proxy outputs)
pulumi up --stack dev
pulumi up --stack staging
# Consumer deployments — no alias awareness needed
cd application && pulumi up --stack dev
Alias stacks capture outputs at deploy time. When canonical stack outputs change, redeploy aliases:
# Update canonical stack
pulumi up --stack shared
# Sync alias stacks (fast — no real resources)
pulumi up --stack dev
pulumi up --stack staging
Automate alias synchronization in CI/CD:
# .github/workflows/deploy.yml
jobs:
deploy-canonical:
runs-on: ubuntu-latest
steps:
- name: Deploy shared stack
run: pulumi up --stack shared --yes
sync-aliases:
needs: deploy-canonical
runs-on: ubuntu-latest
strategy:
matrix:
stack: [dev, staging]
steps:
- name: Sync alias stack
run: pulumi up --stack ${{ matrix.stack }} --yes
Alias deployments are fast (seconds) since they create no real resources — just re-export outputs.
createStackAlias(config)Creates a stack alias that re-exports outputs from a target stack.
Parameters:
config.targetProject (string) - Target project nameconfig.targetStack (string) - Target stack nameconfig.targetOrg (optional string) - Target organization (defaults to current org)config.outputs (string[]) - List of output names to re-exportReturns: AliasExports - Record of Pulumi Outputs
Example:
const alias = createStackAlias({
targetProject: "infrastructure",
targetStack: "shared",
outputs: ["vpcId", "endpoint"],
});
export const vpcId = alias.vpcId;
export const endpoint = alias.endpoint;
createConditionalAlias(config)Creates a conditional alias based on pattern matching.
Parameters:
config.targetProject (string) - Target project nameconfig.patterns (PatternRule[]) - Pattern matching rules (evaluated in order, first match wins)config.defaultTarget (optional string) - Default target if no pattern matchesconfig.targetOrg (optional string) - Target organization (defaults to current org)config.outputs (string[]) - List of output names to re-exportReturns: AliasExports - Record of Pulumi Outputs
Example:
const alias = createConditionalAlias({
targetProject: "infrastructure",
patterns: [
{ pattern: "*/prod", target: "prod" },
{ pattern: "*/dev", target: "shared" },
],
defaultTarget: "shared",
outputs: ["vpcId"],
});
createSimpleAlias(targetProject, targetStack, outputs)Simplified API for creating aliases.
Parameters:
targetProject (string) - Target project nametargetStack (string) - Target stack nameoutputs (string[]) - List of output names to re-exportReturns: AliasExports - Record of Pulumi Outputs
Example:
const alias = createSimpleAlias("infrastructure", "shared", ["vpcId"]);
export const vpcId = alias.vpcId;
matchesPattern(pattern, project, stack)Pattern matching with wildcard support.
Wildcard rules:
* matches any value*-suffix matches strings ending with -suffixprefix-* matches strings starting with prefix-exact matches exactlyExample:
import { matchesPattern } from "@egulatee/pulumi-stack-alias";
matchesPattern("*/dev", "myproject", "dev") // true
matchesPattern("*/*-ephemeral", "app", "pr-123-ephemeral") // true
matchesPattern("app-*/prod-*", "app-api", "prod-us") // true
Patterns follow the format: "projectPattern/stackPattern"
Examples:
"*/dev" - Any project, stack must be "dev""myproject/*" - Project must be "myproject", any stack"*/*-ephemeral" - Any project, stack must end with "-ephemeral""app-*/prod-*" - Project must start with "app-", stack must start with "prod-"| Concern | Producer Redirect (v0.1.0) | Producer Proxy (v0.2.0) | Consumer Config |
|---|---|---|---|
| Who owns mapping | Producer ✓ | Producer ✓ | Consumer |
| Consumer library dependency | Yes | None ✓ | Varies |
| Alias stack weight | Trivial (one pointer) | Light (output refs) | N/A |
| Output freshness | Always live ✓ | Stale until redeployed* | Always live ✓ |
| Consumer code | resolveStackRef(...) | new StackReference(...) ✓ | Custom |
| CI/CD orchestration | Not needed | Recommended | Not needed |
* Mitigated with CI/CD automation — alias deployments are fast (seconds)
✅ Zero consumer dependencies - Consumers use standard Pulumi StackReference
✅ Producer-controlled - Infrastructure projects own aliasing decisions
✅ Type-safe - Full TypeScript support
✅ Flexible patterns - Wildcard pattern matching for conditional aliasing
✅ CI/CD friendly - Fast alias deployments (no real resources)
✅ Simple API - Three functions cover all use cases
Pros:
Cons:
Deploy infrastructure once, route dev/staging to it:
const alias = createConditionalAlias({
targetProject: "infrastructure",
patterns: [
{ pattern: "*/prod", target: "prod" },
],
defaultTarget: "shared",
outputs: ["vpcId", "endpoint"],
});
Route ephemeral stacks to shared infrastructure:
const alias = createConditionalAlias({
targetProject: "infrastructure",
patterns: [
{ pattern: "*/*-ephemeral", target: "shared" },
{ pattern: "*/prod", target: "prod" },
],
defaultTarget: "shared",
outputs: ["vpcId"],
});
Route regional stacks to regional infrastructure:
const alias = createConditionalAlias({
targetProject: "infrastructure",
patterns: [
{ pattern: "*/us-*", target: "us-east" },
{ pattern: "*/eu-*", target: "eu-west" },
],
outputs: ["vpcId"],
});
See the examples directory for complete implementations:
This is a breaking change — complete API rewrite.
Before (v0.1.0):
// infrastructure/index.ts
const config = new pulumi.Config();
const aliasTarget = config.get("aliasTarget");
if (aliasTarget) {
export const _canonicalStack = aliasTarget;
} else {
export const vpcId = vpc.id;
}
After (v0.2.0):
// infrastructure/index.ts
import { createStackAlias } from "@egulatee/pulumi-stack-alias";
const config = new pulumi.Config();
const aliasTarget = config.get("aliasTarget");
if (aliasTarget) {
const alias = createStackAlias({
targetProject: "infrastructure",
targetStack: aliasTarget,
outputs: ["vpcId", "endpoint"],
});
export const vpcId = alias.vpcId;
export const endpoint = alias.endpoint;
} else {
export const vpcId = vpc.id;
export const endpoint = /* ... */;
}
Before (v0.1.0):
import { resolveStackRef } from "@egulatee/pulumi-stack-alias";
const infraStack = resolveStackRef("infrastructure");
const vpcId = infraStack.apply(ref => ref.requireOutput("vpcId"));
After (v0.2.0):
// NO LIBRARY IMPORT NEEDED!
const infraStack = new pulumi.StackReference(
`${pulumi.getOrganization()}/infrastructure/${pulumi.getStack()}`
);
const vpcId = infraStack.requireOutput("vpcId");
@egulatee/pulumi-stack-alias@^0.2.0_canonicalStack exports with createStackAlias() callsresolveStackRef() with standard new StackReference()@egulatee/pulumi-stack-alias from consumer projectsContributions are welcome! Please see the GitHub issues for planned features and enhancements.
MIT © Eric Gulatee
FAQs
Producer-side stack aliasing for Pulumi using lightweight proxy stacks
The npm package @egulatee/pulumi-stack-alias receives a total of 2 weekly downloads. As such, @egulatee/pulumi-stack-alias popularity was classified as not popular.
We found that @egulatee/pulumi-stack-alias demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.

Security News
GitHub Actions now supports cache-mode, a least-privilege control on the Actions cache aimed at the cache poisoning technique behind recent compromises.

Company News
Allow myself to introduce... myself.

Research
/Security News
A Twitch browser extension on Chrome and Firefox forwards users’ live OAuth session tokens through proxies controlled by a Russian bot service.