Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
50 changes: 50 additions & 0 deletions .github/workflows/transaction-ingest.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
name: Transaction Ingest CI

on:
push:
paths:
- 'services/transaction-ingest/**'
workflow_dispatch:

jobs:
build-test-deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: '1.22'

- name: Run tests
working-directory: services/transaction-ingest
run: go test ./...

- name: Build binary
working-directory: services/transaction-ingest
run: |
GOOS=linux GOARCH=amd64 go build -o main
zip -j bin/main.zip main

- name: Configure AWS
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: us-west-2

- name: Login to ECR public
uses: aws-actions/amazon-ecr-login@v2
with:
registry-type: public

- name: Build and push
working-directory: services/transaction-ingest
run: |
docker build -t public.ecr.aws/${{ secrets.AWS_ECR_ALIAS }}/transaction-ingest:latest .
docker push public.ecr.aws/${{ secrets.AWS_ECR_ALIAS }}/transaction-ingest:latest

- name: Deploy CDK
run: npx cdk deploy --all --require-approval never
working-directory: infra
6 changes: 6 additions & 0 deletions infra/bin/transaction_ingest.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#!/usr/bin/env node
import { App } from 'aws-cdk-lib';
import { TransactionIngestStack } from '../lib/transaction_ingest_stack';

const app = new App();
new TransactionIngestStack(app, 'TransactionIngestStack');
59 changes: 59 additions & 0 deletions infra/lib/transaction_ingest_stack.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { Construct } from 'constructs';
import { Stack, StackProps, RemovalPolicy } from 'aws-cdk-lib';
import * as lambda from 'aws-cdk-lib/aws-lambda';
import * as events from 'aws-cdk-lib/aws-events';
import * as targets from 'aws-cdk-lib/aws-events-targets';
import * as dynamodb from 'aws-cdk-lib/aws-dynamodb';
import * as apigw from 'aws-cdk-lib/aws-apigateway';
import * as ssm from 'aws-cdk-lib/aws-ssm';
import * as path from 'path';
import * as logs from 'aws-cdk-lib/aws-logs';

export class TransactionIngestStack extends Stack {
constructor(scope: Construct, id: string, props?: StackProps) {
super(scope, id, props);

const table = new dynamodb.Table(this, 'Transactions', {
partitionKey: { name: 'user_id', type: dynamodb.AttributeType.STRING },
sortKey: { name: 'date', type: dynamodb.AttributeType.STRING },
billingMode: dynamodb.BillingMode.PAY_PER_REQUEST,
removalPolicy: RemovalPolicy.DESTROY,
});

const func = new lambda.Function(this, 'TransactionIngest', {
runtime: lambda.Runtime.GO_1_X,
handler: 'main',
code: lambda.Code.fromAsset(path.join(__dirname, '../../services/transaction-ingest/bin/main.zip')),
environment: {
TRANSACTIONS_TABLE: table.tableName,
PLAID_SECRET: ssm.StringParameter.valueForStringParameter(this, 'PLAID_SECRET'),
},
logRetention: logs.RetentionDays.TWO_WEEKS,
});

table.grantReadWriteData(func);

const rule = new events.Rule(this, 'NightlySync', {
schedule: events.Schedule.cron({ minute: '0', hour: '10' }), // 02:00 PT
});
rule.addTarget(new targets.LambdaFunction(func));

const api = new apigw.RestApi(this, 'IngestApi', {
deployOptions: { stageName: 'prod' },
});

const run = api.root.addResource('api').addResource('ingest').addResource('run');
run.addMethod('POST', new apigw.LambdaIntegration(func), {
authorizationType: apigw.AuthorizationType.IAM,
});

api.addUsagePlan('PerUserPlan', {
throttle: { burstLimit: 10, rateLimit: 10 },
});

new ssm.StringParameter(this, 'PlaidSecretParam', {
parameterName: 'PLAID_SECRET',
stringValue: 'sandbox-123',
});
}
}
8 changes: 8 additions & 0 deletions infra/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"name": "infra",
"private": true,
"dependencies": {
"aws-cdk-lib": "^2.139.0",
"constructs": "^10.2.118"
}
}
11 changes: 11 additions & 0 deletions infra/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"compilerOptions": {
"target": "ES2020",
"module": "commonjs",
"lib": ["es2020"],
"strict": true,
"esModuleInterop": true,
"outDir": "dist"
},
"include": ["**/*.ts"]
}
Loading
Loading