Verif-issues.py :
#####################################################
# PARAMETRES :
# $1 => Token avec droit API (role =>Reporter)
# $2 => Url git des api des projets
# $3 => Numéro d'id du projet gitlab
#
# CODE DE RETOUR :
# 0 => L'exécution est réussie
# 1 => Erreur durant l'exécution
#####################################################
 
from git import Repo
import os
import git
import sys
import re
import requests
 
class CGitlabVerifIssues:
    """
    class permettant de réaliser des vérifications 
    des issues gitlab lors de merge requête et de 
    leurs existence dans l'API gitlab.
 
    ...
 
    Attribus
    ----------
    api_key : str
        Token avec droit API (role =>Reporter).
    url_projet_api : str
        Url git des api des projets.
    id_projet : int
        Numéro d'id du projet gitlab.
    list_issues : array
        Liste des issues trouvaient dans le titre 
        de la demande de fusion.
    headers : set
        Contient l'entête de la requête avec le token 
        api utilisé lors d'une requête vers l'api gitlab.
 
    """

    def __init__(self,
                 api_key,
                 url_projet_api,
                 id_projet):
        """
        Initialisation des attributs.
 
        Parametres:
                api_key (int): Token avec droit API (role =>Reporter)
                url_projet_api (int): Url git des api des projets
                id_projet (int): Numero d'id du projet gitlab
 
        """
 
        self.api_key=api_key
        self.id_projet=id_projet
        self.list_issues=[]
        self.headers={'PRIVATE-TOKEN': self.api_key}
        self.url_projet_api=url_projet_api

 
    def Check_issue_merge(self):
        """
        Vérifie la présence au minimum d'un numéro d'issue dans le titre de la merge request.
 
        Retour:
                0 (int): L'exécution est réussi
                1 (int): Erreur durant l'exécution
        """
 
        regex = re.compile("#\\d+")
        
        url = self.url_projet_api + self.id_projet + "/merge_requests?state=opened"
        print(url)
        resp = requests.get(url,headers=self.headers)
        if (resp.status_code == requests.codes.ok):
            list_mr=resp.json()
            for mr in list_mr:
                title=mr["title"]
                self.list_issues = regex.findall(title)
                if (0 < len(self.list_issues)):
                    print(F"Merge request title : {title}")
                    return 0
                else:
                    print(F"Error : Issue not find in Title Merge Request !!!")
                    print(F"Merge request title : {title}")
                    return 1
        else:
            print(F"Error : When call url = ({url})")
            return 1
        return 0
 
    def Check_issue_exist(self):
        """
        Vérifie si toutes les issues existent bien 
        dans l'api gitlab du projet.
 
        Retour:
                0 (int): L'exécution est réussi
                1 (int): Erreur durant l'exécution
        """
        
        for issue in ( x[1:] for x in self.list_issues ):
            url = self.url_projet_api + self.id_projet + "/issues/" + issue
            print(url)
            resp = requests.get(url,headers=self.headers)
            if (resp.status_code != requests.codes.ok):
                print( F"Error : Issue N° ({issue}) not exist !!!")
                return 1
            print( F"Issue N° ({issue}) find")    
        return 0
 
VerifIssues = CGitlabVerifIssues(sys.argv[1],
                                 sys.argv[2],
                                 sys.argv[3])
ret=VerifIssues.Check_issue_merge()
if(ret == 0):
    ret=VerifIssues.Check_issue_exist()
    if(ret == 0):
        sys.exit(0)
    else:
        sys.exit(1)
else:
    sys.exit(1)

 
Create-release-note.py :
###################################################################
# PARAMETRES :
# $1 => Token avec droit API (rôle =>Reporter)
# $2 => Url git des api des projets
# $3 => Numéro d'id du projet gitlab
# $4 => Url gitlab du projet, cela permettra d’analyser les commit
# $5 => Nom de la branche à traiter
# #6 => Nom de la version qui apparaitra dans la release note
#
# CODE DE RETOUR :
# 0 => L'exécution est réussie
# 1 => Erreur durant l'exécution
###################################################################
 
from git import Repo
import os
import git
import sys
import re
import requests
 
