mirror of
https://github.com/anomalyco/opencode.git
synced 2026-07-21 18:26:09 +00:00
+18




![opencode-agent[bot] <opencode-agent[bot]@users.noreply.github.com>](/assets/img/avatar_default.png)

![opencode-agent[bot] <219766164+opencode-agent[bot]@users.noreply.github.com>](/assets/img/avatar_default.png)

![opencode-agent[bot]](/assets/img/avatar_default.png)
opencode-agent[bot]
GitHub
opencode-agent[bot] <219766164+opencode-agent[bot]@users.noreply.github.com>
LukeParkerDev
opencode-agent[bot] <opencode-agent[bot]@users.noreply.github.com>
Aiden Cline
Brendan Allan
Aarav Sareen
Julian Coy
Brendan Allan
usrnk1
opencode
Vladimir Glafirov
Adam
Frank
Jay
Dustin Deus
Kit Langton
James Long
Simon Klee
Jay
Jack
David Hill
Aiden Cline
James Long
冯基魁
Aiden Cline
Victor Navarro
43ecf3ff1b
Co-authored-by: opencode-agent[bot] <219766164+opencode-agent[bot]@users.noreply.github.com> Co-authored-by: LukeParkerDev <10430890+Hona@users.noreply.github.com> Co-authored-by: opencode-agent[bot] <opencode-agent[bot]@users.noreply.github.com> Co-authored-by: Aiden Cline <63023139+rekram1-node@users.noreply.github.com> Co-authored-by: Brendan Allan <14191578+Brendonovich@users.noreply.github.com> Co-authored-by: Aarav Sareen <96787824+arvsrn@users.noreply.github.com> Co-authored-by: Julian Coy <julian@ex-machina.co> Co-authored-by: Brendan Allan <git@brendonovich.dev> Co-authored-by: usrnk1 <7547651+usrnk1@users.noreply.github.com> Co-authored-by: opencode <opencode@sst.dev> Co-authored-by: Vladimir Glafirov <vglafirov@gitlab.com> Co-authored-by: Adam <2363879+adamdotdevin@users.noreply.github.com> Co-authored-by: Frank <frank@anoma.ly> Co-authored-by: Jay <53023+jayair@users.noreply.github.com> Co-authored-by: Dustin Deus <deusdustin@gmail.com> Co-authored-by: Kit Langton <kit.langton@gmail.com> Co-authored-by: James Long <longster@gmail.com> Co-authored-by: Simon Klee <hello@simonklee.dk> Co-authored-by: Jay <air@live.ca> Co-authored-by: Jack <jack@anoma.ly> Co-authored-by: David Hill <1879069+iamdavidhill@users.noreply.github.com> Co-authored-by: Aiden Cline <aidenpcline@gmail.com> Co-authored-by: James Long <jlongster@users.noreply.github.com> Co-authored-by: 冯基魁 <56265583+fengjikui@users.noreply.github.com> Co-authored-by: Aiden Cline <rekram1-node@users.noreply.github.com> Co-authored-by: Victor Navarro <vn4varro@gmail.com>
332 lines
10 KiB
TypeScript
332 lines
10 KiB
TypeScript
import { domain } from "./stage"
|
|
|
|
const current = aws.getCallerIdentityOutput({})
|
|
const partition = aws.getPartitionOutput({})
|
|
const region = aws.getRegionOutput({})
|
|
|
|
const tableBucketName = `opencode-${$app.stage}-lake`
|
|
const glueCatalogName = "s3tablescatalog"
|
|
const glueCatalogArn = $interpolate`arn:${partition.partition}:glue:${region.region}:${current.accountId}:catalog`
|
|
const glueS3TablesCatalogArn = $interpolate`${glueCatalogArn}/${glueCatalogName}`
|
|
const glueS3TablesChildCatalogArn = $interpolate`${glueS3TablesCatalogArn}/${tableBucketName}`
|
|
const glueS3TablesDatabaseWildcardArn = $interpolate`arn:${partition.partition}:glue:${region.region}:${current.accountId}:database/${glueCatalogName}/${tableBucketName}/*`
|
|
const glueS3TablesTableWildcardArn = $interpolate`arn:${partition.partition}:glue:${region.region}:${current.accountId}:table/${glueCatalogName}/${tableBucketName}/*/*`
|
|
const s3TablesBucketWildcardArn = $interpolate`arn:${partition.partition}:s3tables:${region.region}:${current.accountId}:bucket/*`
|
|
|
|
export const tableBucket = new aws.s3tables.TableBucket("LakeTableBucket", {
|
|
name: tableBucketName,
|
|
forceDestroy: $app.stage !== "production",
|
|
})
|
|
|
|
const s3TablesCatalog = new aws.cloudcontrol.Resource(
|
|
"LakeS3TablesCatalog",
|
|
{
|
|
typeName: "AWS::Glue::Catalog",
|
|
desiredState: $jsonStringify({
|
|
Name: glueCatalogName,
|
|
Description: "Federated catalog for S3 Tables",
|
|
FederatedCatalog: {
|
|
Identifier: s3TablesBucketWildcardArn,
|
|
ConnectionName: "aws:s3tables",
|
|
},
|
|
CreateDatabaseDefaultPermissions: [
|
|
{
|
|
Principal: {
|
|
DataLakePrincipalIdentifier: "IAM_ALLOWED_PRINCIPALS",
|
|
},
|
|
Permissions: ["ALL"],
|
|
},
|
|
],
|
|
CreateTableDefaultPermissions: [
|
|
{
|
|
Principal: {
|
|
DataLakePrincipalIdentifier: "IAM_ALLOWED_PRINCIPALS",
|
|
},
|
|
Permissions: ["ALL"],
|
|
},
|
|
],
|
|
AllowFullTableExternalDataAccess: "True",
|
|
}),
|
|
},
|
|
{ dependsOn: [tableBucket] },
|
|
)
|
|
|
|
const athenaResultsBucket = new aws.s3.Bucket("LakeAthenaResults", {
|
|
bucket: `opencode-${$app.stage}-lake-athena-results`,
|
|
forceDestroy: $app.stage !== "production",
|
|
})
|
|
|
|
const firehoseErrorBucket = new aws.s3.Bucket("LakeFirehoseErrors", {
|
|
bucket: `opencode-${$app.stage}-lake-firehose-errors`,
|
|
forceDestroy: $app.stage !== "production",
|
|
})
|
|
|
|
const athenaWorkgroup = new aws.athena.Workgroup("LakeAthenaWorkgroup", {
|
|
name: `opencode-${$app.stage}-lake-workgroup`,
|
|
forceDestroy: $app.stage !== "production",
|
|
configuration: {
|
|
enforceWorkgroupConfiguration: true,
|
|
publishCloudwatchMetricsEnabled: true,
|
|
// Athena bills $5/TB scanned; kill any query that would scan more than 2 TB
|
|
// so a regression cannot silently burn money. Stats sync full passes scan
|
|
// ~250 GB as of 2026-07.
|
|
bytesScannedCutoffPerQuery: 2 * 1024 ** 4,
|
|
resultConfiguration: {
|
|
outputLocation: $interpolate`s3://${athenaResultsBucket.bucket}/`,
|
|
},
|
|
},
|
|
})
|
|
|
|
const firehoseRole = new aws.iam.Role("LakeFirehoseRole", {
|
|
assumeRolePolicy: aws.iam.getPolicyDocumentOutput({
|
|
statements: [
|
|
{
|
|
effect: "Allow",
|
|
actions: ["sts:AssumeRole"],
|
|
principals: [
|
|
{
|
|
type: "Service",
|
|
identifiers: ["firehose.amazonaws.com"],
|
|
},
|
|
],
|
|
},
|
|
],
|
|
}).json,
|
|
})
|
|
|
|
const firehosePolicy = new aws.iam.RolePolicy("LakeFirehosePolicy", {
|
|
role: firehoseRole.id,
|
|
policy: aws.iam.getPolicyDocumentOutput({
|
|
statements: [
|
|
{
|
|
effect: "Allow",
|
|
actions: [
|
|
"s3tables:ListTableBuckets",
|
|
"s3tables:GetTableBucket",
|
|
"s3tables:GetNamespace",
|
|
"s3tables:GetTable",
|
|
"s3tables:GetTableData",
|
|
"s3tables:GetTableMetadataLocation",
|
|
"s3tables:ListNamespaces",
|
|
"s3tables:ListTables",
|
|
"s3tables:PutTableData",
|
|
"s3tables:UpdateTableMetadataLocation",
|
|
],
|
|
resources: ["*"],
|
|
},
|
|
{
|
|
effect: "Allow",
|
|
actions: [
|
|
"glue:GetCatalog",
|
|
"glue:GetCatalogs",
|
|
"glue:GetDatabase",
|
|
"glue:GetDatabases",
|
|
"glue:GetTable",
|
|
"glue:GetTables",
|
|
"glue:UpdateTable",
|
|
],
|
|
resources: [
|
|
glueCatalogArn,
|
|
glueS3TablesCatalogArn,
|
|
$interpolate`${glueS3TablesCatalogArn}/*`,
|
|
glueS3TablesDatabaseWildcardArn,
|
|
glueS3TablesTableWildcardArn,
|
|
$interpolate`arn:${partition.partition}:glue:${region.region}:${current.accountId}:database/*`,
|
|
$interpolate`arn:${partition.partition}:glue:${region.region}:${current.accountId}:table/*/*`,
|
|
$interpolate`arn:${partition.partition}:glue:${region.region}:${current.accountId}:table/${glueCatalogName}/*`,
|
|
],
|
|
},
|
|
{
|
|
effect: "Allow",
|
|
actions: [
|
|
"s3:AbortMultipartUpload",
|
|
"s3:GetBucketLocation",
|
|
"s3:GetObject",
|
|
"s3:ListBucket",
|
|
"s3:ListBucketMultipartUploads",
|
|
"s3:PutObject",
|
|
],
|
|
resources: [firehoseErrorBucket.arn, $interpolate`${firehoseErrorBucket.arn}/*`],
|
|
},
|
|
{
|
|
effect: "Allow",
|
|
actions: ["lakeformation:GetDataAccess"],
|
|
resources: ["*"],
|
|
},
|
|
],
|
|
}).json,
|
|
})
|
|
|
|
const firehose = new aws.kinesis.FirehoseDeliveryStream(
|
|
"LakeFirehose",
|
|
{
|
|
name: `opencode-${$app.stage}-lake-ingest`,
|
|
destination: "iceberg",
|
|
icebergConfiguration: {
|
|
appendOnly: true,
|
|
bufferingInterval: 60,
|
|
bufferingSize: 1,
|
|
catalogArn: glueS3TablesChildCatalogArn,
|
|
processingConfiguration: {
|
|
enabled: true,
|
|
processors: [
|
|
{
|
|
type: "MetadataExtraction",
|
|
parameters: [
|
|
{ parameterName: "JsonParsingEngine", parameterValue: "JQ-1.6" },
|
|
{
|
|
parameterName: "MetadataExtractionQuery",
|
|
parameterValue:
|
|
'{destinationDatabaseName:._lake_database,destinationTableName:._lake_table,operation:(._lake_operation // "insert")}',
|
|
},
|
|
],
|
|
},
|
|
],
|
|
},
|
|
roleArn: firehoseRole.arn,
|
|
s3BackupMode: "FailedDataOnly",
|
|
s3Configuration: {
|
|
roleArn: firehoseRole.arn,
|
|
bucketArn: firehoseErrorBucket.arn,
|
|
errorOutputPrefix: "errors/!{firehose:error-output-type}/",
|
|
},
|
|
},
|
|
},
|
|
{ dependsOn: [s3TablesCatalog, firehosePolicy] },
|
|
)
|
|
|
|
export const lakeVpc = new sst.aws.Vpc("LakeVpc")
|
|
export const lakeCluster = new sst.aws.Cluster("LakeCluster", { vpc: lakeVpc })
|
|
export const lakeRegion = region.region
|
|
export const lakeCatalog = $interpolate`${glueCatalogName}/${tableBucket.name}`
|
|
export const lakeAthenaWorkgroup = athenaWorkgroup
|
|
|
|
const ingestSecret = new random.RandomPassword("LakeIngestSecret", { length: 32 })
|
|
export const ingestSecretSsm = new aws.ssm.Parameter("LakeIngestSecretSsm", {
|
|
name: $interpolate`/${$app.name}/${$app.stage}/lake/ingest/secret`,
|
|
type: "SecureString",
|
|
value: ingestSecret.result,
|
|
})
|
|
|
|
const ingestConfig = new sst.Linkable("LakeIngestConfig", {
|
|
properties: {
|
|
streamName: firehose.name,
|
|
secret: ingestSecret.result,
|
|
},
|
|
})
|
|
|
|
const ingestService = new sst.aws.Service("LakeIngestService", {
|
|
cluster: lakeCluster,
|
|
architecture: "arm64",
|
|
cpu: "1 vCPU",
|
|
memory: "4 GB",
|
|
image: {
|
|
context: ".",
|
|
dockerfile: "packages/stats/server/Dockerfile",
|
|
},
|
|
link: [ingestConfig],
|
|
permissions: [
|
|
{
|
|
actions: ["firehose:PutRecord", "firehose:PutRecordBatch"],
|
|
resources: [firehose.arn],
|
|
},
|
|
],
|
|
scaling: {
|
|
min: $app.stage === "production" ? 2 : 1,
|
|
max: $app.stage === "production" ? 32 : 4,
|
|
cpuUtilization: 60,
|
|
memoryUtilization: 70,
|
|
},
|
|
loadBalancer: {
|
|
domain: {
|
|
name: `lake.${domain}`,
|
|
dns: sst.cloudflare.dns(),
|
|
},
|
|
rules: [
|
|
{ listen: "80/http", redirect: "443/https" },
|
|
{ listen: "443/https", forward: "3000/http" },
|
|
],
|
|
health: {
|
|
"3000/http": {
|
|
path: "/ready",
|
|
successCodes: "200-299",
|
|
},
|
|
},
|
|
},
|
|
health: {
|
|
command: [
|
|
"CMD-SHELL",
|
|
"bun --eval \"fetch('http://localhost:3000/health').then((r) => process.exit(r.ok ? 0 : 1)).catch(() => process.exit(1))\"",
|
|
],
|
|
interval: "30 seconds",
|
|
retries: 3,
|
|
startPeriod: "30 seconds",
|
|
timeout: "5 seconds",
|
|
},
|
|
dev: {
|
|
command: "bun run start",
|
|
directory: "packages/stats/server",
|
|
url: "http://localhost:3000",
|
|
},
|
|
wait: $app.stage === "production",
|
|
})
|
|
|
|
export const lakeIngest = new sst.Linkable("LakeIngest", {
|
|
properties: {
|
|
url: ingestService.url,
|
|
secret: ingestSecret.result,
|
|
},
|
|
})
|
|
|
|
export const lakeQueryPermissions = [
|
|
{
|
|
actions: ["athena:StartQueryExecution", "athena:GetQueryExecution", "athena:GetQueryResults"],
|
|
resources: [athenaWorkgroup.arn],
|
|
},
|
|
{
|
|
actions: [
|
|
"glue:GetCatalog",
|
|
"glue:GetCatalogs",
|
|
"glue:GetDatabase",
|
|
"glue:GetDatabases",
|
|
"glue:GetTable",
|
|
"glue:GetTables",
|
|
"glue:GetPartitions",
|
|
],
|
|
resources: [
|
|
glueCatalogArn,
|
|
glueS3TablesCatalogArn,
|
|
$interpolate`${glueS3TablesCatalogArn}/*`,
|
|
glueS3TablesDatabaseWildcardArn,
|
|
glueS3TablesTableWildcardArn,
|
|
$interpolate`arn:${partition.partition}:glue:${region.region}:${current.accountId}:database/*`,
|
|
$interpolate`arn:${partition.partition}:glue:${region.region}:${current.accountId}:table/*/*`,
|
|
$interpolate`arn:${partition.partition}:glue:${region.region}:${current.accountId}:table/${glueCatalogName}/*`,
|
|
],
|
|
},
|
|
{
|
|
actions: ["s3:GetBucketLocation", "s3:ListBucket"],
|
|
resources: [athenaResultsBucket.arn],
|
|
},
|
|
{
|
|
actions: ["s3:GetObject", "s3:PutObject", "s3:AbortMultipartUpload", "s3:ListBucketMultipartUploads"],
|
|
resources: [$interpolate`${athenaResultsBucket.arn}/*`],
|
|
},
|
|
{
|
|
actions: [
|
|
"s3tables:GetTableBucket",
|
|
"s3tables:GetNamespace",
|
|
"s3tables:GetTable",
|
|
"s3tables:GetTableData",
|
|
"s3tables:GetTableMetadataLocation",
|
|
"s3tables:ListNamespaces",
|
|
"s3tables:ListTables",
|
|
],
|
|
resources: ["*"],
|
|
},
|
|
{
|
|
actions: ["lakeformation:GetDataAccess"],
|
|
resources: ["*"],
|
|
},
|
|
]
|