Skip to content

Commit

Permalink
Merge pull request #47 from Code4GovTech/supabase_migration_orm
Browse files Browse the repository at this point in the history
Supabase migration orm
  • Loading branch information
sasi2312 authored Aug 13, 2024
2 parents e711754 + 9c5f284 commit 2bdfa5c
Show file tree
Hide file tree
Showing 9 changed files with 288 additions and 172 deletions.
8 changes: 8 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ jobs:
SUPABASE_URL: ${{ vars[format('APP_{0}_SUPABASE_URL', needs.set_vars.outputs.APP_ENV)] }}
SUPABASE_KEY: ${{ secrets[format('APP_{0}_SUPABASE_KEY', needs.set_vars.outputs.APP_ENV)] }}
SECRET_KEY: ${{ secrets[format('APP_{0}_SECRET_KEY', needs.set_vars.outputs.APP_ENV)] }}
POSTGRES_DB_HOST: ${{ secrets[format('APP_{0}_POSTGRES_DB_HOST', needs.set_vars.outputs.APP_ENV)] }}
POSTGRES_DB_NAME: ${{ secrets[format('APP_{0}_POSTGRES_DB_NAME', needs.set_vars.outputs.APP_ENV)] }}
POSTGRES_DB_USER: ${{ secrets[format('APP_{0}_POSTGRES_DB_USER', needs.set_vars.outputs.APP_ENV)] }}
POSTGRES_DB_PASS: ${{ secrets[format('APP_{0}_POSTGRES_DB_PASS', needs.set_vars.outputs.APP_ENV)] }}
steps:
- name: Checkout code
uses: actions/checkout@v2
Expand All @@ -87,6 +91,10 @@ jobs:
echo "SUPABASE_URL=${SUPABASE_URL}" >> .env
echo "SUPABASE_KEY=${SUPABASE_KEY}" >> .env
echo "SECRET_KEY=${SECRET_KEY}" >> .env
echo "POSTGRES_DB_HOST=${POSTGRES_DB_HOST}" >> .env
echo "POSTGRES_DB_NAME=${POSTGRES_DB_NAME}" >> .env
echo "POSTGRES_DB_USER=${POSTGRES_DB_USER}" >> .env
echo "POSTGRES_DB_PASS=${POSTGRES_DB_PASS}" >> .env
mv .env ${{ env.DOT_ENV_FILE_NAME }}
- name: Copy env file to DEV Server
Expand Down
107 changes: 28 additions & 79 deletions app.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,25 @@
from flask import Flask, jsonify,request,url_for
from db import SupabaseInterface
from collections import defaultdict
from flasgger import Swagger
import re,os,traceback
from query import PostgresORM
from utils import *
from flask_cors import CORS,cross_origin
from v2_app import v2
from flask_sqlalchemy import SQLAlchemy
from models import db



app = Flask(__name__)
CORS(app,supports_credentials=True)


app.config['SQLALCHEMY_DATABASE_URI'] = PostgresORM.get_postgres_uri()
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

db.init_app(app)

Swagger(app)

GITHUB_TOKEN =os.getenv('GITHUB_TOKEN')
Expand Down Expand Up @@ -45,61 +53,6 @@ def greeting():




@app.route('/get-data', methods=['GET'])
@cross_origin(supports_credentials=True)
@require_secret_key
def get_data():
"""
Fetch data from Supabase.
---
responses:
200:
description: Data fetched successfully
schema:
type: array
items:
type: object
500:
description: Error fetching data
schema:
type: object
properties:
error:
type: string
"""
try:
response = SupabaseInterface().get_instance().client.table('dmp_pr_updates').select('*').execute()
data = response.data
return jsonify(data)
except Exception as e:
return jsonify({'error': str(e)}), 200



@app.route('/v1/issues', methods=['GET'])
@require_secret_key
def v1get_issues():
try:
response = SupabaseInterface().get_instance().client.table('dmp_issue_updates').select('*').execute()
data = response.data

#group data based on issues
grouped_data = defaultdict(list)
for record in data:
issue_url = record['issue_url']
grouped_data[issue_url].append({
'id': record['id'],
'name': record['body_text']
})

result = [{'issue_url': issue_url, 'issues': issues} for issue_url, issues in grouped_data.items()]
grouped_data = group_by_owner(result)
return jsonify(grouped_data)

