Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add bitrise API #62

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
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
8 changes: 8 additions & 0 deletions .github/workflows/staging-push.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ jobs:
echo "JIRA_PASSWORD=${{ secrets.JIRA_PASSWORD }}" >> $GITHUB_ENV
echo "GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }}" >> $GITHUB_ENV
echo "BUGZILLA_API_KEY=${{ secrets.BUGZILLA_API_KEY }}" >> $GITHUB_ENV
echo "BITRISE_HOST=${{ secrets.BITRISE_HOST }}" >> $GITHUB_ENV
echo "BITRISE_APP_SLUG=${{ secrets.BITRISE_APP_SLUG }}" >> $GITHUB_ENV


- name: Update DB - test runs
run: python ./__main__.py --report-type test-case-coverage --platform mobile --project ALL
Expand All @@ -63,9 +66,14 @@ jobs:
if: always()
run: python ./__main__.py --report-type bugzilla-qe-verify

- name: Bitrise Build Count
if: always()
run: python ./__main__.py --platform mobile --project firefox-ios --report-type bitrise-builds

- name: Set job log URL
if: always()
run: echo "JOB_LOG_URL=https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" >> $GITHUB_ENV

- name: Send custom JSON data to Slack workflow
if: always()
id: slack
Expand Down
4 changes: 4 additions & 0 deletions __main__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import argparse
import sys

from bitrise import BitriseClient
from bugz import BugzillaClient
from github import GithubClient
from jira import JiraClient
Expand Down Expand Up @@ -115,6 +116,9 @@ def main():
if args.report_type == 'bugzilla-qe-verify':
h = BugzillaClient()
h.bugzilla_qe_verify()
if args.report_type == 'bitrise-builds':
h = BitriseClient()
h.builds_count()


if __name__ == '__main__':
Expand Down
59 changes: 59 additions & 0 deletions bitrise.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import sys
import os

from lib.bitrise_conn import BitriseAPIClient
from database import (
Database,
ReportBitriseBuildsCount
)


class Bitrise:

def __init__(self):
try:
BITRISE_HOST = os.environ['BITRISE_HOST']
self.client = BitriseAPIClient(BITRISE_HOST)
self.BITRISE_APP_SLUG = os.environ['BITRISE_APP_SLUG']
except KeyError:
print("ERROR: Missing bitrise env var")
sys.exit(1)

# API: Projects
def builds(self):
return self.client.get_builds(self.BITRISE_APP_SLUG)


class BitriseClient(Bitrise):

def __init__(self):
super().__init__()
print("Init")
self.db = DatabaseBitrise()

def builds_count(self):
# Pull JSON blob from Bitrise
payload = self.builds()

data_frame = self.db.report_bitrise_builds_count(payload)
self.db.report_bitrise_builds_count_insert(data_frame)


class DatabaseBitrise(Database):

def __init__(self):
super().__init__()
self.db = Database()

def report_bitrise_builds_count(self, payload):
# Normalize the JSON data
total_count = payload.get("paging", {}).get("total_item_count")

data = [total_count]
return data

def report_bitrise_builds_count_insert(self, payload):
report = ReportBitriseBuildsCount(total_builds=payload[0])

self.session.add(report)
self.session.commit()
4 changes: 4 additions & 0 deletions database.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ class ReportTestRailMilestones(Base):
__table__ = Table('report_testrail_milestones', Base.metadata, autoload=True) # noqa


class ReportBitriseBuildsCount(Base):
__table__ = Table('report_bitrise_builds_count', Base.metadata, autoload=True) # noqa


class Database:

def __init__(self):
Expand Down
148 changes: 32 additions & 116 deletions lib/bitrise_conn.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
from datetime import datetime
from enum import Enum
import os
import sys
import datetime
import time

import argparse
import logging
import requests

Expand All @@ -12,73 +9,21 @@
_logger = logging.getLogger(__name__)


def parse_args(cmdln_args):
parser = argparse.ArgumentParser(
description="Gets build data for a targeted app on Bitrise"
)
class BitriseAPIClient:

parser.add_argument(
"--project",
help="Use selected project",
required=True,
choices=['ios', 'android']
)

parser.add_argument(
"--branch",
help="Use selected branch",
required=False,
default=None
)

parser.add_argument(
"--workflow",
help="Use selected workflow",
required=False,
default=None
)

parser.add_argument(
"--before",
help="List builds run before a given date (epoch time)",
required=False,
default=None,
type=datetime.fromisoformat
)

parser.add_argument(
"--after",
help="List builds run after a given date (epoch time)",
required=False,
default=None,
type=datetime.fromisoformat
)

return parser.parse_args(args=cmdln_args)


