Ein Python-Programm, das prüft, ob Inhalte aktualisiert wurden, und git festschreibt und an GitLab sendet, wenn diese aktualisiert wurden.

Was ist in diesem Artikel zu tun?

Referenzseite (Danke)

GitLab Docs > API Docs > API resources

Umgebung

Ubuntu 20.04


$ python3 --version
Python 3.8.2

Einführung in GitLab und Erstellen eines Projekts

Einführung von GitLab

Jetzt fangen wir an. Verwenden Sie das lokale GitLab als Git-Server. Dieses Mal werden wir es schnell lokal mit Docker einführen. Führen Sie die folgenden Schritte aus, nachdem Sie in ein geeignetes Verzeichnis auf dem Terminal verschoben haben.


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

cd docker-gitlab

docker-compose up -d

Als ich nach dem Starten des Containers eine Weile gewartet und "docker-compose ps" ausgeführt habe, wurde Folgendes angezeigt.


           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            

Der http-Port des GitLab-Containers ist 10080. Greifen Sie also mit Ihrem Browser auf http: // localhost: 10080 / zu. Wenn der folgende Bildschirm angezeigt wird, ändern Sie das Root-Passwort.

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

Gehen Sie zum Bildschirm unten und erstellen Sie einen Entwicklungsbenutzer (Benutzername kann alles sein).

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

Erstellen eines GitLab-Projekts

Nachdem Sie sich als Entwicklungsbenutzer angemeldet haben, wählen Sie im folgenden Bildschirm die Option Projekt erstellen.

2020-08-17-01.png

Der Projektname lautet "ethercalc_backup" (siehe unten), der Name kann jedoch beliebig sein. Klicken Sie auf die Schaltfläche Projekt erstellen, um ein Projekt zu erstellen.

2020-08-17-02.png

Das Projekt wurde wie folgt erstellt. Die Projekt-ID wird unter dem Projektnamen angezeigt (3 in diesem Artikel). Sie werden diese ID später in Ihrem Python-Code verwenden.

2020-08-17-03.png

Holen Sie sich das Zugriffstoken für die GitLab-API

Sie werden später die GitLab-API aus Ihrem Python-Code verwenden. Zu diesem Zeitpunkt benötigen Sie ein Zugriffstoken. Rufen Sie wie unten gezeigt das Pulldown-Menü oben rechts im Browser auf und wählen Sie "Einstellungen".

2020-08-17-10.png

Wählen Sie auf dem Bildschirm unten im Menü links "Zugriffstoken" aus.

2020-08-17-11.png

Geben Sie auf dem Bildschirm unten unter Name einen beliebigen Namen ein. Scopes überprüft die API und drückt auf die Schaltfläche "Persönliches Zugriffstoken erstellen".

2020-08-17-12.png

Das Zugriffstoken wurde wie folgt erstellt. Kopieren Sie es in die Zwischenablage und speichern Sie es. In diesem Artikel verwenden wir "6f8YXyrZ1SCSADHTJ2L9" als Zugriffstoken.

2020-08-17-13.png

Einführung von EtherCalc

Als Anbieter von Textinhalten verwenden wir EtherCalc für diesen Artikel. Stellen Sie es wie bei GitLab lokal mit Docker bereit. Erstellen Sie nach dem Wechsel in ein anderes Verzeichnis als GitLab auf dem Terminal die Datei docker-compose.yml mit demselben Inhalt wie https://github.com/audreyt/ethercalc/blob/master/docker-compose.yml und erstellen Sie einen Container. Anlaufen.


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

docker-compose up -d

Als ich nach dem Starten des Containers eine Weile gewartet und "docker-compose ps" ausgeführt habe, wurde Folgendes angezeigt.


            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         

Da der http-Port des EtherCalc-Containers 80 ist, versuchen Sie, mit einem Browser auf http: // localhost / zuzugreifen.

2020-08-17-04.png

Erstellen Sie zwei EtherCalc-Blätter zum Testen. Starten Sie einen Texteditor, erstellen Sie eine neue Datei foo.sc und bar.sc und speichern Sie sie.


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--

Die obigen Dateien foo.sc und bar.sc sind Textdateien im SocialCalc-Format, die in EtherCalc importiert werden können. Das Exportieren / Importieren im SocialCalc-Format hat den Vorteil, dass das Blattformat (Erscheinungsbild) ebenfalls wiederhergestellt werden kann. Sie können auch Dateien im CSV-Format importieren, das Blattformat jedoch nicht wiederherstellen.

