Skip to content

Commit 66846d4

Browse files
committed
chore: wip
chore: wip chore: wip
1 parent 99cb4e1 commit 66846d4

File tree

11 files changed

+72
-58
lines changed

11 files changed

+72
-58
lines changed

.stacks/core/cloud/cdk.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"app": "bun ./src/deploy.ts",
2+
"app": "bun ./deploy.ts",
33
"profile": "stacks",
44
"watch": {
55
"include": [
Lines changed: 14 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
/* eslint-disable no-new */
22
import process from 'node:process'
33
import { config } from '@stacksjs/config'
4+
import { ExitCode } from '@stacksjs/types'
45
import { env } from '@stacksjs/env'
56
import * as cdk from 'aws-cdk-lib'
6-
import { Cloud } from './cloud/'
7-
import type { CloudOptions } from './types'
7+
import { Cloud } from './src/cloud'
8+
import { getOrCreateTimestamp } from './src/helpers'
9+
import type { CloudOptions } from './src/types'
810

911
const app = new cdk.App()
1012
const appEnv = config.app.env === 'local' ? 'dev' : config.app.env
@@ -14,6 +16,7 @@ const name = `stacks-cloud-${appEnv}`
1416
const appName = config.app.name?.toLowerCase()
1517
const account = env.AWS_ACCOUNT_ID
1618
const region = env.AWS_DEFAULT_REGION
19+
let timestamp
1720

1821
if (!appKey) {
1922
log.info('Please set an application key. `buddy key:generate` is your friend, in this case.')
@@ -24,11 +27,6 @@ const parts = appKey.split(':')
2427
if (parts && parts.length < 2)
2528
throw new Error('Invalid format application key format. Expected a colon-separated string. You may need to run `buddy key:generate`.')
2629

27-
const partialAppKey = parts[1] ? parts[1].substring(0, 10).toLowerCase() : undefined
28-
29-
if (!partialAppKey)
30-
throw new Error('The application key seems to be missing. Please set it before deploying. `buddy key:generate` is your friend, in this case.')
31-
3230
if (!account || !region)
3331
throw new Error('Missing accountId or region in config.')
3432

@@ -46,34 +44,23 @@ const usEnv = {
4644
region,
4745
}
4846

47+
try {
48+
timestamp = await getOrCreateTimestamp()
49+
}
50+
catch (error) {
51+
console.error('Error fetching timestamp', error)
52+
process.exit(ExitCode.FatalError)
53+
}
54+
4955
export const options = {
5056
env: usEnv,
5157
name,
5258
appEnv: appEnv ?? 'dev',
5359
appName,
5460
domain,
55-
partialAppKey,
61+
timestamp,
5662
} satisfies CloudOptions
5763

5864
new Cloud(app, name, options)
5965

6066
app.synth()
61-
62-
// function isProductionEnv(env: string) {
63-
// return env === 'production' || env === 'prod'
64-
// }
65-
66-
// export async function getExistingBucketNameByPrefix(prefix: string): Promise<string | undefined | null> {
67-
// const s3 = new S3({ region: 'us-east-1' })
68-
69-
// try {
70-
// const response = await s3.send(new ListBucketsCommand({}))
71-
// const bucket = response.Buckets?.find(bucket => bucket.Name?.startsWith(prefix))
72-
73-
// return bucket ? bucket.Name : null
74-
// }
75-
// catch (error) {
76-
// console.error('Error fetching buckets', error)
77-
// return `${prefix}-${partialAppKey}`
78-
// }
79-
// }

.stacks/core/cloud/src/cloud/cdn.ts

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import {
77
aws_cloudfront_origins as origins,
88
aws_route53 as route53,
99
aws_secretsmanager as secretsmanager,
10-
// aws_ssm as ssm,
1110
aws_route53_targets as targets,
1211
} from 'aws-cdk-lib'
1312
import type { Construct } from 'constructs'
@@ -50,23 +49,6 @@ export class CdnStack {
5049
cookieBehavior: this.getCookieBehavior(config.cloud.cdn?.cookieBehavior),
5150
})
5251

53-
// Fetch the timestamp from SSM Parameter Store
54-
// const timestampParam = ssm.StringParameter.fromSecureStringParameterAttributes(scope, 'TimestampParam', {
55-
// parameterName: `/stacks/${props.appName.toLowerCase()}/timestamp`,
56-
// version: 1,
57-
// })
58-
59-
// let timestamp = timestampParam.stringValue
60-
61-
// // If the timestamp does not exist, create it
62-
// if (!timestamp) {
63-
// timestamp = new Date().getTime().toString()
64-
// new ssm.StringParameter(scope, 'TimestampParam', {
65-
// parameterName: `/stacks/${props.appName.toLowerCase()}/timestamp`,
66-
// stringValue: timestamp,
67-
// })
68-
// }
69-
7052
// the actual CDN distribution
7153
this.distribution = new cloudfront.Distribution(scope, 'Cdn', {
7254
domainNames: [props.domain],

.stacks/core/cloud/src/cloud/docs.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,9 @@ export class DocsStack {
2121
// this edge function ensures pretty docs urls
2222
// soon to be reused for our Meema features
2323
this.originRequestFunction = new lambda.Function(scope, 'OriginRequestFunction', {
24-
// this needs to have partialAppKey & timestamp to ensure it is unique, because there is a chance that during testing, you deploy
25-
// the same app many times using the same app key. Since Origin Request (Lambda@Edge) functions are replicated functions, the
26-
// deletion process takes a long time. This is to ensure that the function is always unique in cases of quick recreations.
27-
functionName: `${props.appName}-${props.appEnv}-origin-request-${props.partialAppKey}-${new Date().getTime()}`,
24+
// this needs to have timestamp to ensure uniqueness. Since Origin Request (Lambda@Edge) functions are replicated functions, the
25+
// deletion process takes a "long time". This way, the function is always unique in cases of quick recreations.
26+
functionName: `${props.appName}-${props.appEnv}-origin-request-${props.timestamp}`,
2827
description: 'The Stacks Origin Request function that prettifies URLs',
2928
runtime: lambda.Runtime.NODEJS_18_X,
3029
handler: 'dist/origin-request.handler',

.stacks/core/cloud/src/cloud/email.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ export class EmailStack {
1313
constructor(scope: Construct, props: EmailStackProps) {
1414
const bucketPrefix = `${props.appName}-${props.appEnv}`
1515
this.emailBucket = new s3.Bucket(scope, 'EmailServerBucket', {
16-
bucketName: `${bucketPrefix}-email-${timestamp}`,
16+
bucketName: `${bucketPrefix}-email-${props.timestamp}`,
1717
versioned: true,
1818
removalPolicy: RemovalPolicy.DESTROY,
1919
autoDeleteObjects: true,

.stacks/core/cloud/src/cloud/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/* eslint-disable no-new */
2-
import type { Construct } from 'constructs'
32
import { Stack } from 'aws-cdk-lib'
3+
import type { Construct } from 'constructs'
44
import type { CloudOptions } from '../types'
55
import { CdnStack } from './cdn'
66
import { DnsStack } from './dns'

.stacks/core/cloud/src/cloud/storage.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ export class StorageStack {
2020
this.bucketPrefix = `${props.appName}-${props.appEnv}`
2121

2222
this.publicBucket = new s3.Bucket(scope, 'PublicBucket', {
23-
bucketName: `${this.bucketPrefix}-${props.partialAppKey}`,
23+
bucketName: `${this.bucketPrefix}-${props.timestamp}`,
2424
versioned: true,
2525
autoDeleteObjects: true,
2626
removalPolicy: RemovalPolicy.DESTROY,
@@ -30,7 +30,7 @@ export class StorageStack {
3030
Tags.of(this.publicBucket).add('daily-backup', 'true')
3131

3232
this.privateBucket = new s3.Bucket(scope, 'PrivateBucket', {
33-
bucketName: `${this.bucketPrefix}-private-${props.partialAppKey}`,
33+
bucketName: `${this.bucketPrefix}-private-${props.timestamp}`,
3434
versioned: true,
3535
removalPolicy: RemovalPolicy.DESTROY,
3636
autoDeleteObjects: true,
@@ -48,7 +48,7 @@ export class StorageStack {
4848
Tags.of(this.privateBucket).add('daily-backup', 'true')
4949

5050
this.logBucket = new s3.Bucket(scope, 'LogsBucket', {
51-
bucketName: `${this.bucketPrefix}-logs-${props.partialAppKey}`,
51+
bucketName: `${this.bucketPrefix}-logs-${props.timestamp}`,
5252
removalPolicy: RemovalPolicy.DESTROY,
5353
autoDeleteObjects: true,
5454
blockPublicAccess: new s3.BlockPublicAccess({

.stacks/core/cloud/src/helpers.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { CloudWatchLogsClient, DeleteLogGroupCommand, DescribeLogGroupsCommand }
44
import { EC2, _InstanceType as InstanceType } from '@aws-sdk/client-ec2'
55
import { DescribeFileSystemsCommand, EFSClient } from '@aws-sdk/client-efs'
66
import { IAM } from '@aws-sdk/client-iam'
7+
import { SSM } from '@aws-sdk/client-ssm'
78
import { Lambda } from '@aws-sdk/client-lambda'
89
import type { CountryCode } from '@aws-sdk/client-route-53-domains'
910
import { ContactType, Route53Domains } from '@aws-sdk/client-route-53-domains'
@@ -483,3 +484,48 @@ export async function isFailedState() {
483484

484485
return !isStacksCloudPresent
485486
}
487+
488+
export async function getOrCreateTimestamp(): Promise<string> {
489+
const parameterName = `/stacks/timestamp`
490+
const ssm = new SSM({ region: 'us-east-1' })
491+
492+
try {
493+
const response = await ssm.getParameter({ Name: parameterName })
494+
const timestamp = response.Parameter ? response.Parameter.Value : undefined
495+
496+
if (!timestamp)
497+
throw new Error('Timestamp parameter not found')
498+
499+
return timestamp
500+
}
501+
catch (error: any) {
502+
const timestamp = new Date().getTime().toString()
503+
log.info(`Creating timestamp parameter ${parameterName} with value ${timestamp}`)
504+
await ssm.putParameter({
505+
Name: parameterName,
506+
Value: timestamp,
507+
Type: 'String',
508+
})
509+
510+
return timestamp
511+
}
512+
}
513+
514+
// function isProductionEnv(env: string) {
515+
// return env === 'production' || env === 'prod'
516+
// }
517+
518+
// export async function getExistingBucketNameByPrefix(prefix: string): Promise<string | undefined | null> {
519+
// const s3 = new S3({ region: 'us-east-1' })
520+
521+
// try {
522+
// const response = await s3.send(new ListBucketsCommand({}))
523+
// const bucket = response.Buckets?.find(bucket => bucket.Name?.startsWith(prefix))
524+
525+
// return bucket ? bucket.Name : null
526+
// }
527+
// catch (error) {
528+
// console.error('Error fetching buckets', error)
529+
// return `${prefix}-${timestamp}`
530+
// }
531+
// }

.stacks/core/cloud/src/types.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ export interface CloudOptions extends StackProps {
1010
appEnv: AppEnvType
1111
appName: string
1212
domain: string
13-
partialAppKey: string
13+
timestamp: string
1414
}
1515

1616
// export interface NestedCloudProps extends NestedStackProps {
@@ -23,5 +23,5 @@ export interface NestedCloudProps {
2323
appEnv: AppEnvType
2424
appName: string
2525
domain: string
26-
partialAppKey: string
26+
timestamp: string
2727
}

.stacks/core/database/src/migrations/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ export interface MigrationOptions {
4949
export function generateMigrationFile(options: MigrationOptions) {
5050
const { name, up, down } = options
5151

52-
const timestamp = new Date().getTime()
52+
const timestamp = new Date().getTime().toString()
5353
const fileName = `${timestamp}-${name}.ts`
5454
const filePath = p.frameworkPath(`database/migrations/${fileName}`)
5555
const fileContent = `

0 commit comments

Comments
 (0)