Skip to content

Commit

Permalink
Merge branch 'dev' into deploy
Browse files Browse the repository at this point in the history
  • Loading branch information
jonrkarr committed Jan 14, 2021
2 parents 513435f + 4b43c14 commit ec72205
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 18 deletions.
2 changes: 1 addition & 1 deletion biosimulators_test_suite/_version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = '0.1.15'
__version__ = '0.1.16'
72 changes: 57 additions & 15 deletions biosimulators_test_suite/exec_gh_action.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,18 @@ class ValidateCommitSimulatorGitHubAction(GitHubAction):
issue_number (:obj:`str`): number of GitHub issue which triggered the action
"""
BIOSIMULATORS_AUTH_ENDPOINT = 'https://auth.biosimulations.org/oauth/token'
BIOSIMULATORS_AUDIENCE = os.getenv('BIOSIMULATORS_AUDIENCE', 'api.biosimulators.org')
BIOSIMULATORS_API_ENDPOINT = os.getenv('BIOSIMULATORS_API_ENDPOINT', 'https://api.biosimulators.org/')
BIOSIMULATORS_AUDIENCE = os.getenv(
'BIOSIMULATORS_AUDIENCE',
'api.biosimulators.org')
RUNBIOSIMULATIONS_AUDIENCE = os.getenv(
'RUNBIOSIMULATIONS_AUDIENCE',
'dispatch.biosimulations.org')
BIOSIMULATORS_API_ENDPOINT = os.getenv(
'BIOSIMULATORS_API_ENDPOINT',
'https://api.biosimulators.org/')
RUNBIOSIMULATIONS_API_ENDPOINT = os.getenv(
'RUNBIOSIMULATIONS_API_ENDPOINT',
'https://run.api.biosimulations.dev/')
DOCKER_REGISTRY_URL = 'ghcr.io'
DOCKER_REGISTRY_IMAGE_URL_PATTERN = 'ghcr.io/biosimulators/{}:{}'
DEFAULT_SPECIFICATIONS_VERSION = '1.0.0'
Expand Down Expand Up @@ -293,10 +303,14 @@ def commit_simulator(self, submission, specifications, existing_version_specific
existing_version_specifications (:obj:`list` of :obj:`dict`): specifications of other versions of simulation tool
test_results (:obj:`list` of :obj:`TestCaseResults`): results of test cases
"""
# copy image to BioSimulators namespace of Docker registry (GitHub Container Registry)
# commit image
if submission.validate_image:
# copy image to BioSimulators namespace of Docker registry (GitHub Container Registry)
self.push_image(specifications, existing_version_specifications)

# instruct runBioSimulations to generate a Singularity image for the Docker image
self.trigger_conversion_of_docker_image_to_singularity(specifications)