class Status(Enum):
NOT_FINISHED = 0
SUCCESSFUL = 1
FAILURE = 2
ABORTED_FAILURE = 3
ABORTED_SUCCESS = 4


class Bitrise:

def __init__(self):
def __init__(self, base_url):
try:
self.API_TOKEN = os.environ['BITRISE_TOKEN']
self.API_HEADER = {'Authorization': self.API_TOKEN,
'accept': 'application/json'}
self.API_HEADER = {'accept': 'application/json'}
self.BITRISE_APP_SLUG = ''
self.__url = base_url

except KeyError:
print("ERROR: must set BITRISE_TOKEN")
exit()

def get_apps(self):
resp = requests.get('https://api.bitrise.io/v0.1/apps',
url = self.__url
resp = requests.get(url,
headers=self.API_HEADER)
if resp.status_code != 200:
raise print('GET /apps/ {}'.format(resp.status_code))
Expand All @@ -87,73 +32,44 @@ def get_apps(self):
def set_app(self, project, apps):
if apps is not None:
if project == "android":
self.APP_SLUG = apps['data'][0]['slug']
self.BITRISE_APP_SLUG = apps['data'][0]['slug']
elif project == "ios":
self.APP_SLUG = apps['data'][1]['slug']
self.BITRISE_APP_SLUG = apps['data'][1]['slug']

def get_app(self, project, apps):
if not self.APP_SLUG:
resp = requests.get('https://api.bitrise.io/v0.1/apps/{0}'.
format(self.APP_SLUG),
url = self.__url
if not self.BITRISE_APP_SLUG:
resp = requests.get('{0}''{1}'.
format(url, self.BITRISE_APP_SLUG),
headers=self.API_HEADER)
if resp.status_code != 200:
raise _logger.error('GET /apps/ {}'.format(resp.status_code))
return resp.json()

def get_workflows(self, APP_SLUG):
def get_workflows(self, BITRISE_APP_SLUG):
url = self.__url
resp = \
requests.get('https://api.bitrise.io/v0.1/apps/{0}'
'/build-workflows'.format(self.APP_SLUG),
requests.get('{0}{1}'
'/build-workflows'.format(url, self.BITRISE_APP_SLUG),
headers=self.API_HEADER)
if resp.status_code != 200:
raise _logger.error('GET /apps/ {}'.format(resp.status_code))
return resp.json()

def get_builds(self, params=None):
def get_builds(self, BITRISE_APP_SLUG):
url = self.__url
days_ago = 1
today = datetime.datetime.utcnow().date()
past_date = today - datetime.timedelta(days=days_ago)
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I would need to think how to narrow this down so that we are sure that we count the builds after sometime and right before the github action runs.

print(past_date)
past_date_timestamp = int(time.mktime(past_date.timetuple()))
print(past_date_timestamp)

# Change to BITRISE_HOST
resp = \
requests.get('https://api.bitrise.io/v0.1/apps/{0}'
'/builds'.format(self.APP_SLUG),
headers=self.API_HEADER, params=params)
requests.get('{0}{1}'
'/builds?after={2}'.format(url, BITRISE_APP_SLUG, past_date_timestamp), # noqa
headers=self.API_HEADER)
if resp.status_code != 200:
raise _logger.error('GET /apps/ {}'.format(resp.status_code))
return resp.json()


def main():
args = parse_args(sys.argv[1:])

b = Bitrise()

all_apps = b.get_apps()

b.set_app(args.project, all_apps)
workflows = b.get_workflows(b.APP_SLUG)
builds = b.get_builds({"branch": args.branch,
"workflow": args.workflow,
"after": int(datetime.timestamp(args.after))
if args.after is not None else None,
"before": int(datetime.timestamp(args.before))
if args.before is not None else None})

failures = b.get_failure_count(builds)
print("All recent builds Failure count: {0}".format(failures))

successes = b.get_success_count(builds)
print("All recent builds Success count: {0}".format(successes))

not_finished = b.get_not_finished_count(builds)
print("All recent builds Not finished count: {0}".format(not_finished))

aborted_failure = b.get_aborted_failure(builds)
print("All recent builds Aborted Failure count: {0}"
.format(aborted_failure))

aborted_success = b.get_aborted_success(builds)
print("All recent builds Aborted Success count: {0}"
.format(aborted_success))

print(*workflows['data'], sep=", ")


if __name__ == '__main__':
main()
3 changes: 2 additions & 1 deletion utils/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@
'jira-qa-requests',
'jira-qa-needed',
'bugzilla-qe-verify',
'testrail-milestones'
'testrail-milestones',
'bitrise-builds'
]

# JQL query All QA Requests since 2022 filter_id: 13856
Expand Down