Un programme Python qui vérifie si un contenu a été mis à jour et git valide et pousse vers GitLab s'il a été mis à jour.

Que faire dans cet article

--Chaquez du contenu textuel au fil du temps pour voir s'il a été mis à jour par rapport à la dernière fois.

Page de référence (merci)

GitLab Docs > API Docs > API resources

environnement

Ubuntu 20.04


$ python3 --version
Python 3.8.2

Présentation de GitLab et création d'un projet

Présentation de GitLab

Maintenant, commençons. Utilisez le GitLab sur site comme serveur git. Cette fois, nous l'introduirons rapidement localement avec Docker. Après avoir déplacé vers un répertoire approprié sur le terminal, exécutez ce qui suit.


git clone https://github.com/sameersbn/docker-gitlab

cd docker-gitlab

docker-compose up -d

Quand j'ai attendu un moment après avoir lancé le conteneur et exécuté "docker-compose ps", ce qui suit était affiché.


           Name                         Command                  State                               Ports                        
----------------------------------------------------------------------------------------------------------------------------------
docker-gitlab_gitlab_1       /sbin/entrypoint.sh app:start    Up (healthy)   0.0.0.0:10022->22/tcp, 443/tcp, 0.0.0.0:10080->80/tcp
docker-gitlab_postgresql_1   /sbin/entrypoint.sh              Up             5432/tcp                                             
docker-gitlab_redis_1        docker-entrypoint.sh --log ...   Up             6379/tcp            

Le port http du conteneur GitLab est 10080, accédez donc à http: // localhost: 10080 / avec votre navigateur. Lorsque l'écran ci-dessous apparaît, modifiez le mot de passe root.

スクリーンショット 2019-09-03 15.46.59.png

Allez à l'écran ci-dessous et créez un utilisateur de développement (le nom d'utilisateur peut être n'importe quoi).

スクリーンショット 2019-09-03 15.56.31.png

Créer un projet GitLab

Après vous être connecté en tant qu'utilisateur de développement, sélectionnez Créer un projet dans l'écran ci-dessous.

2020-08-17-01.png

Le nom du projet est "ethercalc_backup" comme indiqué ci-dessous, mais le nom peut être n'importe quoi. Appuyez sur le bouton Créer un projet pour créer un projet.

2020-08-17-02.png

Le projet a été créé comme suit. L'ID de projet est affiché sous le nom du projet (3 dans cet article). Vous utiliserez cet ID plus tard dans votre code Python.

2020-08-17-03.png

Obtenez un jeton d'accès pour l'API GitLab

Vous utiliserez plus tard l'API GitLab à partir de votre code Python. À ce moment-là, vous aurez besoin d'un jeton d'accès, alors obtenez-le. Comme indiqué ci-dessous, affichez le menu déroulant en haut à droite du navigateur et sélectionnez "Paramètres".

2020-08-17-10.png

Sur l'écran ci-dessous, sélectionnez «Jetons d'accès» dans le menu de gauche.

2020-08-17-11.png

Sur l'écran ci-dessous, entrez un nom arbitraire dans Nom, Scopes vérifiera l'API, et appuyez sur le bouton "Créer un jeton d'accès personnel".

2020-08-17-12.png

Le jeton d'accès a été créé comme suit. Copiez-le dans le presse-papiers et enregistrez-le. Dans cet article, nous utiliserons "6f8YXyrZ1SCSADHTJ2L9" comme jeton d'accès.

2020-08-17-13.png

Introduction d'EtherCalc

En tant que fournisseur de contenu textuel, nous utiliserons EtherCalc pour cet article. Comme avec GitLab, déployez-le localement avec Docker. Après avoir déplacé vers un répertoire approprié différent de GitLab sur le terminal, créez docker-compose.yml avec le même contenu que https://github.com/audreyt/ethercalc/blob/master/docker-compose.yml et créez un conteneur. Commencez.


wget https://raw.githubusercontent.com/audreyt/ethercalc/master/docker-compose.yml

docker-compose up -d

Quand j'ai attendu un moment après avoir lancé le conteneur et exécuté "docker-compose ps", ce qui suit était affiché.


            Name                          Command               State          Ports        
--------------------------------------------------------------------------------------------
docker-ethercalc_ethercalc_1   sh -c REDIS_HOST=$REDIS_PO ...   Up      0.0.0.0:80->8000/tcp
docker-ethercalc_redis_1       docker-entrypoint.sh redis ...   Up      6379/tcp         

Comme le port http du conteneur EtherCalc est 80, essayez d'accéder à http: // localhost / avec un navigateur.

