This repository was archived by the owner on Jun 19, 2026. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 246
Bounty Submission: Universal One-Click Deployment (Docker + K8s + Tilt) for FinMind #387
Open
sirrodgepodge
wants to merge
7
commits into
rohitdash08:main
Choose a base branch
from
sirrodgepodge:bounty/universal-one-click-deployment
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 1 commit
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
9711a26
feat: universal one-click deployment (Docker + K8s + Tilt)
9eb0e24
docs: add deployment demo GIF
af8c210
docs: add deployment demo recording
5fc3ede
docs: add deployment demo gif
7dd4ff4
feat: true one-click deployment — runtime API URL injection
sirrodgepodge bbd7259
docs: update deployment demo GIF with verified end-to-end recording
sirrodgepodge 9ec76b5
fix: address PR review feedback and clean demo artifacts
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,61 @@ | ||
| spec: | ||
| name: finmind | ||
| region: nyc | ||
| services: | ||
| - name: backend | ||
| dockerfile_path: packages/backend/Dockerfile | ||
| github: | ||
| repo: rohitdash08/FinMind | ||
| branch: main | ||
| deploy_on_push: true | ||
| http_port: 8000 | ||
| instance_count: 1 | ||
| instance_size_slug: basic-xxs | ||
| routes: | ||
| - path: /api | ||
| - path: /health | ||
| health_check: | ||
| http_path: /health | ||
| initial_delay_seconds: 10 | ||
| period_seconds: 10 | ||
| run_command: | | ||
| sh -c "python -m flask --app wsgi:app init-db && gunicorn --workers=2 --threads=4 --bind 0.0.0.0:8000 wsgi:app" | ||
| envs: | ||
| - key: DATABASE_URL | ||
| scope: RUN_TIME | ||
| value: ${db.DATABASE_URL} | ||
| - key: REDIS_URL | ||
| scope: RUN_TIME | ||
| value: CHANGE_ME_SET_EXTERNAL_REDIS_URL | ||
| - key: JWT_SECRET | ||
| scope: RUN_TIME | ||
| type: SECRET | ||
| value: change-me | ||
|
sirrodgepodge marked this conversation as resolved.
Outdated
|
||
| - key: LOG_LEVEL | ||
| scope: RUN_TIME | ||
| value: INFO | ||
| - key: GEMINI_MODEL | ||
| scope: RUN_TIME | ||
| value: gemini-1.5-flash | ||
|
|
||
| - name: frontend | ||
| dockerfile_path: app/Dockerfile | ||
| github: | ||
| repo: rohitdash08/FinMind | ||
| branch: main | ||
| deploy_on_push: true | ||
| http_port: 80 | ||
| instance_count: 1 | ||
| instance_size_slug: basic-xxs | ||
| routes: | ||
| - path: / | ||
|
|
||
| databases: | ||
| - name: db | ||
| engine: PG | ||
| version: "16" | ||
| size: db-s-dev-database | ||
| num_nodes: 1 | ||
|
|
||
| # Note: DigitalOcean App Platform doesn't have managed Redis. | ||
| # Use DigitalOcean Managed Redis or Upstash, then set REDIS_URL on the backend service. | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| web: sh -c "cd packages/backend && python -m flask --app wsgi:app init-db && gunicorn --workers=2 --threads=4 --bind 0.0.0.0:$PORT wsgi:app" | ||
|
sirrodgepodge marked this conversation as resolved.
Outdated
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| # FinMind Tiltfile — local Kubernetes development | ||
|
|
||
| # Build images | ||
| docker_build('ghcr.io/rohitdash08/finmind-backend', './packages/backend', | ||
| live_update=[ | ||
| sync('./packages/backend/app', '/app/app'), | ||
| sync('./packages/backend/wsgi.py', '/app/wsgi.py'), | ||
| run('pip install -r requirements.txt', trigger=['./packages/backend/requirements.txt']), | ||
| ] | ||
| ) | ||
|
|
||
| docker_build('nginx', './app', | ||
|
sirrodgepodge marked this conversation as resolved.
Outdated
|
||
| # Multi-stage build: React build → nginx static serve. | ||
| # Full rebuild on source changes (live_update not viable for multi-stage). | ||
| ) | ||
|
|
||
| # Apply K8s manifests | ||
| k8s_yaml([ | ||
| 'deploy/k8s/namespace.yaml', | ||
| 'deploy/k8s/secrets.example.yaml', | ||
| 'deploy/k8s/app-stack.yaml', | ||
| ]) | ||
|
|
||
| # Tilt automatically matches docker_build image names to K8s manifests. | ||
| # If images don't match, use k8s_image_json_path or set_image. | ||
|
|
||
| # Resource grouping and dependencies | ||
| k8s_resource('postgres', labels=['database'], | ||
| port_forwards='5432:5432') | ||
|
|
||
| k8s_resource('redis', labels=['database'], | ||
| port_forwards='6379:6379') | ||
|
|
||
| k8s_resource('backend', labels=['app'], | ||
| port_forwards='8000:8000', | ||
| resource_deps=['postgres', 'redis']) | ||
|
|
||
| k8s_resource('nginx', labels=['app'], | ||
| port_forwards='8080:80', | ||
| resource_deps=['backend']) | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| { | ||
| "name": "FinMind", | ||
| "description": "AI-powered personal finance manager", | ||
| "repository": "https://github.com/rohitdash08/FinMind", | ||
| "logo": "", | ||
| "keywords": ["finance", "budgeting", "flask", "react"], | ||
| "stack": "container", | ||
| "addons": [ | ||
| { | ||
| "plan": "heroku-postgresql:essential-0" | ||
| }, | ||
| { | ||
| "plan": "heroku-redis:mini" | ||
| } | ||
| ], | ||
| "env": { | ||
| "JWT_SECRET": { | ||
| "description": "Secret key for JWT token signing", | ||
| "generator": "secret" | ||
| }, | ||
| "DATABASE_URL": { | ||
| "description": "PostgreSQL connection URL (auto-set by addon)" | ||
| }, | ||
| "REDIS_URL": { | ||
| "description": "Redis connection URL (auto-set by addon)" | ||
| }, | ||
| "LOG_LEVEL": { | ||
| "description": "Logging level", | ||
| "value": "INFO" | ||
| }, | ||
| "GEMINI_API_KEY": { | ||
| "description": "Google Gemini API key for AI features", | ||
| "required": false | ||
| }, | ||
| "GEMINI_MODEL": { | ||
| "description": "Gemini model name", | ||
| "value": "gemini-1.5-flash" | ||
| } | ||
| }, | ||
| "formation": { | ||
| "web": { | ||
| "quantity": 1, | ||
| "size": "basic" | ||
| } | ||
| }, | ||
| "buildpacks": [], | ||
| "scripts": {}, | ||
| "environments": {} | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| # AWS App Runner configuration | ||
| # Deploy with: aws apprunner create-service --cli-input-json file://apprunner.json | ||
| # | ||
| # This YAML is a reference. Convert to JSON for the CLI or use the console. | ||
|
sirrodgepodge marked this conversation as resolved.
Outdated
|
||
|
|
||
| ServiceName: finmind-backend | ||
| SourceConfiguration: | ||
| ImageRepository: | ||
| ImageIdentifier: <ECR_IMAGE_URI> | ||
| ImageRepositoryType: ECR | ||
| ImageConfiguration: | ||
| Port: "8000" | ||
| RuntimeEnvironmentVariables: | ||
| DATABASE_URL: <your-database-url> | ||
| REDIS_URL: <your-redis-url> | ||
| JWT_SECRET: <your-jwt-secret> | ||
| LOG_LEVEL: INFO | ||
| GEMINI_MODEL: gemini-1.5-flash | ||
| StartCommand: "sh -c 'python -m flask --app wsgi:app init-db && gunicorn --workers=2 --threads=4 --bind 0.0.0.0:8000 wsgi:app'" | ||
| AutoDeploymentsEnabled: true | ||
| InstanceConfiguration: | ||
| Cpu: "0.25 vCPU" | ||
| Memory: "0.5 GB" | ||
| HealthCheckConfiguration: | ||
| Protocol: HTTP | ||
| Path: /health | ||
| Interval: 10 | ||
| Timeout: 5 | ||
| HealthyThreshold: 1 | ||
| UnhealthyThreshold: 5 | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,178 @@ | ||
| AWSTemplateFormatVersion: '2010-09-09' | ||
| Description: FinMind ECS Fargate Stack | ||
|
|
||
| Parameters: | ||
| VpcId: | ||
| Type: AWS::EC2::VPC::Id | ||
| SubnetIds: | ||
| Type: List<AWS::EC2::Subnet::Id> | ||
| BackendImage: | ||
| Type: String | ||
| Description: Backend Docker image URI | ||
| FrontendImage: | ||
| Type: String | ||
| Description: Frontend Docker image URI | ||
| DatabaseUrl: | ||
| Type: String | ||
| NoEcho: true | ||
| RedisUrl: | ||
| Type: String | ||
| NoEcho: true | ||
| JwtSecret: | ||
| Type: String | ||
| NoEcho: true | ||
| Default: '' | ||
|
sirrodgepodge marked this conversation as resolved.
Outdated
|
||
|
|
||
| Resources: | ||
| ECSCluster: | ||
| Type: AWS::ECS::Cluster | ||
| Properties: | ||
| ClusterName: finmind | ||
| CapacityProviders: [FARGATE] | ||
|
|
||
| ExecutionRole: | ||
| Type: AWS::IAM::Role | ||
| Properties: | ||
| RoleName: finmind-execution-role | ||
| AssumeRolePolicyDocument: | ||
| Version: '2012-10-17' | ||
| Statement: | ||
| - Effect: Allow | ||
| Principal: | ||
| Service: ecs-tasks.amazonaws.com | ||
| Action: sts:AssumeRole | ||
| ManagedPolicyArns: | ||
| - !Sub arn:${AWS::Partition}:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy | ||
|
|
||
| TaskRole: | ||
| Type: AWS::IAM::Role | ||
| Properties: | ||
| RoleName: finmind-task-role | ||
| AssumeRolePolicyDocument: | ||
| Version: '2012-10-17' | ||
| Statement: | ||
| - Effect: Allow | ||
| Principal: | ||
| Service: ecs-tasks.amazonaws.com | ||
| Action: sts:AssumeRole | ||
|
|
||
| LogGroup: | ||
| Type: AWS::Logs::LogGroup | ||
| Properties: | ||
| LogGroupName: /ecs/finmind | ||
| RetentionInDays: 14 | ||
|
|
||
| SecurityGroup: | ||
| Type: AWS::EC2::SecurityGroup | ||
| Properties: | ||
| GroupDescription: FinMind ECS Security Group | ||
| VpcId: !Ref VpcId | ||
| SecurityGroupIngress: | ||
| - IpProtocol: tcp | ||
| FromPort: 80 | ||
| ToPort: 80 | ||
| CidrIp: 0.0.0.0/0 | ||
| - IpProtocol: tcp | ||
| FromPort: 8000 | ||
| ToPort: 8000 | ||
| CidrIp: 0.0.0.0/0 | ||
|
|
||
| BackendTaskDef: | ||
| Type: AWS::ECS::TaskDefinition | ||
| Properties: | ||
| Family: finmind-backend | ||
| Cpu: '256' | ||
| Memory: '512' | ||
| NetworkMode: awsvpc | ||
| RequiresCompatibilities: [FARGATE] | ||
| ExecutionRoleArn: !GetAtt ExecutionRole.Arn | ||
| TaskRoleArn: !GetAtt TaskRole.Arn | ||
| ContainerDefinitions: | ||
| - Name: backend | ||
| Image: !Ref BackendImage | ||
| Essential: true | ||
| PortMappings: | ||
| - ContainerPort: 8000 | ||
| Environment: | ||
| - Name: DATABASE_URL | ||
| Value: !Ref DatabaseUrl | ||
| - Name: REDIS_URL | ||
| Value: !Ref RedisUrl | ||
| - Name: JWT_SECRET | ||
| Value: !Ref JwtSecret | ||
| - Name: LOG_LEVEL | ||
| Value: INFO | ||
| Command: | ||
| - sh | ||
| - -c | ||
| - "python -m flask --app wsgi:app init-db && gunicorn --workers=2 --threads=4 --bind 0.0.0.0:8000 wsgi:app" | ||
| LogConfiguration: | ||
| LogDriver: awslogs | ||
| Options: | ||
| awslogs-group: !Ref LogGroup | ||
| awslogs-region: !Ref AWS::Region | ||
| awslogs-stream-prefix: backend | ||
| HealthCheck: | ||
| Command: ["CMD-SHELL", "curl -f http://localhost:8000/health || exit 1"] | ||
| Interval: 30 | ||
| Timeout: 5 | ||
| Retries: 3 | ||
| StartPeriod: 30 | ||
|
|
||
| FrontendTaskDef: | ||
| Type: AWS::ECS::TaskDefinition | ||
| Properties: | ||
| Family: finmind-frontend | ||
| Cpu: '256' | ||
| Memory: '256' | ||
| NetworkMode: awsvpc | ||
| RequiresCompatibilities: [FARGATE] | ||
| ExecutionRoleArn: !GetAtt ExecutionRole.Arn | ||
| ContainerDefinitions: | ||
| - Name: frontend | ||
| Image: !Ref FrontendImage | ||
| Essential: true | ||
| PortMappings: | ||
| - ContainerPort: 80 | ||
| LogConfiguration: | ||
| LogDriver: awslogs | ||
| Options: | ||
| awslogs-group: !Ref LogGroup | ||
| awslogs-region: !Ref AWS::Region | ||
| awslogs-stream-prefix: frontend | ||
|
|
||
| BackendService: | ||
| Type: AWS::ECS::Service | ||
| Properties: | ||
| Cluster: !Ref ECSCluster | ||
| ServiceName: finmind-backend | ||
| TaskDefinition: !Ref BackendTaskDef | ||
| DesiredCount: 1 | ||
| LaunchType: FARGATE | ||
| NetworkConfiguration: | ||
| AwsvpcConfiguration: | ||
| AssignPublicIp: ENABLED | ||
| SecurityGroups: [!Ref SecurityGroup] | ||
| Subnets: !Ref SubnetIds | ||
|
|
||
| FrontendService: | ||
| Type: AWS::ECS::Service | ||
| Properties: | ||
| Cluster: !Ref ECSCluster | ||
| ServiceName: finmind-frontend | ||
| TaskDefinition: !Ref FrontendTaskDef | ||
| DesiredCount: 1 | ||
| LaunchType: FARGATE | ||
| NetworkConfiguration: | ||
| AwsvpcConfiguration: | ||
| AssignPublicIp: ENABLED | ||
| SecurityGroups: [!Ref SecurityGroup] | ||
| Subnets: !Ref SubnetIds | ||
|
|
||
| Outputs: | ||
| ClusterName: | ||
| Value: !Ref ECSCluster | ||
| BackendServiceName: | ||
| Value: !GetAtt BackendService.Name | ||
| FrontendServiceName: | ||
| Value: !GetAtt FrontendService.Name | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.