class CGitlabReleaseNote:
    """
    class permettant de réaliser des vérifications d'issues gitlab 
    lors de merge request et de leurs existence dans l'API gitlab.
 
    ...
 
    Attribus
    ----------
    api_key : str
        Token avec droit API (role =>Reporter).
    url_projet_api : str
        Url git des api des projets.
    id_projet : int
        Numero d'id du projet gitlab.
    repo : git.Repo
        Represante une copie du repositories du projets git
    log : git.refs.log.RefLog
        Contient les logs des commits lié au repo.
    list_issues : array
        Liste des issues trouvaient dans le titre des merges request.
    release_name : str
        Nom de la version qui apparaitra dans la release note
    """
    
    def __init__(self,
                 api_key,
                 url_projet_api,
                 id_projet,
                 url,
                 branch_name,
                 release_name):
        """
        Initialisation des attributs.
 
        Paramètres :
                api_key (int): Token avec droit API (role =>Reporter)
                url_projet_api (int): Url git des api des projets
                id_projet (int): Numero d'id du projet gitlab
                url (str): Url gitlab du projet, cela permettra d’analyser les commit
                branch_name (str): Nom de la branche à traiter
                release_name (str): Nom de la version qui apparaitra dans la release note
        """
 
        self.repo = git.Repo.clone_from(url, os.path.join("test", 
                                                          "/home/devops/test"), 
                                                          branch=branch_name)
        self.log = eval("self.repo.heads.%s.log()" %(branch_name))
        self.list_issues=[]
        self.api_key=api_key
        self.release_name=release_name
        self.id_projet=id_projet
        self.url_projet_api=url_projet_api
 
    def __print_commit(self,commit):
        print('----')
        print(str(commit.hexsha))
        print("\"{}\" by {} ({})".format(commit.summary,
                                         commit.message,
                                         commit.author.name,
                                         commit.author.email))
        print(str(commit.authored_datetime))
        print(str("count: {} and size: {}".format(commit.count(),
                                                  commit.size)))
 
    def Recovery_commits_issue(self):
        """
        Récupère tous les commit de merge en interrogant l'API Gitlab
        et un créer un tableau contenant pour chaque issue (id,label,titre).
 
            Retour:
                    0 (int): L'exécution est réussi
                    1 (int): Erreur durant l'exécution
        """
        
        l_commits_issue=[]
        last_commit_number=self.log[-1].newhexsha[0:8]
        regex = re.compile("#\\d+")
        commits = list(self.repo.iter_commits(last_commit_number + 
                                              '^1..' + last_commit_number + 
                                              '^2'))
        for commit in commits:
            self.__print_commit(commit)
            resultats = regex.findall(commit.message)
            l_commits_issue += [ resultat[1:] for resultat in resultats ]
        print("List commit with issues number : "+ ", ".join(l_commits_issue))
        headers={'PRIVATE-TOKEN': self.api_key}
        for issue in l_commits_issue:
            url = self.url_projet_api + self.id_projet + "/issues/" + issue
            print(url)
            resp = requests.get(url,headers=headers)
            if (resp.status_code == requests.codes.ok):
                l_resp = resp.json()
                iid=l_resp["iid"]
                title=l_resp["title"]
                for label in l_resp["labels"]:
                    if "release" in label.lower() :
     label_release= label.replace('Release::','').replace('release::','')
                    break
                if (label_release != ''):
                    self.list_issues.append("%s:%s:%s" %( iid, 
                                                          label_release, 
                                                          title))
                else:
                    print( F"Error : Not label find in issue ({iid})")
                    return 1
            else:
                print( F"Error : Issue not found ({iid})")
                print( F"Status code : ({resp.status_code})")
                return 1
        print(self.list_issues)
        return 0
     
    def Create_release_note(self):
        """
        Créer un fichier Release-note.txt contenant par label toutes
        les issues associés.
 
        Retour:
                0 (int): L'exécution est réussi
                1 (int): Erreur durant l'exécution
        """
 
        l_labels_release=['Added',
                          'Changed',
                          'Fixed',
                          'Removed',
                          'Deprecated',
                          'Security']
        size_release_name=len("Release Name : "+ self.release_name)
 
        with open("Release-note.txt", "a") as fichier:
            print(  "#" * (30+size_release_name), file=fichier)
            print(  "#",
                    " " * 14,
                    "Release Name : ",
                    self.release_name,
                    " " * 14,
                    "#",
                    sep='',
                    file=fichier)
            print( "#" * (30+size_release_name), end="\n\n", file=fichier)
            print( "Description of delivery :", end="\n\n", file=fichier)
 
            issues = set( issue.split(':')[1] for issue in self.list_issues )
            for label_release in l_labels_release:
                if label_release in issues:
                    print( F"[{label_release}] :", file=fichier)
                    for issue in self.list_issues:
                        x, y, z=issue.split(':')
                        if(y == label_release):
                            print( F"\t{x}: {z}", file=fichier )
                            
        with open("Release-note.txt", "r") as fichier:
            print(fichier.read())
        return 0
 
ReleaseNote = CGitlabReleaseNote(sys.argv[1],
                                 sys.argv[2],
                                 sys.argv[3],
                                 sys.argv[4],
                                 sys.argv[5],
                                 sys.argv[6])
ret=ReleaseNote.Recovery_commits_issue()
if(ret == 0):
    ret=ReleaseNote.Create_release_note()
    if(ret == 0):
        sys.exit(0)
    else:
        sys.exit(1)
else:
    sys.exit(1)