except Exception as e:
error_traceback = traceback.format_exc()
return jsonify({'error': str(e), 'traceback': error_traceback}), 200


@app.route('/issues', methods=['GET'])
Expand Down Expand Up @@ -127,21 +80,18 @@ def get_issues():
type: string
"""
try:
# Fetch all issues with their details
response = SupabaseInterface().get_instance().client.table('dmp_orgs').select('*, dmp_issues(*)').execute()
res = []

for org in response.data:
obj = {}
issues = org['dmp_issues']
obj['org_id'] = org['id']
obj['org_name'] = org['name']
renamed_issues = [{"id": issue["id"], "name": issue["title"]} for issue in issues]
obj['issues'] = renamed_issues

res.append(obj)

return jsonify({"issues": res})
# Fetch all issues with their details
data = PostgresORM.get_issue_query()
response = []

for result in data:
response.append({
'org_id': result.org_id,
'org_name': result.org_name,
'issues': result.issues
})

return jsonify({"issues": response})

except Exception as e:
error_traceback = traceback.format_exc()
Expand Down Expand Up @@ -190,16 +140,15 @@ def get_issues_by_owner(owner):
description: Error message
"""
try:
# Construct the GitHub URL based on the owner parameter
org_link = f"https://github.com/{owner}"


# Fetch organization details from dmp_orgs table
response = SupabaseInterface().get_instance().client.table('dmp_orgs').select('name', 'description').eq('name', owner).execute()

if not response.data:
response = PostgresORM.get_issue_owner(owner)
if not response:
return jsonify({'error': "Organization not found"}), 404

return jsonify(response.data)

orgs_dict = [org.to_dict() for org in response]

return jsonify(orgs_dict)

except Exception as e:
error_traceback = traceback.format_exc()
Expand Down
61 changes: 0 additions & 61 deletions db.py
Original file line number Diff line number Diff line change
@@ -1,61 +0,0 @@
import os, sys
from typing import Any
from supabase import create_client, Client
from supabase.lib.client_options import ClientOptions
from abc import ABC, abstractmethod

client_options = ClientOptions(postgrest_client_timeout=None)



class SupabaseInterface():

_instance = None

def __init__(self):
if not SupabaseInterface._instance:

# Load environment variables
from dotenv import load_dotenv
load_dotenv()

SUPABASE_URL = os.getenv('SUPABASE_URL')
SUPABASE_KEY = os.getenv('SUPABASE_KEY')
self.client: Client = create_client(SUPABASE_URL, SUPABASE_KEY)
SupabaseInterface._instance = self
else:
SupabaseInterface._instance = self._instance



@staticmethod
def get_instance():
# Static method to retrieve the singleton instance
if not SupabaseInterface._instance:
# If no instance exists, create a new one
SupabaseInterface._instance = SupabaseInterface()
return SupabaseInterface._instance


def readAll(self, table):
data = self.client.table(f"{table}").select("*").execute()
return data.data

def add_data(self, data,table_name):
data = self.client.table(table_name).insert(data).execute()
return data.data

def add_data_filter(self, data, table_name):
# Construct the filter based on the provided column names and values
filter_data = {column: data[column] for column in ['dmp_id','issue_number','owner']}

# Check if the data already exists in the table based on the filter
existing_data = self.client.table(table_name).select("*").eq('dmp_id',data['dmp_id']).execute()

# If the data already exists, return without creating a new record
if existing_data.data:
return "Data already exists"

# If the data doesn't exist, insert it into the table
new_data = self.client.table(table_name).insert(data).execute()
return new_data.data
141 changes: 141 additions & 0 deletions models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from datetime import datetime

db = SQLAlchemy()

class DmpOrg(db.Model):
__tablename__ = 'dmp_orgs'

id = db.Column(db.Integer, primary_key=True, autoincrement=True)
created_at = db.Column(db.DateTime, default=datetime.utcnow, nullable=False)
name = db.Column(db.String, nullable=False)
description = db.Column(db.Text, nullable=True)
link = db.Column(db.String, nullable=False)
repo_owner = db.Column(db.String, nullable=False)

# Relationship to DmpIssueUpdate
issues = db.relationship('DmpIssueUpdate', backref='organization', lazy=True)

# Updated relationship name to avoid conflict
dmp_issues = db.relationship('DmpIssue', backref='organization', lazy=True)

def __repr__(self):
return f"<DmpOrg(id={self.id}, name={self.name})>"

