From 5d11ace6d1f44b10137f34df0004054ebc019c0c Mon Sep 17 00:00:00 2001
From: Tiago Freitas Pereira <tiagofrepereira@gmail.com>
Date: Mon, 21 Oct 2019 18:02:44 +0200
Subject: [PATCH] Created 2 commands to process gitlab logs

---
 bob/devtools/pipelines.py         |  50 ++++++++++++
 bob/devtools/scripts/pipelines.py | 130 ++++++++++++++++++++++++++++++
 conda/meta.yaml                   |   3 +
 setup.py                          |   2 +
 4 files changed, 185 insertions(+)
 create mode 100644 bob/devtools/pipelines.py
 create mode 100644 bob/devtools/scripts/pipelines.py

diff --git a/bob/devtools/pipelines.py b/bob/devtools/pipelines.py
new file mode 100644
index 00000000..29ecf8b5
--- /dev/null
+++ b/bob/devtools/pipelines.py
@@ -0,0 +1,50 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+"""Pipeline utilities"""
+
+from tabulate import tabulate
+import re
+from datetime import datetime
+
+
+def process_log(log):
+    """
+    Summarizes the execution time of a pipeline given its Job log
+    """
+
+    current_package = None
+    logs = dict()
+    dates = []
+    for l in log:
+
+        # Check which package are we
+        if len(re.findall("Building bob/[a-z]*", l)) > 0:
+            logs[current_package] = dates
+            dates = []
+
+            pattern = re.findall("Building bob/[a-z]*", l)[0]
+            current_package = l[9:-1]
+            continue
+
+        # Checking the date
+        date = re.findall(
+            "[0-9]{4,4}-[0-9]{2,2}-[0-9]{2,2} [0-9]{2,2}:[0-9]{2,2}:[0-9]{2,2}", l
+        )
+        if len(date) > 0:
+            # logs[date[0]]=current_package
+            dates.append(date[0])
+
+    ## Last log
+    if len(dates) > 0:
+        logs[current_package] = dates
+
+    table = []
+    for k in logs:
+        first = datetime.strptime(logs[k][0], "%Y-%m-%d %H:%M:%S")
+        last = datetime.strptime(logs[k][-1], "%Y-%m-%d %H:%M:%S")
+        delta = ((last - first).seconds) / 60
+
+        table.append([str(k), str(first), str(round(delta, 2)) + "m"])
+
+    print(tabulate(table))
diff --git a/bob/devtools/scripts/pipelines.py b/bob/devtools/scripts/pipelines.py
new file mode 100644
index 00000000..7d21bc06
--- /dev/null
+++ b/bob/devtools/scripts/pipelines.py
@@ -0,0 +1,130 @@
+#!/usr/bin/env python
+
+import os
+
+import click
+import gitlab
+import urllib
+
+from . import bdt
+from ..release import get_gitlab_instance
+
+from ..log import verbosity_option, get_logger, echo_normal, echo_warning
+from ..pipelines import process_log
+logger = get_logger(__name__)
+from tabulate import tabulate
+
+@click.command(
+    epilog="""
+Examples:
+
+  1. Process all the jobs from a particular pipeline
+
+     $ bdt gitlab process-pipelines bob/bob.nightlies pipelines
+
+  2. Process a particular job from a pipeline
+
+     $ bdt gitlab process-pipelines bob/bob.nightlies pipelines --job-id xxx
+
+"""
+)
+@click.argument("package")
+@click.argument("pipeline")
+@click.option('--job-id', default=None, help='A job id from a pipeline')
+@verbosity_option()
+@bdt.raise_on_error
+def process_pipelines(package, pipeline, job_id):
+    """Returns the last tag information on a given PACKAGE."""
+
+    if "/" not in package:
+        raise RuntimeError('PACKAGE should be specified as "group/name"')
+
+    gl = get_gitlab_instance()
+
+    # we lookup the gitlab package once
+    try:
+        project = gl.projects.get(package)
+        pipeline = project.pipelines.get(pipeline)
+
+        jobs = [j for j in pipeline.jobs.list()]        
+        if job_id is not None:
+            jobs = [j for j in jobs if int(j.attributes["id"])==int(job_id)]
+
+
+        if(len(jobs) == 0 ):
+            print("Job %s not found in the pipeline %s. Use `bdt gitlab get-pipelines` to search " % (job_id, pipeline.attributes["id"]))
+                         
+        # Reading log
+        try:
+            for j in jobs:
+                print("Pipeline %s, Job %s" % (pipeline.attributes["id"], int(j.attributes["id"])))
+                web_url = j.attributes["web_url"] + "/raw"                
+                log = str(urllib.request.urlopen(web_url).read()).split("\\n")
+                process_log(log)
+        except urllib.error.HTTPError as e:
+            logger.warn(
+                "Gitlab access error - Log %s can't be found" % web_url, package
+            )
+            echo_warning("%s: unknown" % (package,))
+
+        logger.info(
+            "Found gitlab project %s (id=%d)",
+            project.attributes["path_with_namespace"],
+            project.id,
+        )
+
+        pass
+    except gitlab.GitlabGetError as e:
+        logger.warn("Gitlab access error - package %s does not exist?", package)
+        echo_warning("%s: unknown" % (package,))
+
+
+@click.command(
+    epilog="""
+Examples:
+
+  1. Get the most recent pipelines from a particular project wit their corresponding job numbers
+
+     $ bdt gitlab get-pipelines bob/bob.nightlies
+
+
+"""
+)
+@click.argument("package")
+@verbosity_option()
+@bdt.raise_on_error
+def get_pipelines(package):
+    """Returns the CI pipelines given a given PACKAGE."""
+
+    if "/" not in package:
+        raise RuntimeError('PACKAGE should be specified as "group/name"')
+
+    gl = get_gitlab_instance()
+
+    # we lookup the gitlab package once
+    try:
+        project = gl.projects.get(package)
+        logger.info(
+            "Found gitlab project %s (id=%d)",
+            project.attributes["path_with_namespace"],
+            project.id,
+        )
+
+        pipelines = project.pipelines.list()
+        description = [["Pipeline", "Branch", "Status", "Jobs"]]
+        for pipeline in pipelines:
+            jobs = [j.attributes["id"] for j in pipeline.jobs.list()]
+            description.append(
+                [
+                    "%s" % pipeline.attributes["id"],
+                    "%s" % pipeline.attributes["ref"],
+                    "%s" % pipeline.attributes["status"],
+                    "%s" % jobs,
+                ]
+            )
+        print("Jobs from project %s" % package)
+        print(tabulate(description))
+
+    except gitlab.GitlabGetError as e:
+        logger.warn("Gitlab access error - package %s does not exist?", package)
+        echo_warning("%s: unknown" % (package,))
diff --git a/conda/meta.yaml b/conda/meta.yaml
index 71775eec..df6141cd 100644
--- a/conda/meta.yaml
+++ b/conda/meta.yaml
@@ -48,6 +48,7 @@ requirements:
     - jinja2
     - termcolor
     - psutil
+    - tabulate
 
 test:
   requires:
@@ -101,6 +102,8 @@ test:
     - bdt dav rmtree --help
     - bdt dav clean-betas --help
     - bdt dav upload --help
+    - bdt gitlab process-pipelines --help
+    - bdt gitlab get-pipelines --help    
     - sphinx-build -aEW ${PREFIX}/share/doc/{{ name }}/doc sphinx
     - if [ -n "${CI_PROJECT_DIR}" ]; then mv sphinx "${CI_PROJECT_DIR}/"; fi
 
diff --git a/setup.py b/setup.py
index ab67bfde..1e729138 100644
--- a/setup.py
+++ b/setup.py
@@ -67,6 +67,8 @@ setup(
           'jobs = bob.devtools.scripts.jobs:jobs',
           'visibility = bob.devtools.scripts.visibility:visibility',
           'getpath = bob.devtools.scripts.getpath:getpath',
+          'process-pipelines = bob.devtools.scripts.pipelines:process_pipelines',
+          'get-pipelines- = bob.devtools.scripts.pipelines:get_pipelines',          
           ],
 
         'bdt.ci.cli': [
-- 
GitLab