Gehen Sie zum Importieren wie folgt vor.


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

Greifen Sie mit Ihrem Browser auf http: // localhost / foo und http: // localhost / bar zu. Wenn die Zelle des Blattes die folgenden Daten enthält, ist der Import erfolgreich.

2020-08-17-05.png

2020-08-17-06.png

Wir werden die Dateien in den Formaten SocialCalc und CSV von diesen URLs herunterladen und in GitLab verwalten.

Python-Code

Bitte verzeihen Sie mir, dass der Code verschieden ist und sich schlecht benimmt.

Die logische Verarbeitungsprozedur ist wie folgt. Für jeden Inhalt von foo und bar

--Download von Dateien aus EtherCalc und GitLab (sowohl SocialCalc- als auch CSV-Format) --Wenn die Datei in GitLab nicht vorhanden ist, fügen Sie dem Git-Repository eine neue hinzu. --Wenn sich in GitLab eine Datei befindet, vergleichen Sie sowohl EtherCalc- als auch GitLab-Dateien. Wenn es einen Unterschied gibt, aktualisieren Sie das Git-Repository.

Unten ist der Python-Code. Der Code verwendet eine Variable namens logger. Beachten Sie jedoch, dass der Code für die Protokollierung weggelassen wurde.

ethercalc_backup.py



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

#URL des von git verwalteten Ethercalc-Inhalts
ethercalc_uris = [ "http://localhost/foo", "http://localhost/bar" ]

#GitLab verwandt
gitlab_base_uri = "http://localhost:10080/"

#Sicherungsziel im Git-Repository
gitlab_backup_directory = "ethercalc"

gitlab_private_token = "6f8YXyrZ1SCSADHTJ2L9"
gitlab_project_id = 3

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

#Neue Zeile
LF = '\n'


def get_gitlab_file(private_token, file_path):
    """
Holen Sie sich 1 Datei aus dem GitLab-Repository

    Parameters
    ----------
    private_token : str
Zugriffstoken für die GitLab-API

    file_path : str
Dateipfad vom oberen Rand des Git-Repositorys

    Returns
    -------
    anonymous : json
Antwort von 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):
    """
Holen Sie sich Dateien aus den EtherCalc- und GitLab-Repositorys, vergleichen Sie die Aktionsvariablen und fügen Sie sie hinzu, wenn es einen Unterschied gibt

    Parameters
    ----------
    actions : list
Die Aktionsvariable wurde später an die Commit-API von GitLab übergeben

    ethercalc_uri : str
EtherCalc-URI

    git_filename : str
Dateiname im Git-Repository

    Returns
    -------
Keiner
    """

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

    #Herunterladen von 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}")

    #Von GitLab herunterladen
    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:
        #Wenn es in GitLab keine Datei gibt, erstellen Sie später eine neue und git commit & push
        action_str = "create"
    except:
        raise
    else:
        # logger.debug(f"content_gitlab={LF}{content_gitlab}")

        #Vergleichen Sie die von EtherCalc und GitLab heruntergeladenen Dateien
        if content_ethercalc == content_gitlab:
            logger.info("content_ethercalc == content_gitlab")
        else:
            logger.info("content_ethercalc != content_gitlab")
            #Wenn es einen Unterschied im Dateiinhalt gibt, git commit & push später
            action_str = "update"

    #Wird in der Aktionsvariablen registriert, wenn eine Aktion erstellt oder aktualisiert wird
    if 0 < len(action_str):
        action = {
            "action": action_str,
            "file_path": file_path,
            "content": content_ethercalc
        }
        actions.append(action)


def main():
    # ethercalc_Verarbeiten Sie jede URL von 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()    #String"foo"、"bar"Mitnahme
        socialcalc_uri = ethercalc_uri[::-1].replace(basename[::-1], basename[::-1] + "/_", 1)[::-1]
        csv_uri = ethercalc_uri + ".csv"
        logger.info(f"[{index}] {basename}")

        #Laden Sie von EtherCalc und GitLab im SocialCalc-Format herunter und vergleichen Sie den Dateiinhalt
        time.sleep(0.5)     #Schlafen Sie richtig, um kein DoS-Angriff zu sein
        compare_ethercalc_and_gitlab(actions, socialcalc_uri, f"{basename}.sc")

        #Laden Sie es von EtherCalc und GitLab im CSV-Format herunter und vergleichen Sie den Dateiinhalt
        time.sleep(0.5)     #Schlafen Sie richtig, um kein DoS-Angriff zu sein
        compare_ethercalc_and_gitlab(actions, csv_uri, f"{basename}.csv")

        if len(actions) == 0:
            #Geben Sie kein Commit ein, wenn sich der Dateiinhalt von EtherCalc und GitLab nicht unterscheidet
            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 und Ausgabe zu protokollieren
        # 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)

Erster Versuch

Beim ersten Mal ist das GitLab-Repository leer. Gehen Sie auf Ihrem Terminal wie folgt vor:


python3 ethercalc_backup.py

Folgendes wird am Ende der Ausführungsnachricht angezeigt.


2 Git Commits

Überprüfen Sie das Projekt auf dem GitLab-Bildschirm. Es hat 2 Commits wie unten gezeigt und ein neues Ethercalc-Verzeichnis wurde erstellt.

2020-08-17-15.png

Als ich unter ethercalc ging, gab es zwei Arten von Commits, foo und bar, wie unten gezeigt, und zwei neue Dateien, das SocialCalc-Format und das CSV-Format, wurden für jedes Commit erstellt.

2020-08-17-16.png

Sie können den Inhalt überprüfen, indem Sie auf den Dateinamen klicken.

Zweiter Versuch

Beim zweiten Mal werde ich nur den Inhalt von foo mit EtherCalc ändern und den Python-Code ausführen. Ich habe Hallo usw. wie folgt hinzugefügt.

2020-08-17-17.png

Gehen Sie auf Ihrem Terminal wie folgt vor:


python3 ethercalc_backup.py

Folgendes wird am Ende der Ausführungsnachricht angezeigt.


1 Git Commit

Überprüfen Sie das Projekt auf dem GitLab-Bildschirm. Es sind 3 Commits wie unten gezeigt.

2020-08-17-18.png

3 Wenn ich auf Commits klicke, habe ich ein aktuelles foo-Commit hinzugefügt, wie unten gezeigt, aber nichts für die Leiste.

2020-08-17-20.png

Als ich auf das Commit des hinzugefügten Foo geklickt habe, wurde der Unterschied zum vorherigen Commit wie unten gezeigt angezeigt.

2020-08-17-21.png

Dritter Versuch

Beim dritten Mal werde ich versuchen, den Python-Code auszuführen, ohne EtherCalc zu ändern.


python3 ethercalc_backup.py

Folgendes wird am Ende der Ausführungsnachricht angezeigt.


0 Git Commits

das ist alles.

Recommended Posts

Ein Python-Programm, das prüft, ob Inhalte aktualisiert wurden, und git festschreibt und an GitLab sendet, wenn diese aktualisiert wurden.
Ein Python-Programm, das die Größe eines Videos ändert und es in ein Bild verwandelt
Ich möchte ein Programm ausführen und verteilen, das die Größe von Bildern in Python3 + Pyinstaller ändert
Schreiben wir ein Python-Programm und führen es aus
Python-Skript, das das Azure-Status-RSS crawlt und an Hipchat sendet
Ein Programm, das ein paar Kilogramm BMI und Standardgewicht verlangt [Python]
Eine Geschichte, die es einfach macht, den Wohnbereich mit Elasticsearch und Python abzuschätzen
[Python] Ein Programm, um die Anzahl der Äpfel und Orangen zu ermitteln, die geerntet werden können
[Free] Python-Zertifizierungskurs wurde zu freeCodeCamp hinzugefügt!
So schreiben Sie eine Meta-Klasse, die sowohl Python2 als auch Python3 unterstützt
・ <Slack> Schreiben Sie eine Funktion, um Slack zu benachrichtigen, damit sie jederzeit in Anführungszeichen gesetzt werden kann (Python).
Schreiben Sie ein Programm, das das Programm missbraucht und 100 E-Mails sendet
Eine Kurzanleitung zu PyFlink, die Apache Flink und Python kombiniert
Codieren Sie Python, um zu überprüfen und grafisch darzustellen, ob es dem Gesetz von Benford entspricht
[Python] Ein Programm, das den Inhalt der Liste nach links dreht
[Python / Jupyter] Übersetzen Sie den Kommentar des in die Zwischenablage kopierten Programms und fügen Sie ihn in eine neue Zelle ein.