Skip to content
Open
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
fd174a0
chore: update vitest
MengLinMaker Jan 26, 2026
1d2f245
Revert "chore: update vitest"
MengLinMaker Jan 27, 2026
0d5097f
draft image component
MengLinMaker Jan 29, 2026
43a7d80
prettier
MengLinMaker Jan 29, 2026
013b303
export image
MengLinMaker Jan 29, 2026
6b0929f
implement missing args
MengLinMaker Jan 29, 2026
576bc66
update sst to use latest
MengLinMaker Jan 29, 2026
8bf8856
add image digest mainly for internal use
MengLinMaker Jan 29, 2026
b5a01dd
refactor fargate to use new image component
MengLinMaker Jan 29, 2026
e552538
fix: add name prefix to prevent pulumi component name clash
MengLinMaker Mar 2, 2026
844979d
refactor function to use new image component
MengLinMaker Mar 2, 2026
60bc639
fix: avoid flaky digest deploy issue with digestless and tagless imag…
MengLinMaker Mar 2, 2026
5d5b26a
uri should be in ecr@digest format to use specific container version
MengLinMaker Mar 2, 2026
ef2cecd
no idea what node() is used for
MengLinMaker Mar 2, 2026
2fa3000
fargate should use uri directly
MengLinMaker Mar 2, 2026
a840d37
config to generate image doc page with tsdoc
MengLinMaker Mar 3, 2026
e8a69fa
extract Platform type which could not be processed by doc generator
MengLinMaker Mar 3, 2026
022506a
remove unused variables
MengLinMaker Mar 3, 2026
8d7752d
Record type can be doc generated
MengLinMaker Mar 3, 2026
7b84ec1
add examples to doc
MengLinMaker Mar 3, 2026
974af5d
support image compression
MengLinMaker Mar 3, 2026
008fbc6
Handle `assumeRoles` array format from Pulumi AWS v7 (#6522)
vimtor Mar 4, 2026
ba01a21
Merge branch 'dev' into feat-sst-image
MengLinMaker Mar 4, 2026
547703e
doc: alternative SOCI indexing only supports gzip
MengLinMaker Mar 4, 2026
fea4451
revert unecessary code changes
MengLinMaker Mar 28, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion examples/aws-task/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@
"author": "",
"license": "ISC",
"dependencies": {
"sst": "^4"
"sst": "latest"
Comment thread
MengLinMaker marked this conversation as resolved.
Outdated
}
}
16 changes: 10 additions & 6 deletions pkg/project/provider/aws.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,13 +92,17 @@ func (a *AwsProvider) Init(app string, stage string, args map[string]interface{}
if err != nil {
return err
}
if assumeRole, ok := args["assumeRole"].(map[string]interface{}); ok {
stsclient := sts.NewFromConfig(cfg)
cfg.Credentials = stscreds.NewAssumeRoleProvider(stsclient, assumeRole["roleArn"].(string), func(aro *stscreds.AssumeRoleOptions) {
if sessionName, ok := assumeRole["sessionName"].(string); ok {
aro.RoleSessionName = sessionName
if assumeRoles, ok := args["assumeRoles"].([]interface{}); ok {
for _, role := range assumeRoles {
if roleMap, ok := role.(map[string]interface{}); ok {
stsclient := sts.NewFromConfig(cfg)
cfg.Credentials = stscreds.NewAssumeRoleProvider(stsclient, roleMap["roleArn"].(string), func(aro *stscreds.AssumeRoleOptions) {
if sessionName, ok := roleMap["sessionName"].(string); ok {
aro.RoleSessionName = sessionName
}
})
}
})
}
}
_, err = cfg.Credentials.Retrieve(ctx)
if err != nil {
Expand Down
97 changes: 14 additions & 83 deletions platform/src/components/aws/fargate.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import fs from "fs";
import path from "path";
import { ComponentResourceOptions, interpolate, secret } from "@pulumi/pulumi";
import { all, output } from "@pulumi/pulumi";
import { Input } from "../input";
Expand All @@ -13,7 +11,6 @@ import { ImageArgs, Platform } from "@pulumi/docker-build";
import { Component, Transform, transform } from "../component";
import {
cloudwatch,
ecr,
ecs,
getCallerIdentityOutput,
getPartitionOutput,
Expand All @@ -23,11 +20,11 @@ import {
import { Link } from "../link";
import { Permission } from "./permission";
import { bootstrap } from "./helpers/bootstrap";
import { imageBuilder } from "./helpers/container-builder";
import { toNumber } from "../cpu";
import { toSeconds } from "../duration";
import { Cluster } from "./cluster";
import { physicalName } from "../naming";
import { Image } from "./image";

export const supportedCpus = {
"0.25 vCPU": 256,
Expand Down Expand Up @@ -1052,86 +1049,20 @@ export function createTaskDefinition(
image: (() => {
if (typeof container.image === "string") return output(container.image);

const containerImage = container.image;
const contextPath = path.join($cli.paths.root, container.image.context);
const dockerfile = container.image.dockerfile ?? "Dockerfile";
const dockerfilePath = path.join(contextPath, dockerfile);
const dockerIgnorePath = fs.existsSync(
path.join(contextPath, `${dockerfile}.dockerignore`),
)
? path.join(contextPath, `${dockerfile}.dockerignore`)
: path.join(contextPath, ".dockerignore");

// add .sst to .dockerignore if not exist
const lines = fs.existsSync(dockerIgnorePath)
? fs.readFileSync(dockerIgnorePath).toString().split("\n")
: [];
if (!lines.find((line) => line === ".sst")) {
fs.writeFileSync(
dockerIgnorePath,
[...lines, "", "# sst", ".sst"].join("\n"),
);
}

// Build image
const image = imageBuilder(
...transform(
args.transform?.image,
`${name}Image${container.name}`,
{
context: { location: contextPath },
dockerfile: { location: dockerfilePath },
buildArgs: containerImage.args,
secrets: all([linkEnvs, containerImage.secrets ?? {}]).apply(
([link, secrets]) => ({ ...link, ...secrets }),
),
target: container.image.target,
platforms: [container.image.platform],
tags: [container.name, ...(container.image.tags ?? [])].map(
(tag) => interpolate`${bootstrapData.assetEcrUrl}:${tag}`,
),
registries: [
ecr
.getAuthorizationTokenOutput(
{
registryId: bootstrapData.assetEcrRegistryId,
},
{ parent },
)
.apply((authToken) => ({
address: authToken.proxyEndpoint,
password: secret(authToken.password),
username: authToken.userName,
})),
],
...(container.image.cache !== false
? {
cacheFrom: [
{
registry: {
ref: interpolate`${bootstrapData.assetEcrUrl}:${container.name}-cache`,
},
},
],
cacheTo: [
{
registry: {
ref: interpolate`${bootstrapData.assetEcrUrl}:${container.name}-cache`,
imageManifest: true,
ociMediaTypes: true,
mode: "max",
},
},
],
}
: {}),
push: true,
},
{ parent },
),
);
const image = new Image(`${name}${container.name}`, {
context: container.image.context,
dockerfile: container.image.dockerfile,
args: container.image.args,
secrets: linkEnvs,
target: container.image.target,
platforms: [container.image.platform],
tags: [container.name, ...(container.image.tags ?? [])],
transform: {
image: args.transform?.image,
},
});
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same { parent } thing


return interpolate`${bootstrapData.assetEcrUrl}@${image.digest}`;
return image.uri;
})(),
cpu: container.cpu ? toNumber(container.cpu) : undefined,
memory: container.memory ? toMBs(container.memory) : undefined,
Expand Down
72 changes: 9 additions & 63 deletions platform/src/components/aws/function.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ import {
} from "@pulumi/aws";
import { Permission, permission } from "./permission.js";
import { Vpc } from "./vpc.js";
import { Image } from "@pulumi/docker-build";
import { Image } from "./image";
import { rpc } from "../rpc/rpc.js";
import { parseRoleArn } from "./helpers/arn.js";
import { RandomBytes } from "@pulumi/random";
Expand Down Expand Up @@ -2234,67 +2234,15 @@ export class Function extends Component implements Link.Linkable {
// The build artifact directory already exists, with all the user code and
// config files. It also has the dockerfile, we need to now just build and push to
// the container registry.
return all([isContainer, dev, bundle, containerCache]).apply(
([
isContainer,
dev,
bundle, // We need the bundle to be resolved because of implicit dockerfiles even though we don't use it here
containerCache,
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we are no longer using this variable, perhaps we can remove it?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Which variable? bundle is already removed

]) => {
if (!isContainer || dev) return;

const authToken = ecr.getAuthorizationTokenOutput({
registryId: bootstrapData.assetEcrRegistryId,
return all([isContainer, dev, architecture]).apply(
([isContainer, dev, architecture]) => {
if (!isContainer || dev) return;
return new Image(name, {
context: `.sst/artifacts/${name}-src`,
tags: ['latest'],
platforms: [architecture === "arm64" ? "linux/arm64" : "linux/amd64"],
});
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should pass { parent } like we do for other nested components

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same { parent } thing


return new Image(
`${name}Image`,
{
tags: [$interpolate`${bootstrapData.assetEcrUrl}:latest`],
context: {
location: path.join(
$cli.paths.work,
"artifacts",
`${name}-src`,
),
},
...(containerCache !== false
? {
cacheFrom: [
{
registry: {
ref: $interpolate`${bootstrapData.assetEcrUrl}:${name}-cache`,
},
},
],
cacheTo: [
{
registry: {
ref: $interpolate`${bootstrapData.assetEcrUrl}:${name}-cache`,
imageManifest: true,
ociMediaTypes: true,
mode: "max",
},
},
],
}
: {}),
platforms: [
architecture.apply((v) =>
v === "arm64" ? "linux/arm64" : "linux/amd64",
),
],
push: true,
registries: [
authToken.apply((authToken) => ({
address: authToken.proxyEndpoint,
username: authToken.userName,
password: secret(authToken.password),
})),
],
},
{ parent },
);
},
);
}
Expand Down Expand Up @@ -2513,9 +2461,7 @@ export class Function extends Component implements Link.Linkable {
...(isContainer
? {
packageType: "Image",
imageUri: imageAsset!.ref.apply(
(ref) => ref?.replace(":latest", ""),
),
imageUri: imageAsset!.uri,
imageConfig: {
commands: [
all([handler, runtime]).apply(([handler, runtime]) => {
Expand Down
32 changes: 0 additions & 32 deletions platform/src/components/aws/helpers/container-builder.ts

This file was deleted.

Loading