2020-08-17-04.png

Faites deux feuilles EtherCalc pour les tests. Lancez un éditeur de texte, créez de nouveaux foo.sc et bar.sc et enregistrez.


editor foo.sc

foo.sc



socialcalc:version:1.0
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary=SocialCalcSpreadsheetControlSave
--SocialCalcSpreadsheetControlSave
Content-type: text/plain; charset=UTF-8

# SocialCalc Spreadsheet Control Save
version:1.0
part:sheet
part:edit
part:audit
--SocialCalcSpreadsheetControlSave
Content-type: text/plain; charset=UTF-8

version:1.5
cell:A1:t:foo1
cell:A2:t:foo2
sheet:c:1:r:2:tvf:1
valueformat:1:text-wiki
--SocialCalcSpreadsheetControlSave
Content-type: text/plain; charset=UTF-8

version:1.0
rowpane:0:1:1
colpane:0:1:1
ecell:A1
--SocialCalcSpreadsheetControlSave
Content-type: text/plain; charset=UTF-8

--SocialCalcSpreadsheetControlSave--

editor bar.sc

bar.sc



socialcalc:version:1.0
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary=SocialCalcSpreadsheetControlSave
--SocialCalcSpreadsheetControlSave
Content-type: text/plain; charset=UTF-8

# SocialCalc Spreadsheet Control Save
version:1.0
part:sheet
part:edit
part:audit
--SocialCalcSpreadsheetControlSave
Content-type: text/plain; charset=UTF-8

version:1.5
cell:A1:t:bar1
cell:A2:t:bar2
sheet:c:1:r:2:tvf:1
valueformat:1:text-wiki
--SocialCalcSpreadsheetControlSave
Content-type: text/plain; charset=UTF-8

version:1.0
rowpane:0:1:1
colpane:0:1:1
ecell:A1
--SocialCalcSpreadsheetControlSave
Content-type: text/plain; charset=UTF-8

--SocialCalcSpreadsheetControlSave--

Les fichiers foo.sc et bar.sc ci-dessus sont des fichiers texte au format SocialCalc qui peuvent être importés dans EtherCalc. L'exportation / importation au format SocialCalc présente l'avantage que le format de feuille (apparence) peut également être récupéré. Vous pouvez également importer des fichiers au format CSV, mais vous ne pouvez pas récupérer le format de feuille.

Procédez comme suit pour importer.


curl -X PUT -H 'Content-Type: text/x-socialcalc' --data-binary @foo.sc http://localhost/_/foo

curl -X PUT -H 'Content-Type: text/x-socialcalc' --data-binary @bar.sc http://localhost/_/bar

Accédez à http: // localhost / foo et http: // localhost / bar dans votre navigateur. Si la cellule de la feuille contient les données suivantes, l'importation est réussie.

2020-08-17-05.png

2020-08-17-06.png

Nous téléchargerons les fichiers aux formats SocialCalc et CSV à partir de ces URL et les gérerons dans GitLab.

Code Python

Veuillez me pardonner pour le code étant divers et mal comporté.

La procédure de traitement logique est la suivante. Pour chacun des contenus de foo et bar

--Téléchargez des fichiers depuis EtherCalc et GitLab (formats SocialCalc et csv) --Si le fichier n'existe pas dans GitLab, ajoutez-en un nouveau au référentiel git.

Voici le code Python. Le code utilise une variable appelée logger, mais veuillez noter que le code autour de la journalisation a été omis.

ethercalc_backup.py



import time
import datetime
import urllib.request
import urllib.parse
import json
import pprint
import re
import base64

#URL du contenu ethercalc géré par git
ethercalc_uris = [ "http://localhost/foo", "http://localhost/bar" ]

#Liés à GitLab
gitlab_base_uri = "http://localhost:10080/"

#Destination de sauvegarde dans le référentiel git
gitlab_backup_directory = "ethercalc"

gitlab_private_token = "6f8YXyrZ1SCSADHTJ2L9"
gitlab_project_id = 3

#maintenant
str_now = datetime.datetime.today().strftime("%Y%m%d_%H%M%S")

#nouvelle ligne
LF = '\n'


def get_gitlab_file(private_token, file_path):
    """
Obtenez 1 fichier du référentiel GitLab

    Parameters
    ----------
    private_token : str
Jeton d'accès pour l'API GitLab

    file_path : str
Chemin du fichier depuis le haut du référentiel git

    Returns
    -------
    anonymous : json
Réponse de GitLab
    """

    # https://docs.gitlab.com/ee/api/repository_files.html
    gitlab_uri = f"{gitlab_base_uri}api/v4/projects/{gitlab_project_id}/repository/files/{urllib.parse.quote(file_path, safe='')}?ref=master"
    logger.info(f"gitlab_uri={gitlab_uri}")
    headers = {
        "PRIVATE-TOKEN": private_token
    }
    request = urllib.request.Request(gitlab_uri, headers=headers)
    try:
        with urllib.request.urlopen(request) as res:
            res_files = json.loads(res.read())
    except urllib.error.HTTPError as ee:
        if ee.code == 404:
            return {}
        else:
            raise
    except:
        raise
    else:
        # logger.debug(f"gitlab res_commit={LF}{pprint.pformat(res_files)}")
        return res_files


def compare_ethercalc_and_gitlab(actions, ethercalc_uri, git_filename):
    """
Obtenez des fichiers à partir des référentiels EtherCalc et GitLab, comparez et ajoutez des actions à la variable d'actions s'il y a des différences

    Parameters
    ----------
    actions : list
Variable Actions transmise plus tard à l'API commits de GitLab

    ethercalc_uri : str
URI EtherCalc

    git_filename : str
Nom de fichier dans le référentiel git

    Returns
    -------
Aucun
    """

    logger.info(f"ethercalc URL={ethercalc_uri}")

    #Télécharger depuis EtherCalc
    request = urllib.request.Request(ethercalc_uri)
    with urllib.request.urlopen(request) as res:
        content_ethercalc = res.read().decode("utf-8")
    # logger.debug(f"content_ethercalc={LF}{content_ethercalc}")

    #Télécharger depuis GitLab
    action_str = ""
    file_path = f"{gitlab_backup_directory}/{git_filename}"
    res_gitlab_file = get_gitlab_file(gitlab_private_token, file_path)
    try:
        content_gitlab = base64.b64decode(res_gitlab_file["content"]).decode("utf-8")
    except KeyError:
        #S'il n'y a pas de fichier dans GitLab, créez-en un nouveau plus tard et git commit & push
        action_str = "create"
    except:
        raise
    else:
        # logger.debug(f"content_gitlab={LF}{content_gitlab}")

        #Comparez les fichiers téléchargés depuis EtherCalc et GitLab
        if content_ethercalc == content_gitlab:
            logger.info("content_ethercalc == content_gitlab")
        else:
            logger.info("content_ethercalc != content_gitlab")
            #Quand il y a une différence dans le contenu du fichier, git commit et push plus tard
            action_str = "update"

    #Enregistré dans la variable d'actions lorsque l'action est créée ou mise à jour
    if 0 < len(action_str):
        action = {
            "action": action_str,
            "file_path": file_path,
            "content": content_ethercalc
        }
        actions.append(action)


def main():
    # ethercalc_Traitez chaque URL d'uris
    actions = list()
    count_commit = 0
    re_compile = re.compile(r".*/(.*?)$")
    for index, ethercalc_uri in enumerate(ethercalc_uris):
        basename, = re_compile.match(ethercalc_uri).groups()    #Chaîne"foo"、"bar"Sortir
        socialcalc_uri = ethercalc_uri[::-1].replace(basename[::-1], basename[::-1] + "/_", 1)[::-1]
        csv_uri = ethercalc_uri + ".csv"
        logger.info(f"[{index}] {basename}")

        #Téléchargez depuis EtherCalc et GitLab au format SocialCalc et comparez le contenu des fichiers
        time.sleep(0.5)     #Dormez correctement pour ne pas être une attaque DoS
        compare_ethercalc_and_gitlab(actions, socialcalc_uri, f"{basename}.sc")

        #Téléchargez depuis EtherCalc et GitLab au format csv et comparez le contenu des fichiers
        time.sleep(0.5)     #Dormez correctement pour ne pas être une attaque DoS
        compare_ethercalc_and_gitlab(actions, csv_uri, f"{basename}.csv")

        if len(actions) == 0:
            #Ne git commit s'il n'y a pas de différence dans le contenu des fichiers d'EtherCalc et de GitLab
            continue

        # git commit & push
        # https://docs.gitlab.com/ee/api/commits.html
        gitlab_uri = f"{gitlab_base_uri}api/v4/projects/{gitlab_project_id}/repository/commits"
        commit_message = datetime.datetime.today().strftime(f"backup {str_now} {basename}")
        logger.info(f'git commit -m "{commit_message}"')
        headers = {
            "method": "POST",
            "PRIVATE-TOKEN": gitlab_private_token,
            "Content-Type": "application/json"
        }
        payload = {
            "branch": "master",
            "commit_message": commit_message,
            "actions": actions
        }
        logger.debug(f"payload={LF}{pprint.pformat(payload)}")

        request = urllib.request.Request(gitlab_uri, json.dumps(payload).encode("utf-8"), headers=headers)
        with urllib.request.urlopen(request) as res:
            res_commit = json.loads(res.read())
        logger.debug(f"gitlab res_commit={LF}{pprint.pformat(res_commit)}")

        #git diff et sortie dans le journal
        # https://docs.gitlab.com/ee/api/commits.html
        gitlab_uri = f"{gitlab_base_uri}api/v4/projects/{gitlab_project_id}/repository/commits/{res_commit['id']}/diff"
        logger.info(f"git diff ( {res_commit['id']} )")
        headers = {
            "PRIVATE-TOKEN": gitlab_private_token,
        }
        request = urllib.request.Request(gitlab_uri, headers=headers)
        with urllib.request.urlopen(request) as res:
            res_diff = json.loads(res.read())
        logger.info(f"gitlab res_diff={LF}{pprint.pformat(res_diff)}")

        count_commit += 1
        actions = list()

    logger.info(f"{count_commit}Git commit")


