-
Notifications
You must be signed in to change notification settings - Fork 0
Dev/70/alex get feature info #84
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
Changes from all commits
6046a85
778c8ed
baa5c9f
0b6b0c1
39c93d2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,8 @@ | ||
| import github3 | ||
| import datetime | ||
| import iso8601 | ||
| import re | ||
|
|
||
| import github3 | ||
| from zope import interface | ||
|
|
||
| from deploystream.providers.interfaces import IPlanningProvider | ||
|
|
@@ -70,33 +73,42 @@ def get_features(self, **filters): | |
| repository.name) | ||
| if repository.has_issues: | ||
| for issue in repository.iter_issues(**filters): | ||
| issue_info = transforms.remap(issue.__dict__, FEATURE_MAP) | ||
| if issue.pull_request: | ||
| issue_type = 'PR' | ||
| else: | ||
| issue_type = 'story' | ||
| issue_info['type'] = issue_type | ||
| issue_info['project'] = project | ||
| owner = issue_info['assignee'] | ||
| if owner is None: | ||
| issue_info['owner'] = '' | ||
| else: | ||
| # take only login name from User object | ||
| issue_info['owner'] = owner.login | ||
| issue_info = self._convert_to_dict(issue, project) | ||
| features.append(issue_info) | ||
|
|
||
| # sort by putting PRs first, stories second | ||
| features = sorted(features, key=lambda f: f['type'] == 'story') | ||
|
|
||
| return features | ||
|
|
||
| def _convert_to_dict(self, issue, project): | ||
| issue_info = transforms.remap(issue.__dict__, FEATURE_MAP) | ||
| if issue.pull_request: | ||
| issue_type = 'PR' | ||
| else: | ||
| issue_type = 'story' | ||
| issue_info['type'] = issue_type | ||
| issue_info['project'] = project | ||
| owner = issue_info['assignee'] | ||
| if owner is None: | ||
| issue_info['owner'] = '' | ||
| else: | ||
| # take only login name from User object | ||
| issue_info['owner'] = owner.login | ||
| return issue_info | ||
|
|
||
| def get_feature_info(self, feature_id): | ||
| # Feature ID will need to have org in it. | ||
| # For now we'll do a really crude search through the get_features | ||
| # results | ||
| for feat in self.get_features(): | ||
| if str(feat['id']) == str(feature_id): | ||
| return feat | ||
| # Issue with this approach is that we return the first issue with an | ||
| # ID across all repos. | ||
| # Such are the shortcomings of using Git as a planning provider. To | ||
| # get round this we'd need to have the repo in the feature_id, but this | ||
| # seems a bad idea from the POV of matching branch names. | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yup this is a hairy issue. We may want to think of a decent solution to that. |
||
| for repository in self.repositories: | ||
| project = '{0}/{1}'.format(repository.owner.login, | ||
| repository.name) | ||
| issue = repository.issue(feature_id) | ||
| if issue: | ||
| return self._convert_to_dict(issue, project) | ||
|
|
||
| @classmethod | ||
| def get_oauth_data(self): | ||
|
|
@@ -135,6 +147,7 @@ def get_repo_branches_involved(self, feature_id, hierarchy_regexes): | |
|
|
||
| """ | ||
| branch_list = [] | ||
| two_months_ago = datetime.datetime.now() - datetime.timedelta(60) | ||
|
|
||
| for repo in self.repositories: | ||
| repo_branches = {} | ||
|
|
@@ -157,9 +170,16 @@ def get_repo_branches_involved(self, feature_id, hierarchy_regexes): | |
| # we haven't already done so and store them in the | ||
| # temporary ``repo_branches`` dict | ||
| if repo_branches[sha].get('commits') is None: | ||
| repo_branches[sha]['commits'] = [ | ||
| c.sha for c in repo.iter_commits(sha=sha) | ||
| ] | ||
| c_list = [] | ||
| for commit in repo.iter_commits(sha=sha): | ||
| commit_date = commit.commit.committer['date'] | ||
| commit_date_time = iso8601.parse_date( | ||
| commit_date) | ||
| if (commit_date_time.replace(tzinfo=None) < | ||
| two_months_ago): | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For now I'm using this to stop going back to the beginning of time for every branch that matches the feature id. Sooner rather than later we're going to need a chat about switching the architecture to being pre-fetched. Are you free at all this week?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the best local caching for repos is going to be local clones as in storyboard, which will make all these more efficient. Give this a read and see possible solutions, I am thinking deploy keys but there are other options: https://help.github.com/articles/managing-deploy-keys One can create deploy keys via the API: http://developer.github.com/v3/repos/keys/
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We'll revisit this in the next round of changes following the hangout I guess. I'm going to set up some planning tool - I think we could do with some stories & tasks to get this going. |
||
| break | ||
| c_list.append(commit.sha) | ||
| repo_branches[sha]['commits'] = c_list | ||
| # Check if we're merged in | ||
| parent_data = repo_branches[parent] | ||
| has_parent = parent_data['sha'] in branch_data['commits'] | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is something still nagging me with this approach.
When getting feature info from a provider this way, it will make it more difficult to correlate and aggregate data from various sources (e.g. planning info in sprintly, open PRs in github, branches in github/git, jobs in Jenkins...). An alternative approach is passing a
Featureobject (or a dict if you prefer) around to the various providers in sequence (starting with the planning provider) so that each decorates the feature with additional data it knows about.For example, I would like to get initial feature info from sprintly, then pass this to the github provider so that it adds information about open PRs and relevant branches (and even mergeability status and build success from the PR), then to Jenkins so that it can add information about known builds to the feature's branches...
Up for hangout discussion.