# commit submission to BioSimulators database
if 'biosimulators' not in specifications:
specifications['biosimulators'] = {}
Expand Down Expand Up @@ -370,25 +384,30 @@ def is_submission_latest_version_of_simulator(self, specifications, existing_ver
return False
return True

def trigger_conversion_of_docker_image_to_singularity(self, specifications):
""" Post the simulation to the BioSimulators database
Args:
specifications (:obj:`dict`): specifications of a simulation tool
"""
auth_headers = self.get_auth_headers_for_biosimulations_api(self.RUNBIOSIMULATIONS_AUDIENCE)

response = requests.post(self.RUNBIOSIMULATIONS_API_ENDPOINT + 'images/refresh',
headers=auth_headers,
json={
'simulator': specifications['id'],
'version': specifications['version'],
})
response.raise_for_status()

def post_entry_to_biosimulators_api(self, specifications, existing_version_specifications):
""" Post the simulation to the BioSimulators database
Args:
specifications (:obj:`dict`): specifications of a simulation tool
existing_version_specifications (:obj:`list` of :obj:`dict`): specifications of other versions of simulation tool
"""
api_id = os.getenv('BIOSIMULATORS_API_CLIENT_ID')
api_secret = os.getenv('BIOSIMULATORS_API_CLIENT_SECRET')

response = requests.post(self.BIOSIMULATORS_AUTH_ENDPOINT, json={
'client_id': api_id,
'client_secret': api_secret,
'audience': self.BIOSIMULATORS_AUDIENCE,
"grant_type": "client_credentials",
})
response.raise_for_status()
response_data = response.json()
auth_headers = {'Authorization': response_data['token_type'] + ' ' + response_data['access_token']}
auth_headers = self.get_auth_headers_for_biosimulations_api(self.BIOSIMULATORS_AUDIENCE)

existing_versions = [existing_version_spec['version'] for existing_version_spec in existing_version_specifications]
update_simulator = specifications['version'] in existing_versions
Expand All @@ -400,3 +419,26 @@ def post_entry_to_biosimulators_api(self, specifications, existing_version_speci
requests_method = requests.post
response = requests_method(endpoint, headers=auth_headers, json=specifications)
response.raise_for_status()

def get_auth_headers_for_biosimulations_api(self, audience):
""" Get authorization headers for using one of the BioSimulations REST APIs
(BioSimulators, runBioSimulations, etc.).
Args:
audience (:obj:`str`): API audience
Returns:
:obj:`dict`: authorization headers
"""
api_id = os.getenv('BIOSIMULATORS_API_CLIENT_ID')
api_secret = os.getenv('BIOSIMULATORS_API_CLIENT_SECRET')

response = requests.post(self.BIOSIMULATORS_AUTH_ENDPOINT, json={
'client_id': api_id,
'client_secret': api_secret,
'audience': audience,
"grant_type": "client_credentials",
})
response.raise_for_status()
response_data = response.json()
return {'Authorization': response_data['token_type'] + ' ' + response_data['access_token']}
22 changes: 20 additions & 2 deletions tests/test_exec_gh_action.py
Original file line number Diff line number Diff line change
Expand Up @@ -344,14 +344,14 @@ def put(self, url, json=None, headers=None, auth=None):
with mock.patch('requests.post', side_effect=requests_mock.post):
with mock.patch.object(exec_gh_action.ValidateCommitSimulatorGitHubAction, 'push_image', return_value=None):
action.commit_simulator(SimulatorSubmission(validate_image=True), specs, existing_version_specs, [])
self.assertEqual(requests_mock.n_post, 4)
self.assertEqual(requests_mock.n_post, 6)

existing_version_specs = [{'id': 'tellurium', 'version': '2.1.6'}]
with mock.patch.dict(os.environ, self.env):
with mock.patch('requests.post', side_effect=requests_mock.post):
with mock.patch('requests.put', side_effect=requests_mock.put):
action.commit_simulator(SimulatorSubmission(validate_image=False), specs, existing_version_specs, [])
self.assertEqual(requests_mock.n_post, 5)
self.assertEqual(requests_mock.n_post, 7)
self.assertEqual(requests_mock.n_put, 1)

def test_run(self):
Expand All @@ -365,6 +365,7 @@ def test_run(self):
self._exec_run_mock_objs(requests_mock, docker_mock, validation_run_results)
self.assertEqual(requests_mock.issue_state, 'open')
self.assertEqual(requests_mock.simulator_versions, [])
self.assertEqual(requests_mock.refreshed_images, [])
self.assertEqual(requests_mock.issue_labels, set(['Validate/commit simulator', 'Invalid']))
self.assertEqual(len(requests_mock.issue_messages), 2)
self.assertRegex(requests_mock.issue_messages[-1], 'Specifications must be adhere to the BioSimulators schema')
Expand All @@ -381,6 +382,7 @@ def test_run(self):
self._exec_run_mock_objs(requests_mock, docker_mock, validation_run_results)
self.assertEqual(requests_mock.issue_state, 'open')
self.assertEqual(requests_mock.simulator_versions, [])
self.assertEqual(requests_mock.refreshed_images, [])
self.assertEqual(requests_mock.issue_labels, set(['Validate/commit simulator', 'Validated']))
self.assertEqual(len(requests_mock.issue_messages), 2)
self.assertEqual(requests_mock.issue_messages[-1], 'The specifications of your simulator is valid!')
Expand All @@ -398,6 +400,7 @@ def test_run(self):
self._exec_run_mock_objs(requests_mock, docker_mock, validation_run_results)
self.assertEqual(requests_mock.issue_state, 'open')
self.assertEqual(requests_mock.simulator_versions, [])
self.assertEqual(requests_mock.refreshed_images, [])
self.assertEqual(requests_mock.issue_labels, set(['Validate/commit simulator', 'Invalid']))
self.assertEqual(len(requests_mock.issue_messages), 3)
self.assertRegex(requests_mock.issue_messages[-1], 'Singularity error')
Expand All @@ -415,6 +418,7 @@ def test_run(self):
self._exec_run_mock_objs(requests_mock, docker_mock, validation_run_results)
self.assertEqual(requests_mock.issue_state, 'open')
self.assertEqual(requests_mock.simulator_versions, [])
self.assertEqual(requests_mock.refreshed_images, [])
self.assertEqual(requests_mock.issue_labels, set(['Validate/commit simulator', 'Invalid']))
self.assertEqual(len(requests_mock.issue_messages), 4)
self.assertRegex(requests_mock.issue_messages[-2], 'Passed 0 test cases')
Expand All @@ -432,6 +436,7 @@ def test_run(self):
self._exec_run_mock_objs(requests_mock, docker_mock, validation_run_results)
self.assertEqual(requests_mock.issue_state, 'open')
self.assertEqual(requests_mock.simulator_versions, [])
self.assertEqual(requests_mock.refreshed_images, [])
self.assertEqual(requests_mock.issue_labels, set(['Validate/commit simulator', 'Invalid']))
self.assertEqual(len(requests_mock.issue_messages), 4)
self.assertRegex(requests_mock.issue_messages[-1], 'No test cases are applicable')
Expand All @@ -448,6 +453,7 @@ def test_run(self):
self._exec_run_mock_objs(requests_mock, docker_mock, validation_run_results)
self.assertEqual(requests_mock.issue_state, 'open')
self.assertEqual(requests_mock.simulator_versions, [])
self.assertEqual(requests_mock.refreshed_images, [])
self.assertEqual(requests_mock.issue_labels, set(['Validate/commit simulator', 'Validated']))
self.assertEqual(len(requests_mock.issue_messages), 4)
self.assertRegex(requests_mock.issue_messages[-2], 'Passed 1 test cases:')
Expand All @@ -465,6 +471,7 @@ def test_run(self):
self._exec_run_mock_objs(requests_mock, docker_mock, validation_run_results)
self.assertEqual(requests_mock.issue_state, 'closed')
self.assertEqual(set(v['version'] for v in requests_mock.simulator_versions), set(['2.1.6']))
self.assertEqual(requests_mock.refreshed_images, [{'simulator': 'tellurium', 'version': '2.1.6'}])
self.assertEqual(requests_mock.issue_labels, set(['Validate/commit simulator', 'Validated', 'Approved']))
self.assertEqual(len(requests_mock.issue_messages), 5)
self.assertRegex(requests_mock.issue_messages[-1], 'Your submission was committed to the BioSimulators registry.')
Expand All @@ -489,6 +496,7 @@ def test_run(self):
self._exec_run_mock_objs(requests_mock, docker_mock, validation_run_results)
self.assertEqual(requests_mock.issue_state, 'open')
self.assertEqual(set(v['version'] for v in requests_mock.simulator_versions), set([]))
self.assertEqual(requests_mock.refreshed_images, [])
self.assertEqual(requests_mock.issue_labels, set(['Validate/commit simulator', 'Validated']))
self.assertEqual(len(requests_mock.issue_messages), 5)
self.assertRegex(requests_mock.issue_messages[-1], 'A member of the BioSimulators team will review your submission')
Expand All @@ -509,6 +517,7 @@ def test_run(self):
self._exec_run_mock_objs(requests_mock, docker_mock, validation_run_results)
self.assertEqual(requests_mock.issue_state, 'open')
self.assertEqual(set(v['version'] for v in requests_mock.simulator_versions), set(['2.1.5']))
self.assertEqual(requests_mock.refreshed_images, [])
self.assertEqual(requests_mock.issue_labels, set(['Validate/commit simulator', 'Validated']))
self.assertEqual(len(requests_mock.issue_messages), 5)
self.assertRegex(requests_mock.issue_messages[-1], 'A member of the BioSimulators team will review your submission')
Expand All @@ -529,6 +538,7 @@ def test_run(self):
self._exec_run_mock_objs(requests_mock, docker_mock, validation_run_results)
self.assertEqual(requests_mock.issue_state, 'closed')
self.assertEqual(set(v['version'] for v in requests_mock.simulator_versions), set(['2.1.5', '2.1.6']))
self.assertEqual(requests_mock.refreshed_images, [{'simulator': 'tellurium', 'version': '2.1.6'}])
self.assertEqual(requests_mock.issue_labels, set(['Validate/commit simulator', 'Validated', 'Approved']))
self.assertEqual(len(requests_mock.issue_messages), 5)
self.assertRegex(requests_mock.issue_messages[-1], 'Your submission was committed to the BioSimulators registry.')
Expand All @@ -554,6 +564,7 @@ def test_run(self):
self._exec_run_mock_objs(requests_mock, docker_mock, validation_run_results)
self.assertEqual(requests_mock.issue_state, 'closed')
self.assertEqual(set(v['version'] for v in requests_mock.simulator_versions), set(['2.1.5', '2.1.4']))
self.assertEqual(requests_mock.refreshed_images, [{'simulator': 'tellurium', 'version': '2.1.4'}])
self.assertEqual(requests_mock.issue_labels, set(['Validate/commit simulator', 'Validated', 'Approved']))
self.assertEqual(len(requests_mock.issue_messages), 5)
self.assertRegex(requests_mock.issue_messages[-1], 'Your submission was committed to the BioSimulators registry.')
Expand All @@ -577,6 +588,7 @@ def test_run(self):
self._exec_run_mock_objs(requests_mock, docker_mock, validation_run_results)
self.assertEqual(requests_mock.issue_state, 'closed')
self.assertEqual(set(v['version'] for v in requests_mock.simulator_versions), set(['2.1.5']))
self.assertEqual(requests_mock.refreshed_images, [{'simulator': 'tellurium', 'version': '2.1.5'}])
self.assertEqual(len(requests_mock.simulator_versions[-1]['biosimulators']['validationTests']['results']), 1)
self.assertEqual(requests_mock.simulator_versions[-1]['biosimulators']['validationTests']['results'][0]['case']['id'], 'sedml.case-passed')
self.assertEqual(requests_mock.issue_labels, set(['Validate/commit simulator', 'Validated', 'Approved']))
Expand Down Expand Up @@ -618,6 +630,8 @@ def __init__(self, submitted_version='2.1.6', new_simulator=True, previous_versi
},
]

self.refreshed_images = []

self.issue_labels = set(['Validate/commit simulator'])
if previous_run_valid == True:
self.issue_labels.add('Validated')
Expand Down Expand Up @@ -687,6 +701,10 @@ def post(self, url, json=None, auth=None, headers=None):
else:
error = 'Specs are invalid'
response = None
elif url == exec_gh_action.ValidateCommitSimulatorGitHubAction.RUNBIOSIMULATIONS_API_ENDPOINT + 'images/refresh':
self.refreshed_images.append(json)
error = None
response = None
elif url == 'https://api.github.com/repos/biosimulators/Biosimulators/issues/11/labels':
for label in json['labels']:
self.issue_labels.add(label)
Expand Down

0 comments on commit ec72205

Please sign in to comment.