DEV Community

Manoj Kumar
Manoj Kumar

Posted on

GitHub Metric Microservices Deployment on AWS using ECR - Part 2 - Issue Service & PR Service

In Part 1, we looked at setting up the AWS configurations and the implementation of Commit Service. Let's look at how the rest of the microservices are implemented. This is a lengthy part so make sure to read until the very end and move to part 3.

Issue Service

This service fetches the user’s connected issues and saves them to the DynamoDB table – deviq_issues and returns the issues in order – Issues Created by user, issued assigned to the user and issues closed by the user. This service runs on port 5021.

issueService.py

import requests
import issueServiceUtil
import boto3

from flask import Flask

issueApp = Flask(__name__)

@issueApp.route('/')
def index():
    return "Hello! from Issue Service"

session = boto3.Session(region_name='<aws_region')
dynamodb = session.resource('dynamodb')
table_name = '<table_name>'
table = dynamodb.Table(table_name)



@issueApp.route('/issues/<username>')
def get_user_issues(username):
    json_array_response = []
    maxId = getPid.getMaxPid()
    token = getPid.get_gh_token()
    # Get issues created by the user
    created_url = f"https://api.github.com/search/issues?q=author:{username}"
    created_response = requests.get(created_url, headers={"Authorization": f"token {token}"})

    if created_response.status_code == 200:
        created_issues = created_response.json()['items']
        print(f"Issues created by {username}:")
        for issue in created_issues:
            table.put_item(Item={
                'pid':maxId,
                'gh_username': username,
                'issue_title': issue['title'],
                'url':issue['html_url'],
                'type': 'CREATED'
                })
            maxId+=1
            print(f"- {issue['title']} ({issue['html_url']})")

        json_array_response.append(created_issues)

    else:
        print(f"Error: {created_response.status_code}")

    # Get issues assigned to the user
    assigned_url = f"https://api.github.com/search/issues?q=assignee:{username}"
    assigned_response = requests.get(assigned_url, headers={"Authorization": f"token {token}"})

    if assigned_response.status_code == 200:
        assigned_issues = assigned_response.json()['items']
        print(f"Issues assigned to {username}:")
        for issue in assigned_issues:
            table.put_item(Item={
                'pid':maxId,
                'gh_username': username,
                'issue_title': issue['title'],
                'url':issue['html_url'],
                'type': 'ASSIGNED'
                })
            maxId+=1
            print(f"- {issue['title']} ({issue['html_url']})")
        json_array_response.append(assigned_issues)
    else:
        print(f"Error: {assigned_response.status_code}")

    # Get closed issues by the user
    closed_url = f"https://api.github.com/search/issues?q=author:{username}+is:closed"
    closed_response = requests.get(closed_url, headers={"Authorization": f"token {token}"})

    if closed_response.status_code == 200:
        closed_issues = closed_response.json()['items']
        print(f"Closed issues by {username}:")
        for issue in closed_issues:
            table.put_item(Item={
                'pid':maxId,
                'gh_username': username,
                'issue_title': issue['title'],
                'url':issue['html_url'],
                'type': 'CLOSED'
                })
            maxId+=1
            print(f"- {issue['title']} ({issue['html_url']})")
        json_array_response.append(closed_issues)
    else:
        print(f"Error: {closed_response.status_code}")

    return json_array_response

if __name__ == '__main__':
    issueApp.run(debug=True, host='0.0.0.0', port=5021)
Enter fullscreen mode Exit fullscreen mode

Quick peek into issueServiceUtil.py

import boto3
import json

# Initialize a DynamoDB client
dynamodb = boto3.resource('dynamodb', region_name='<aws_region>')

# Specify the table name and column (attribute) name
table_name = '<table_name>'
column_name = '<key>'

# Initialize a DynamoDB table resource
table = dynamodb.Table(table_name)

# Perform a scan operation to get all items sorted in descending order by the specified column
response = table.scan()

def getMaxPid():
    # Check if any items were returned
    if 'Items' in response:
        items = response['Items']
        if len(items) > 0:
            max_value = max(item[column_name] for item in items)
            print(f"The maximum value for {column_name} is: {max_value}")
            return max_value + 1
        else:
            print(f"No items found in the table")
            return 1
    else:
        print(f"Error in scanning the table")
        return -1


def get_gh_token():
    secret_name = "<SECRET_NAME>"
    region_name = "<aws_region>"
    session = boto3.Session()
    client = session.client(service_name='secretsmanager', region_name=region_name)
    get_s = client.get_secret_value(SecretId = secret_name)

    secret = get_s['SecretString']
    ss = json.loads(secret)
    return ss['github_token']
