Skip to content

Commit

Permalink
feat: adds health endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
Justintime50 committed Aug 17, 2021
1 parent 41a8c97 commit c91b71a
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 37 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# CHANGELOG

## v0.12.0 (2021-08-17)

* Adds a `/health` endpoint that returns a 200 if Harvey is up and running

## v0.11.0 (2021-07-19)

* Adds the ability to filter webhooks based on origin, this is great if you want to deny all requests that don't come from GitHub. This can be achieved via the `FILTER_WEBHOOKS` environment variable (closes #41)
Expand Down
24 changes: 16 additions & 8 deletions harvey/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,21 @@
# TODO: Add authentication to each endpoint


@API.route('/health', methods=['GET'])
def healthcheck():
"""Return a 200 if Harvey is running."""
status_code = 200
response = {
'success': True,
'message': 'Ok',
}, status_code

return response


@API.route('/pipelines/start', methods=['POST'])
def start_pipeline():
"""Start a pipeline based on webhook data
"""
"""Start a pipeline based on webhook data."""
return Webhook.parse_webhook(request=request, use_compose=False)


Expand All @@ -45,8 +56,7 @@ def start_pipeline_compose():

@API.route('/pipelines/<pipeline_id>', methods=['GET'])
def retrieve_pipeline(pipeline_id):
"""Retrieve a pipeline's logs by ID
"""
"""Retrieve a pipeline's logs by ID."""
# TODO: This is a hacky temporary solution until we can
# store this data in a database and is not meant to remain
# as a long-term solution
Expand All @@ -61,17 +71,15 @@ def retrieve_pipeline(pipeline_id):

@API.route('/pipelines', methods=['GET'])
def retrieve_pipelines():
"""Retrieve a list of pipelines
"""
"""Retrieve a list of pipelines."""
# TODO: This is a hacky temporary solution until we can
# store this data in a database and is not meant to remain
# as a long-term solution
pipelines = {'pipelines': []}
for root, dirs, files in os.walk(Global.PROJECTS_LOG_PATH, topdown=True):
for file in files:
timestamp = time.ctime(os.path.getmtime(os.path.join(root, file)))
pipelines['pipelines'].append(
f'{timestamp}: {os.path.join(root, file)}')
pipelines['pipelines'].append(f'{timestamp}: {os.path.join(root, file)}')
return json.dumps(pipelines, indent=4)


Expand Down
38 changes: 17 additions & 21 deletions harvey/globals.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
import os


class Global():
"""Contains global configuration for Harvey
"""
class Global:
"""Contains global configuration for Harvey"""

DOCKER_VERSION = 'v1.41' # Docker API version
# TODO: Figure out how to sync this version number with the one in `setup.py`
HARVEY_VERSION = '0.11.0' # Harvey release
HARVEY_VERSION = '0.12.0' # Harvey release
PROJECTS_PATH = 'projects'
PROJECTS_LOG_PATH = 'logs/projects'
HARVEY_LOG_PATH = 'logs/harvey'
Expand All @@ -26,7 +26,7 @@ class Global():
'pull',
'test',
'deploy',
'full'
'full',
]
# TODO: Get these directly from the API instead of a static list
GITHUB_WEBHOOK_IP_RANGES = [
Expand All @@ -38,44 +38,37 @@ class Global():

@classmethod
def repo_name(cls, webhook):
"""Return the repo name from the webhook JSON
"""
"""Return the repo name from the webhook JSON"""
return webhook['repository']['name'].lower()

@classmethod
def repo_full_name(cls, webhook):
"""Return the repo's full name from the webhook JSON
"""
"""Return the repo's full name from the webhook JSON"""
return webhook['repository']['full_name'].lower()

@classmethod
def repo_commit_author(cls, webhook):
"""Return the repo's commit author name from the webhook JSON
"""
"""Return the repo's commit author name from the webhook JSON"""
return webhook['commits'][0]['author']['name']

@classmethod
def repo_url(cls, webhook):
"""Return the repo's URL from the webhook JSON
"""
"""Return the repo's URL from the webhook JSON"""
return webhook['repository']['ssh_url'] # Use SSH URL so private repos can be cloned/pulled

@classmethod
def repo_owner_name(cls, webhook):
"""Return the repo's owner's name from the webhook JSON
"""
"""Return the repo's owner's name from the webhook JSON"""
return webhook['repository']['owner']['name'].lower()

@classmethod
def repo_commit_id(cls, webhook):
"""Return the repo's id from the webhook JSON
"""
"""Return the repo's id from the webhook JSON"""
return webhook['commits'][0]['id']

@classmethod
def docker_project_name(cls, webhook):
"""Return the project name to be used for containers and images
"""
"""Return the project name to be used for containers and images"""
return f'{Global.repo_owner_name(webhook)}-{Global.repo_name(webhook)}'

@classmethod
Expand All @@ -87,8 +80,11 @@ def github_webhook_ip_ranges(cls):
https://docs.github.com/en/github/authenticating-to-github/keeping-your-account-and-data-secure/about-githubs-ip-addresses # noqa
"""
ip_address_list = [str(ip_address) for ip_range in Global.GITHUB_WEBHOOK_IP_RANGES
for ip_address in ipaddress.IPv4Network(ip_range)]
ip_address_list = [
str(ip_address)
for ip_range in Global.GITHUB_WEBHOOK_IP_RANGES
for ip_address in ipaddress.IPv4Network(ip_range)
]

# Keep localhost included for testing
ip_address_list.append('127.0.0.1')
Expand Down
10 changes: 4 additions & 6 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
'requests == 2.*',
'requests_unixsocket == 0.2.*',
'slackclient == 2.*',
'python-dotenv == 0.17.*'
'python-dotenv == 0.17.*',
]

DEV_REQUIREMENTS = [
Expand All @@ -21,7 +21,7 @@

setuptools.setup(
name='harvey-ci',
version='0.11.0',
version='0.12.0',
description='Your personal CI/CD and Docker orchestration platform.',
long_description=long_description,
long_description_content_type="text/markdown",
Expand All @@ -36,12 +36,10 @@
],
install_requires=REQUIREMENTS,
extras_require={
'dev': DEV_REQUIREMENTS
'dev': DEV_REQUIREMENTS,
},
entry_points={
'console_scripts': [
'harvey-ci=harvey.app:main'
]
'console_scripts': ['harvey-ci=harvey.app:main'],
},
python_requires='>=3.6',
)
4 changes: 2 additions & 2 deletions test/unit/test_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@
@pytest.mark.parametrize(
'route',
[
'health',
'pipelines',
# 'pipelines/<pipeline_id>', # TODO: Figure out how to test endpoints with parameters
]
],
)
def test_routes_are_reachable_get(mock_client, route):
response = mock_client.get(route)
Expand Down

0 comments on commit c91b71a

Please sign in to comment.