def to_dict(self):
return {
'id': self.id,
'created_at': self.created_at.isoformat(),
'name': self.name,
'description': self.description,
'link': self.link,
'repo_owner': self.repo_owner
}

class DmpIssue(db.Model):
__tablename__ = 'dmp_issues'

id = db.Column(db.Integer, primary_key=True, autoincrement=True)
issue_url = db.Column(db.String, nullable=False)
issue_number = db.Column(db.Integer, nullable=False)
mentor_username = db.Column(db.String, nullable=True)
contributor_username = db.Column(db.String, nullable=True)
title = db.Column(db.String, nullable=False)
org_id = db.Column(db.Integer, db.ForeignKey('dmp_orgs.id'), nullable=False)
description = db.Column(db.Text, nullable=True)
repo = db.Column(db.String, nullable=True)


# Relationship to Prupdates
pr_updates = db.relationship('Prupdates', backref='pr_details', lazy=True)

def __repr__(self):
return f"<DmpIssue(id={self.id}, title={self.title})>"

def to_dict(self):
return {
'id': self.id,
'issue_url': self.issue_url,
'issue_number': self.issue_number,
'mentor_username': self.mentor_username,
'contributor_username': self.contributor_username,
'title': self.title,
'org_id': self.org_id,
'description': self.description,
'repo': self.repo
}

class DmpIssueUpdate(db.Model):
__tablename__ = 'dmp_issue_updates'

created_at = db.Column(db.DateTime, default=datetime.utcnow, nullable=False)
body_text = db.Column(db.Text, nullable=False)
comment_link = db.Column(db.String, nullable=False)
comment_id = db.Column(db.BigInteger, primary_key=True, nullable=False)
comment_api = db.Column(db.String, nullable=False)
comment_updated_at = db.Column(db.DateTime, nullable=False)
dmp_id = db.Column(db.Integer, db.ForeignKey('dmp_orgs.id'), nullable=False)
created_by = db.Column(db.String, nullable=False)

def __repr__(self):
return f"<DmpIssueUpdate(comment_id={self.comment_id}, dmp_id={self.dmp_id})>"

def to_dict(self):
return {
'created_at': self.created_at.isoformat(),
'body_text': self.body_text,
'comment_link': self.comment_link,
'comment_id': self.comment_id,
'comment_api': self.comment_api,
'comment_updated_at': self.comment_updated_at.isoformat(),
'dmp_id': self.dmp_id,
'created_by': self.created_by
}

class Prupdates(db.Model):
__tablename__ = 'dmp_pr_updates'

created_at = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
pr_id = db.Column(db.Integer, nullable=False,primary_key=True)
status = db.Column(db.String, nullable=False)
title = db.Column(db.String, nullable=False)
pr_updated_at = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
merged_at = db.Column(db.DateTime)
closed_at = db.Column(db.DateTime)
dmp_id = db.Column(db.Integer, db.ForeignKey('dmp_issues.id'), nullable=False) # ForeignKey relationship
link = db.Column(db.String, nullable=False)

def __repr__(self):
return f'<PullRequest {self.pr_id} - {self.title}>'

def to_dict(self):
return {
'created_at': self.created_at.isoformat(),
'pr_id': self.pr_id,
'status': self.status,
'title': self.title,
'pr_updated_at': self.pr_updated_at.isoformat(),
'merged_at': self.merged_at.isoformat() if self.merged_at else None,
'closed_at': self.closed_at.isoformat() if self.closed_at else None,
'dmp_id': self.dmp_id,
'link': self.link
}

class DmpWeekUpdate(db.Model):
__tablename__ = 'dmp_week_updates'

id = db.Column(db.Integer, primary_key=True, autoincrement=True)
issue_url = db.Column(db.String, nullable=False)
week = db.Column(db.Integer, nullable=False)
total_task = db.Column(db.Integer, nullable=False)
completed_task = db.Column(db.Integer, nullable=False)
progress = db.Column(db.Integer, nullable=False)
task_data = db.Column(db.Text, nullable=False)
dmp_id = db.Column(db.Integer, nullable=False)

def __repr__(self):
return f"<DmpWeekUpdate(id={self.id}, week={self.week}, dmp_id={self.dmp_id})>"

# if __name__ == '__main__':
# db.create_all()
Loading

0 comments on commit 2bdfa5c

Please sign in to comment.