Enter fullscreen mode Exit fullscreen mode

deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: issueservice-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: issueservice
  template:
    metadata:
      labels:
        app: issueservice
    spec:
      containers:
      - name: issueservice
        image: <ecr_image_id:tag>
        ports:
        - containerPort: 5021
Enter fullscreen mode Exit fullscreen mode

service.yaml

apiVersion: v1
kind: Service
metadata:
  name: issueservice-service
spec:
  selector:
    app: issueservice
  ports:
    - protocol: TCP
      port: 5021
      targetPort: 5021
  type: LoadBalancer 
Enter fullscreen mode Exit fullscreen mode

PR (Pull Request) Service

This service fetches the user’s assigned pull requests and saves them to the DynamoDB table – deviq_prs and returns those Pull Requests. This service runs on port 5069😉

prService.yaml

import requests
from datetime import datetime
import boto3
import getPid

from flask import Flask

prApp = Flask(__name__)

date_format = "%Y-%m-%dT%H:%M:%SZ"

session = boto3.Session(region_name='<aws_region>')
dynamodb = session.resource('dynamodb')
table_name = '<table_name>'
table = dynamodb.Table(table_name)

@prApp.route('/')
def index():
    return "Hello! from PR Service"

@prApp.route('/pr/<username>')
def get_user_pullrequests(username):
    token = getPid.get_gh_token()
    repo_url = f"https://api.github.com/users/{username}/repos?type=owner"
    response = requests.get(repo_url, headers={"Authorization": f"token {token}"})
    prs =[]

    maxId = getPid.getMaxPid()
    if response.status_code == 200:
        repositories = response.json()
        for repo in repositories:
            repo_name = repo["name"]
            owner = repo["owner"]["login"]

            pr_url = f"https://api.github.com/repos/{owner}/{repo_name}/pulls?state=all"

            # Step 2: Get the list of pull requests for each repository
            response = requests.get(pr_url, headers={"Authorization": f"token {token}"})
            pull_requests = response.json()

            for pr in pull_requests:
                pr_created_at = pr["created_at"]
                pr_closed_at = pr["closed_at"] if pr["closed_at"] else pr["updated_at"]

                # Step 3: Calculate the resolution time for each pull request
                resolution_time = (datetime.strptime(pr_closed_at,date_format) - datetime.strptime(pr_created_at, date_format)).total_seconds() / 60
                print(f"Pull Request #{pr['number']} in {owner}/{repo_name} resolved in {round(resolution_time, ndigits= 3)} minutes.")

                table.put_item(Item={
                'pid':maxId,
                'gh_username': username,
                'PR No': f"Pull Request # {pr['number']}",
                'repo_name': f"{owner}/{repo_name}",
                'resolving time': int(round(resolution_time, ndigits= 3))
                })

                pr = {
                'PR No': f"Pull Request # {pr['number']}",
                'repo_name': f"{owner}/{repo_name}",
                'resolving time': int(round(resolution_time, ndigits= 3))
                }
                #pr_json = json.dumps(pr)

                prs.append(pr)
                maxId+=1

    else:
        return f"Error: {response}"

    return prs
if __name__ == '__main__':
    prApp.run(debug=True,host='0.0.0.0', port=5069)
Enter fullscreen mode Exit fullscreen mode

and the prServiceUtil.py

import boto3
import json
# Initialize a DynamoDB client
dynamodb = boto3.resource('dynamodb', region_name='<aws_region>')

# Specify the table name and column (attribute) name
table_name = '<table_name>'
column_name = '<key>'

# Initialize a DynamoDB table resource
table = dynamodb.Table(table_name)

# Perform a scan operation to get all items sorted in descending order by the specified column
response = table.scan()

def getMaxPid():
    # Check if any items were returned
    if 'Items' in response:
        items = response['Items']
        if len(items) > 0:
            max_value = max(item[column_name] for item in items)
            print(f"The maximum value for {column_name} is: {max_value}")
            return max_value + 1
        else:
            print(f"No items found in the table")
            return 1
    else:
        print(f"Error in scanning the table")
        return -1


def get_gh_token():
    secret_name = "<SECRET_NAME>"
    region_name = "<aws_region>"
    session = boto3.Session()
    client = session.client(service_name='secretsmanager', region_name=region_name)
    get_s = client.get_secret_value(SecretId = secret_name)

    secret = get_s['SecretString']
    ss = json.loads(secret)
    return ss['github_token']

Enter fullscreen mode Exit fullscreen mode

Top comments (0)