Merge "add support for storyboard bug and task trackers"
This commit is contained in:
commit
1f611c4ddf
@ -247,7 +247,8 @@ For deliverable set of projects, we use one YAML file per release
|
||||
series to hold all of the metadata for all releases and branches of
|
||||
that deliverable. For each deliverable, we need to track:
|
||||
|
||||
* the launchpad project name (such as ``oslo.config``)
|
||||
* the launchpad project name (such as ``oslo.config``) or storyboard
|
||||
project id (such as ``760``)
|
||||
* the series (Kilo, Liberty, etc.)
|
||||
* the release model being used
|
||||
* for each repository
|
||||
@ -280,6 +281,11 @@ The top level of a deliverable file is a mapping with keys:
|
||||
|
||||
``launchpad``
|
||||
The slug name of the launchpad project, suitable for use in URLs.
|
||||
(Not needed for projects using storyboard.)
|
||||
|
||||
``storyboard``
|
||||
The ID of the storyboard project, suitable for use in URLs and API
|
||||
calls. (Not needed for projects using launchpad.)
|
||||
|
||||
``release-notes``
|
||||
The URL or URLs to the published release notes for the deliverable
|
||||
|
@ -142,13 +142,10 @@ def validate_series_first(deliverable_info, series_name,
|
||||
)
|
||||
|
||||
|
||||
def validate_launchpad(deliverable_info, mk_warning, mk_error):
|
||||
"Look for the launchpad project"
|
||||
try:
|
||||
def validate_bugtracker(deliverable_info, mk_warning, mk_error):
|
||||
"Look for the bugtracker info"
|
||||
if 'launchpad' in deliverable_info:
|
||||
lp_name = deliverable_info['launchpad']
|
||||
except KeyError:
|
||||
mk_error('No launchpad project given')
|
||||
else:
|
||||
try:
|
||||
lp_resp = requests.get('https://api.launchpad.net/1.0/' + lp_name)
|
||||
except requests.exceptions.ConnectionError as e:
|
||||
@ -158,6 +155,35 @@ def validate_launchpad(deliverable_info, mk_warning, mk_error):
|
||||
else:
|
||||
if (lp_resp.status_code // 100) == 4:
|
||||
mk_error('Launchpad project %s does not exist' % lp_name)
|
||||
elif 'storyboard' in deliverable_info:
|
||||
try:
|
||||
sb_id = int(deliverable_info['storyboard'])
|
||||
except (TypeError, ValueError):
|
||||
mk_error('Invalid storyboard ID, must be a number: %s' %
|
||||
deliverable_info['storyboard'])
|
||||
return
|
||||
try:
|
||||
projects_resp = requests.get(
|
||||
'https://storyboard.openstack.org/api/v1/projects'
|
||||
)
|
||||
except requests.exceptions.ConnectionError as e:
|
||||
# The flakey Launchpad API failed. Don't punish the user for that.
|
||||
mk_warning('Could not verify storyboard project %s (%s)' %
|
||||
(sb_id, e))
|
||||
else:
|
||||
if (projects_resp.status_code // 100) == 4:
|
||||
mk_warning(
|
||||
'Could not verify storyboard project, API call failed.'
|
||||
)
|
||||
for project in projects_resp.json():
|
||||
if sb_id == project.get('id'):
|
||||
break
|
||||
else:
|
||||
mk_error(
|
||||
'Did not find a storyboard project with ID %s' % sb_id
|
||||
)
|
||||
else:
|
||||
mk_error('No launchpad or storyboard project given')
|
||||
|
||||
|
||||
def validate_team(deliverable_info, team_data, mk_warning, mk_error):
|
||||
@ -689,7 +715,7 @@ def main():
|
||||
print('ERROR: {}'.format(msg))
|
||||
errors.append('{}: {}'.format(filename, msg))
|
||||
|
||||
validate_launchpad(deliverable_info, mk_warning, mk_error)
|
||||
validate_bugtracker(deliverable_info, mk_warning, mk_error)
|
||||
validate_team(deliverable_info, team_data, mk_warning, mk_error)
|
||||
validate_release_notes(deliverable_info, mk_warning, mk_error)
|
||||
validate_type(deliverable_info, mk_warning, mk_error)
|
||||
|
@ -26,12 +26,12 @@ from openstack_releases import defaults
|
||||
from openstack_releases.cmds import validate
|
||||
|
||||
|
||||
class TestValidateLaunchpad(base.BaseTestCase):
|
||||
class TestValidateBugTracker(base.BaseTestCase):
|
||||
|
||||
def test_no_launchpad_name(self):
|
||||
def test_no_tracker(self):
|
||||
warnings = []
|
||||
errors = []
|
||||
validate.validate_launchpad(
|
||||
validate.validate_bugtracker(
|
||||
{},
|
||||
warnings.append,
|
||||
errors.append,
|
||||
@ -40,11 +40,11 @@ class TestValidateLaunchpad(base.BaseTestCase):
|
||||
self.assertEqual(1, len(errors))
|
||||
|
||||
@mock.patch('requests.get')
|
||||
def test_invalid_launchpad_name(self, get):
|
||||
def test_launchpad_invalid_name(self, get):
|
||||
get.return_value = mock.Mock(status_code=404)
|
||||
warnings = []
|
||||
errors = []
|
||||
validate.validate_launchpad(
|
||||
validate.validate_bugtracker(
|
||||
{'launchpad': 'nonsense-name'},
|
||||
warnings.append,
|
||||
errors.append,
|
||||
@ -53,11 +53,11 @@ class TestValidateLaunchpad(base.BaseTestCase):
|
||||
self.assertEqual(1, len(errors))
|
||||
|
||||
@mock.patch('requests.get')
|
||||
def test_valid_launchpad_name(self, get):
|
||||
def test_launchpad_valid_name(self, get):
|
||||
get.return_value = mock.Mock(status_code=200)
|
||||
warnings = []
|
||||
errors = []
|
||||
validate.validate_launchpad(
|
||||
validate.validate_bugtracker(
|
||||
{'launchpad': 'oslo.config'},
|
||||
warnings.append,
|
||||
errors.append,
|
||||
@ -71,7 +71,7 @@ class TestValidateLaunchpad(base.BaseTestCase):
|
||||
get.side_effect = requests.exceptions.ConnectionError('testing')
|
||||
warnings = []
|
||||
errors = []
|
||||
validate.validate_launchpad(
|
||||
validate.validate_bugtracker(
|
||||
{'launchpad': 'oslo.config'},
|
||||
warnings.append,
|
||||
errors.append,
|
||||
@ -79,6 +79,79 @@ class TestValidateLaunchpad(base.BaseTestCase):
|
||||
self.assertEqual(1, len(warnings))
|
||||
self.assertEqual(0, len(errors))
|
||||
|
||||
@mock.patch('requests.get')
|
||||
def test_storyboard_valid_id(self, get):
|
||||
get.return_value = mock.Mock(status_code=200)
|
||||
get.return_value.json.return_value = [
|
||||
{
|
||||
"name": "openstack-infra/storyboard",
|
||||
"created_at": "2014-03-12T17:52:19+00:00",
|
||||
"is_active": True,
|
||||
"updated_at": None,
|
||||
"autocreate_branches": False,
|
||||
"repo_url": None,
|
||||
"id": 456,
|
||||
"description": "OpenStack Task Tracking API",
|
||||
},
|
||||
{
|
||||
"name": "openstack-infra/shade",
|
||||
"created_at": "2015-01-07T20:56:27+00:00",
|
||||
"is_active": True,
|
||||
"updated_at": None,
|
||||
"autocreate_branches": False,
|
||||
"repo_url": None,
|
||||
"id": 760,
|
||||
"description": "Client library for OpenStack...",
|
||||
}
|
||||
]
|
||||
warnings = []
|
||||
errors = []
|
||||
validate.validate_bugtracker(
|
||||
{'storyboard': '760'},
|
||||
warnings.append,
|
||||
errors.append,
|
||||
)
|
||||
self.assertEqual(0, len(warnings))
|
||||
self.assertEqual(0, len(errors))
|
||||
|
||||
@mock.patch('requests.get')
|
||||
def test_storyboard_invalid_id(self, get):
|
||||
get.return_value = mock.Mock(status_code=200)
|
||||
warnings = []
|
||||
errors = []
|
||||
validate.validate_bugtracker(
|
||||
{'storyboard': 'name-not-id'},
|
||||
warnings.append,
|
||||
errors.append,
|
||||
)
|
||||
self.assertEqual(0, len(warnings))
|
||||
self.assertEqual(1, len(errors))
|
||||
|
||||
@mock.patch('requests.get')
|
||||
def test_storyboard_no_such_project(self, get):
|
||||
get.return_value = mock.Mock(status_code=200)
|
||||
get.return_value.json.return_value = [
|
||||
{
|
||||
"name": "openstack-infra/storyboard",
|
||||
"created_at": "2014-03-12T17:52:19+00:00",
|
||||
"is_active": True,
|
||||
"updated_at": None,
|
||||
"autocreate_branches": False,
|
||||
"repo_url": None,
|
||||
"id": 456,
|
||||
"description": "OpenStack Task Tracking API",
|
||||
},
|
||||
]
|
||||
warnings = []
|
||||
errors = []
|
||||
validate.validate_bugtracker(
|
||||
{'storyboard': '-760'},
|
||||
warnings.append,
|
||||
errors.append,
|
||||
)
|
||||
self.assertEqual(0, len(warnings))
|
||||
self.assertEqual(1, len(errors))
|
||||
|
||||
|
||||
class TestValidateTeam(base.BaseTestCase):
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user