From f9a23edb815a7c132644af342d5ceb46d815909e Mon Sep 17 00:00:00 2001 From: jlrifer <31681347+jlrifer@users.noreply.github.com> Date: Thu, 26 Apr 2018 21:54:33 -0500 Subject: [PATCH] Add community activity --- api/pages/code/activity.py | 399 +++++++++++++++++++++++++++++++++++++ api/yaml/openapi.yaml | 42 ++++ api/yaml/widgets.yaml | 12 +- 3 files changed, 452 insertions(+), 1 deletion(-) create mode 100644 api/pages/code/activity.py diff --git a/api/pages/code/activity.py b/api/pages/code/activity.py new file mode 100644 index 00000000..4752da4b --- /dev/null +++ b/api/pages/code/activity.py @@ -0,0 +1,399 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +######################################################################## +# OPENAPI-URI: /api/code/activity +######################################################################## +# get: +# responses: +# '200': +# content: +# application/json: +# schema: +# $ref: '#/components/schemas/Factor' +# description: 200 Response +# default: +# content: +# application/json: +# schema: +# $ref: '#/components/schemas/Error' +# description: unexpected error +# security: +# - cookieAuth: [] +# summary: Shows community activity data for a set of repos over a given period of time +# post: +# requestBody: +# content: +# application/json: +# schema: +# $ref: '#/components/schemas/defaultWidgetArgs' +# responses: +# '200': +# content: +# application/json: +# schema: +# $ref: '#/components/schemas/Factor' +# description: 200 Response +# default: +# content: +# application/json: +# schema: +# $ref: '#/components/schemas/Error' +# description: unexpected error +# security: +# - cookieAuth: [] +# summary: Shows community activity data for a set of repos over a given period of time +# +######################################################################## + + + + + +""" +This is the community activity renderer for Kibble +""" + +import json +import time +import re + +def run(API, environ, indata, session): + + # We need to be logged in for this! + if not session.user: + raise API.exception(403, "You must be logged in to use this API endpoint! %s") + + now = time.time() + + # First, fetch the view if we have such a thing enabled + viewList = [] + if indata.get('view'): + viewList = session.getView(indata.get('view')) + if indata.get('subfilter'): + viewList = session.subFilter(indata.get('subfilter'), view = viewList) + + + dateTo = indata.get('to', int(time.time())) + dateFrom = indata.get('from', dateTo - (86400*30*6)) # Default to a 6 month span + if dateFrom < 0: + dateFrom = 0 + dateYonder = dateFrom - (dateTo - dateFrom) + + + #################################################################### + # COMMITS # + #################################################################### + dOrg = session.user['defaultOrganisation'] or "apache" + query = { + 'query': { + 'bool': { + 'must': [ + {'range': + { + 'tsday': { + 'from': dateFrom, + 'to': dateTo + } + } + }, + { + 'term': { + 'organisation': dOrg + } + } + ] + } + } + } + # Source-specific or view-specific?? + if indata.get('source'): + query['query']['bool']['must'].append({'term': {'sourceID': indata.get('source')}}) + elif viewList: + query['query']['bool']['must'].append({'terms': {'sourceID': viewList}}) + if indata.get('email'): + query['query']['bool']['should'] = [{'term': {'committer_email': indata.get('email')}}, {'term': {'author_email': indata.get('email')}}] + query['query']['bool']['minimum_should_match'] = 1 + + # Get number of commits, this period + res = session.DB.ES.count( + index=session.DB.dbname, + doc_type="code_commit", + body = query + ) + no_commits = res['count'] + + + + #################################################################### + # ISSUES OPENED # + #################################################################### + query = { + 'query': { + 'bool': { + 'must': [ + {'range': + { + 'created': { + 'from': dateFrom, + 'to': dateTo + } + } + }, + { + 'term': { + 'organisation': dOrg + } + } + ] + } + } + } + # Source-specific or view-specific?? + if indata.get('source'): + query['query']['bool']['must'].append({'term': {'sourceID': indata.get('source')}}) + elif viewList: + query['query']['bool']['must'].append({'terms': {'sourceID': viewList}}) + if indata.get('email'): + query['query']['bool']['should'] = [{'term': {'issueCreator': indata.get('email')}}, {'term': {'issueCloser': indata.get('email')}}] + query['query']['bool']['minimum_should_match'] = 1 + + # Get number of issues created, this period + res = session.DB.ES.count( + index=session.DB.dbname, + doc_type="issue", + body = query + ) + no_issues_created = res['count'] + + + #################################################################### + # COMMENTS # + #################################################################### + dOrg = session.user['defaultOrganisation'] or "apache" + query = { + 'query': { + 'bool': { + 'must': [ + {'range': + { + 'created': { + 'from': dateFrom, + 'to': dateTo + } + } + }, + { + 'term': { + 'organisation': dOrg + } + } + ] + } + }, + 'sort': { + 'comments': 'desc' + } + } + # Source-specific or view-specific?? + if indata.get('source'): + query['query']['bool']['must'].append({'term': {'sourceID': indata.get('source')}}) + elif viewList: + query['query']['bool']['must'].append({'terms': {'sourceID': viewList}}) + if indata.get('email'): + query['query']['bool']['should'] = [{'term': {'issueCreator': indata.get('email')}}, {'term': {'issueCloser': indata.get('email')}}] + query['query']['bool']['minimum_should_match'] = 1 + + res = session.DB.ES.search( + index=session.DB.dbname, + doc_type="issue", + size = 25, + body = query + ) + + no_comments = 0; + for bucket in res['hits']['hits']: + doc = bucket['_source'] + doc['count'] = doc.get('comments', 0) + no_comments += doc['count'] + + + + #################################################################### + # Change to PRIOR SPAN # + #################################################################### + dOrg = session.user['defaultOrganisation'] or "apache" + query = { + 'query': { + 'bool': { + 'must': [ + {'range': + { + 'tsday': { + 'from': dateYonder, + 'to': dateFrom-1 + } + } + }, + { + 'term': { + 'organisation': dOrg + } + } + ] + } + } + } + # Source-specific or view-specific?? + if indata.get('source'): + query['query']['bool']['must'].append({'term': {'sourceID': indata.get('source')}}) + elif viewList: + query['query']['bool']['must'].append({'terms': {'sourceID': viewList}}) + if indata.get('email'): + query['query']['bool']['should'] = [{'term': {'committer_email': indata.get('email')}}, {'term': {'author_email': indata.get('email')}}] + query['query']['bool']['minimum_should_match'] = 1 + + # Get number of commits, this period + res = session.DB.ES.count( + index=session.DB.dbname, + doc_type="code_commit", + body = query + ) + no_commits_b = res['count'] + + + #################################################################### + #################################################################### + query = { + 'query': { + 'bool': { + 'must': [ + {'range': + { + 'created': { + 'from': dateYonder, + 'to': dateFrom-1 + } + } + }, + { + 'term': { + 'organisation': dOrg + } + } + ] + } + } + } + # Source-specific or view-specific?? + if indata.get('source'): + query['query']['bool']['must'].append({'term': {'sourceID': indata.get('source')}}) + elif viewList: + query['query']['bool']['must'].append({'terms': {'sourceID': viewList}}) + if indata.get('email'): + query['query']['bool']['should'] = [{'term': {'issueCreator': indata.get('email')}}, {'term': {'issueCloser': indata.get('email')}}] + query['query']['bool']['minimum_should_match'] = 1 + + # Get number of issues created, this period + res = session.DB.ES.count( + index=session.DB.dbname, + doc_type="issue", + body = query + ) + no_issues_created_b = res['count'] + + + #################################################################### + #################################################################### + dOrg = session.user['defaultOrganisation'] or "apache" + query = { + 'query': { + 'bool': { + 'must': [ + {'range': + { + 'created': { + 'from': dateYonder, + 'to': dateFrom-1 + } + } + }, + { + 'term': { + 'organisation': dOrg + } + } + ] + } + }, + 'sort': { + 'comments': 'desc' + } + } + # Source-specific or view-specific?? + if indata.get('source'): + query['query']['bool']['must'].append({'term': {'sourceID': indata.get('source')}}) + elif viewList: + query['query']['bool']['must'].append({'terms': {'sourceID': viewList}}) + if indata.get('email'): + query['query']['bool']['should'] = [{'term': {'issueCreator': indata.get('email')}}, {'term': {'issueCloser': indata.get('email')}}] + query['query']['bool']['minimum_should_match'] = 1 + + res = session.DB.ES.search( + index=session.DB.dbname, + doc_type="issue", + size = 25, + body = query + ) + + no_comments_b = 0; + for bucket in res['hits']['hits']: + doc = bucket['_source'] + doc['count'] = doc.get('comments', 0) + no_comments_b += doc['count'] + + + + total = no_commits + no_issues_created + no_comments + total_b = no_commits_b + no_issues_created_b + no_comments_b + + JSON_OUT = { + 'factors': [ + { + 'title': "Commits", + 'count': no_commits, + 'previous': no_commits_b + }, + { + 'title': "Issues", + 'count': no_issues_created, + 'previous': no_issues_created_b + }, + { + 'title': "Comments", + 'count': no_comments, + 'previous': no_comments_b + }, + { + 'title': "Total Activity", + 'count': total, + 'previous': total_b + } + ], + 'okay': True, + 'responseTime': time.time() - now, + } + yield json.dumps(JSON_OUT) diff --git a/api/yaml/openapi.yaml b/api/yaml/openapi.yaml index 03f0e4c2..d4ef3fd5 100644 --- a/api/yaml/openapi.yaml +++ b/api/yaml/openapi.yaml @@ -905,6 +905,48 @@ paths: security: - cookieAuth: [] summary: Shows top 25 jobs by total build time spent + /api/code/activity: + get: + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/Factor' + description: 200 Response + default: + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + description: unexpected error + security: + - cookieAuth: [] + summary: Shows community activity data for a set of repos over a given period + of time + post: + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/defaultWidgetArgs' + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/Factor' + description: 200 Response + default: + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + description: unexpected error + security: + - cookieAuth: [] + summary: Shows community activity data for a set of repos over a given period + of time /api/code/changes: get: responses: diff --git a/api/yaml/widgets.yaml b/api/yaml/widgets.yaml index 542ac061..40e146fe 100644 --- a/api/yaml/widgets.yaml +++ b/api/yaml/widgets.yaml @@ -263,13 +263,23 @@ widgets: source: code/top-commits name: "Top repos by commits" target: "" + - + name: "Factors" + children: - type: factors datatype: repo - blocks: 4 + blocks: 6 source: code/pony name: "Pony Factors" target: "" + - + type: factors + datatype: repo + blocks: 6 + source: code/activity + name: "Community Activty" + target: "" ### ISSUE TRACKERS issues: