Skip to content
Open
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
38 changes: 38 additions & 0 deletions .github/workflows/deploy-activity-tracking.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: Deploy to AWS ECR

on:
push:
branches:
- main
paths:
- "activity-tracking/**"

jobs:
build:
runs-on: ubuntu-latest
steps:
- run: |
echo The PR was merged
- name: Checkout code
uses: actions/checkout@v2

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

- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v1

- name: Build, tag, and push image to Amazon ECR (Activity Tracking)
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
ECR_REPOSITORY: mla-fitnessapp-activity
IMAGE_TAG: latest
run: |
cd activity-tracking
docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG -f Dockerfile .
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
38 changes: 38 additions & 0 deletions .github/workflows/deploy-analytics.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: Deploy to AWS ECR

on:
push:
branches:
- main
paths:
- "analytics/**"

jobs:
build:
runs-on: ubuntu-latest
steps:
- run: |
echo The PR was merged
- name: Checkout code
uses: actions/checkout@v2

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

- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v1

- name: Build, tag, and push image to Amazon ECR (Analytics)
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
ECR_REPOSITORY: mla-fitnessapp-analytics
IMAGE_TAG: latest
run: |
cd analytics
docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG -f Dockerfile .
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
38 changes: 38 additions & 0 deletions .github/workflows/deploy-auth.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: Deploy to AWS ECR

on:
push:
branches:
- main
paths:
- "authservice/**"

jobs:
build:
runs-on: ubuntu-latest
steps:
- run: |
echo The PR was merged
- name: Checkout code
uses: actions/checkout@v2

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

- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v1

- name: Build, tag, and push image to Amazon ECR (AuthService)
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
ECR_REPOSITORY: mla-fitnessapp-authservice
IMAGE_TAG: latest
run: |
cd authservice
docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG -f Dockerfile .
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
38 changes: 38 additions & 0 deletions .github/workflows/deploy-frontend.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: Deploy to AWS ECR

on:
push:
branches:
- main
paths:
- "frontend/**"

jobs:
build:
runs-on: ubuntu-latest
steps:
- run: |
echo The PR was merged
- name: Checkout code
uses: actions/checkout@v2

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

- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v1

- name: Build, tag, and push image to Amazon ECR (Frontend)
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
ECR_REPOSITORY: mla-fitnessapp-fe
IMAGE_TAG: latest
run: |
cd frontend
docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG -f Dockerfile .
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
63 changes: 62 additions & 1 deletion analytics/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,78 @@
import logging
import os
from datetime import datetime, timedelta
from ariadne import load_schema_from_path, make_executable_schema, graphql_sync, ObjectType, QueryType
from ariadne.constants import PLAYGROUND_HTML

app = Flask(__name__)
CORS(app, resources={r"/*": {"origins": "*"}},
methods="GET,HEAD,POST,OPTIONS,PUT,PATCH,DELETE")

load_dotenv()
title = "Weekly Exercise Tracker Statistics"
heading = "MLA Flask Microservice"
user = "testuser"
mongo_uri = os.getenv('MONGO_URI')
mongo_db = os.getenv('MONGO_DB')

client = MongoClient(mongo_uri)
db = client[mongo_db]

query = QueryType()
type_defs = load_schema_from_path("schema.graphql")

@app.route('/api/graphql', methods=['GET'])
def graphql_playground():
print("Received a get request")
return PLAYGROUND_HTML, 200

@app.route('/api/graphql', methods=['POST'])
def graphql_server():
print("Getting a request...")
data = request.get_json()
success, result = graphql_sync(
schema,
data,
context_value=request,
debug=True
)
status_code = 200 if success else 400
return jsonify(result), status_code

@query.field("stats")
def resolve_stats(_, info):
try:
print("Resolving the list stats info")
loadedStats = stats()
print(loadedStats)
payload = {
"success": True,
"results": loadedStats
}
except Exception as error:
payload = {
"success": False,
"errors": [str(error)]
}
return payload

@query.field("filteredStats")
def resolve_filteredStats(*_, name=None):
try:
print("Resolving the list stats info")
loadedStats = user_stats(name)
print(loadedStats)
payload = {
"success": True,
"results": loadedStats
}
except Exception as error:
payload = {
"success": False,
"errors": [str(error)]
}
return payload


@app.route('/')
def index():
Expand Down Expand Up @@ -103,6 +163,7 @@ def user_stats(username):
stats = list(db.exercises.aggregate(pipeline))
return jsonify(stats=stats)

schema = make_executable_schema(type_defs, query)

@app.route('/stats/weekly/', methods=['GET'])
def weekly_user_stats():
Expand Down Expand Up @@ -158,4 +219,4 @@ def weekly_user_stats():


if __name__ == "__main__":
app.run(debug=True, host='0.0.0.0', port=5050)
app.run(debug=True, host='0.0.0.0', port=5050)
23 changes: 22 additions & 1 deletion analytics/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,25 @@ pymongo==4.2.0
gunicorn==20.1.0
python-dotenv==0.19.0
Flask-PyMongo==2.3.0
Flask-CORS==3.0.10
Flask-CORS==3.0.10
mongomock==3.22.0
anyio==4.2.0
ariadne==0.11.0
blinker==1.7.0
click==8.1.7
dnspython==2.4.2
Flask-SQLAlchemy==3.1.1
graphql-core==3.0.5
idna==3.6
itsdangerous==2.1.2
Jinja2==3.1.2
MarkupSafe==2.1.3
packaging==23.2
sniffio==1.3.0
SQLAlchemy==2.0.25
starlette<0.14
typing_extensions==4.9.0
Werkzeug==3.0.1



23 changes: 23 additions & 0 deletions analytics/schema.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
schema {
query: Query
}
type Stats{
username: String!
exercises: [Exercise]
}

type Exercise {
exerciseType: String
totalDuration: Int
}

type StatsResult {
success: Boolean!
errors: [String]
results: [Stats]
}

type Query {
stats: StatsResult
filteredStats(name: String): StatsResult
}
47 changes: 47 additions & 0 deletions analytics/test_api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# test_analytics_api.py
import unittest
from flask import json
from app import app
import mongomock

class AnalyticsAPITestCase(unittest.TestCase):
def setUp(self):
# Create a mongomock client
self.mock_client = mongomock.MongoClient()
app.config["MONGO_URI"] = "mongomock://localhost"

# Patch the application's database client with the mock client
app.db_client = self.mock_client

# Continue with setting up a test client for Flask
self.app = app.test_client()

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

I'm not sure this sets up the db mock properly - try implementing the way we caught up about!

#test_client used to simulate requests and test reponse without running server
self.app.testing = True

def test_root_endpoint(self):
response = self.app.get('/')
self.assertEqual(response.status_code, 200)
# Assuming the response is JSON with a list of exercises
data = json.loads(response.data)
self.assertIsInstance(data, list) # Check if data is a list

def test_stats_endpoint(self):
response = self.app.get('/stats')
self.assertEqual(response.status_code, 200)
data = json.loads(response.data)
self.assertTrue('stats' in data) # Check if 'stats' key exists in response

def test_user_stats_endpoint(self):
response = self.app.get('/stats/testuser')
self.assertEqual(response.status_code, 200)
data = json.loads(response.data)
self.assertTrue('stats' in data)

def test_weekly_user_stats(self):
response = self.app.get('/stats/weekly/?user=testuser&start=2022-01-01&end=2022-01-07')
self.assertEqual(response.status_code, 200)
data = json.loads(response.data)
self.assertTrue('stats' in data)

if __name__ == '__main__':
unittest.main()