if __name__ == '__main__':
    try:
        main()
    except Exception as ee:
        logger.exception(ee)

Premier essai

La première fois, le référentiel GitLab est vide. Procédez comme suit sur votre terminal:


python3 ethercalc_backup.py

Ce qui suit est affiché à la fin du message d'exécution.


2 commits git

Vérifiez le projet sur l'écran GitLab. Il a 2 Commits comme indiqué ci-dessous, et un nouveau répertoire ethercalc a été créé.

2020-08-17-15.png

Lorsque je suis passé sous ethercalc, il y avait deux types de commits, foo et bar, comme indiqué ci-dessous, et deux nouveaux fichiers, le format SocialCalc et le format csv, ont été créés pour chaque commit.

2020-08-17-16.png

Vous pouvez vérifier le contenu en cliquant sur le nom du fichier.

Deuxième essai

La deuxième fois, je ne changerai que le contenu de foo avec EtherCalc et exécuterai le code Python. J'ai ajouté Hello etc. comme suit.

2020-08-17-17.png

Procédez comme suit sur votre terminal:


python3 ethercalc_backup.py

Ce qui suit est affiché à la fin du message d'exécution.


1 git commit

Vérifiez le projet sur l'écran GitLab. Il s'agit de 3 Commits comme indiqué ci-dessous.

2020-08-17-18.png

3 Lorsque je clique sur Commits, j'ai ajouté un récent commit foo comme indiqué ci-dessous, mais rien pour bar.

2020-08-17-20.png

Lorsque j'ai cliqué sur le commit du toto ajouté, la différence avec le commit précédent était affiché comme indiqué ci-dessous.

2020-08-17-21.png

Troisième essai

La troisième fois, j'essaierai d'exécuter le code Python sans changer EtherCalc.


python3 ethercalc_backup.py

Ce qui suit est affiché à la fin du message d'exécution.


0 git commits

c'est tout.

Recommended Posts

Un programme Python qui vérifie si un contenu a été mis à jour et git valide et pousse vers GitLab s'il a été mis à jour.
Un programme python qui redimensionne une vidéo et la transforme en image
Je veux exécuter et distribuer un programme qui redimensionne les images Python3 + pyinstaller
Écrivons un programme Python et exécutons-le
Script Python qui explore le flux RSS du statut Azure et le publie sur Hipchat
Un programme qui demande quelques kilogrammes pour atteindre l'IMC et le poids standard [Python]
Une histoire qui facilite l'estimation de la surface habitable à l'aide d'Elasticsearch et de Python
[Python] Un programme pour trouver le nombre de pommes et d'oranges qui peuvent être récoltées
[Gratuit] Le cours de certification Python a été ajouté à freeCodeCamp!
Comment écrire une classe méta qui prend en charge à la fois python2 et python3
・ <Slack> Ecrire une fonction pour notifier Slack afin qu'elle puisse être citée à tout moment (Python)
Ecrire un programme qui abuse du programme et envoie 100 e-mails
Un guide rapide de PyFlink qui combine Apache Flink et Python
Code Python pour vérifier et représenter graphiquement s'il suit la loi de Benford
[Python] Un programme qui fait pivoter le contenu de la liste vers la gauche
[Python / Jupyter] Traduisez le commentaire du programme copié dans le presse-papiers et insérez-le dans une nouvelle cellule.