CI / CD-Prozessaktualisierung: Vorbereitung und Planung

Bild

Im Jahr 2020 ist es wahrscheinlich ziemlich schwierig, ein Projekt in einer Stapelbeschreibung zu finden, das keines der folgenden Wörter enthält: IaC, Microservices, Kubernetes, Docker, aws / azure / gcloud, Blockchain, ML, VR usw. Und das ist großartig! Fortschritt steht nicht still. Wir wachsen, unsere Projekte wachsen mit uns, es erscheinen bequemere und funktionalere Werkzeuge, die moderne Probleme lösen.

Guten Tag. Also wollte ich diesen Artikel beginnen. Aber dann habe ich einige Dinge überprüft, mit meinen Kollegen gesprochen und festgestellt, dass ich falsch liegen würde. Es gibt immer noch Projekte, die bereits über 15 Jahre alt sind, mit Managern und Teilnehmern, die alte Gläubige sind, und dementsprechend verfügen diese Projekte über einen alten Technologie-Stack, der in einem bestehenden Zoo nur schwer zu pflegen ist. Und aus irgendeinem Grund kann dieses Projekt nicht global aktualisiert werden (der Kunde ist ein Starover, es gibt kein Update, das Projekt ist sehr groß und die Migration verzögert sich oder jeder ist mit allem zufrieden), und Sie müssen es unterstützen. Noch unangenehmer, wenn ein ähnliches Projekt noch aktiv entwickelt wird. Es ist wie ein Schneeball. Der Kunde und die Öffentlichkeit benötigen Funktionen, der Code muss bereitgestellt werden, die Server müssen beachtet und gepflegt werden ... Aber das Bitpack - im Allgemeinen unterstützt es kein Quecksilber mehr. Ein solcher Fall wird zur Prüfung vorgeschlagen.

Was berücksichtigt wird: Konvertieren von mercurial-git, Verschieben von CI von CruiseControl.NET nach TeamCity, von git-Bereitstellung zu Octopus mit einer kleinen Beschreibung des gesamten Prozesses.

Der Text ist sehr viel geworden, daher wird er in separate Teile unterteilt, um die Wahrnehmung zu erleichtern. Es wird ein Inhaltsverzeichnis geben.
Teil 1: Was ist, warum ist es nicht so, Planung, ein kleiner Schlag. Ich würde diesen Teil als nahezu technisch bezeichnen.
Teil 2: Teamcity.
Teil 3: Octopus Deploy.
Teil 4: hinter den Kulissen. Unangenehme Momente, Pläne für die Zukunft, möglicherweise FAQ. Höchstwahrscheinlich kann es auch als nahezu technisch bezeichnet werden.

Ich würde dies aus vielen Gründen nicht als Leitfaden für Wiederholungen bezeichnen: unzureichendes Eintauchen in die Projektprozesse aufgrund von Zeitmangel, unzureichendes Üben solcher Dinge, ein riesiger Monolith, in dem alle Teilprojekte eng miteinander verflochten sind, und eine Reihe anderer Nuancen, die Sie zum Brennen, Staunen und Aushalten bringen , aber auf keinen Fall bitte nicht. Aufgrund der Merkmale des Projekts (es ist ziemlich einzigartig) werden einige Schritte exklusiv für diesen Fall zugeschnitten.

Klassische Einführung


Wir hatten ein Quecksilber-Repository, mehr als 300 (offen!) Brunchs, ccnet, ein weiteres ccnet + git (für Bereitstellungen) und eine ganze Reihe von Projektmodulen mit eigenen Konfigurationen und einzelnen Clients, vier Umgebungen und einer ganzen Reihe von Pools in IIS sowie cmd Skripte, SQL, mehr als fünfhundert Domänen, zwei Dutzend Builds und aktive Entwicklung zusätzlich. Nicht, dass dies alles notwendig gewesen wäre, aber es hat funktioniert, und es war unpraktisch und lang. Das einzige, was mich beunruhigte, war das Vorhandensein anderer Projekte, die meine Aufmerksamkeit erforderten. Nichts bei der Arbeit mit Aufgaben dieser Größenordnung ist gefährlicher als mangelnde Konzentration und Unterbrechung.

Ich wusste, dass ich früher oder später auf andere Aufgaben achten musste, und deshalb habe ich viel Zeit damit verbracht, die vorhandene Infrastruktur zu studieren, damit es später zumindest nicht zu ungelösten Problemen kommt.

Leider kann ich aufgrund der NDA keine vollständige Beschreibung des Projekts geben, sodass allgemeine technische Punkte berücksichtigt werden. Alle Namen, die sich auf das Projekt beziehen, werden ebenfalls übermalt. Ich entschuldige mich für den schwarzen Fleck auf den Screenshots.

Eines der Hauptmerkmale des Projekts ist, dass es eine Reihe von Modulen hat, die einen Kern haben, sich jedoch in ihren Konfigurationen unterscheiden. Es gibt auch Module mit einem „speziellen“ Ansatz, die für Wiederverkäufer und insbesondere Großkunden entwickelt wurden. Ein Modul kann mehr als einen Client bedienen. Ein Kunde sollte als separate Organisation oder Gruppe von Personen verstanden werden, die Zugriff auf ein bestimmtes Modul erhalten. Jeder Client erhält Zugriff auf seine eigene Domain, hat sein eigenes Design und seine eigenen Standardeinstellungen. Der Client wird durch die von ihm verwendete Domäne identifiziert.

Das allgemeine Schema dieses Teils des Projekts kann wie folgt dargestellt werden:


Wie Sie sehen können, wird der Kern überall gleich verwendet, und dies kann verwendet werden.

Gründe, warum die Aufgabe bestand, CI / CD-Prozesse zu überprüfen und zu aktualisieren:

  1. CruiseControl.NET wurde als Build-System verwendet. Die Zusammenarbeit mit ihm ist im Prinzip ein zweifelhaftes Vergnügen. XML-Konfigurationen auf mehreren Bildschirmen, eine Reihe von Abhängigkeiten und Verknüpfungen von Konfigurationen untereinander, Mangel an modernen Lösungen für moderne Probleme.
  2. Einige Entwickler (hauptsächlich Leads) des Projekts müssen Zugriff auf Build-Server haben, und manchmal möchten sie die ccnet-Konfigurationen ändern, die nicht geändert werden sollten. Ratet mal, was als nächstes passiert. Sie benötigen eine einfache und bequeme Verwaltung der Rechte im CI-System, ohne den Entwicklern den Zugriff auf den Server zu entziehen. Einfach gesagt, es gibt keine Textkonfiguration - es gibt keinen Ort, an dem man mit verspielten Händen klettern kann.
  3. - … CCNET, git. (. ).
  4. , . , . 
  5. - , — ( ) .
  6. . ? ? ? .
  7. Suboptimaler Ressourceneinsatz und veralteter Prozess zum Erstellen und Bereitstellen von Code.

Abbildung zu Absatz 3:


In der Planungsphase wurde beschlossen, Teamcity als Build-System und Octopus als Bereitstellungssystem zu verwenden. Die "eiserne" Infrastruktur des Kunden ist unverändert geblieben: separate dedizierte Server für Entwickler, Test, Staging und Produktion sowie Reseller-Server (hauptsächlich Produktionsumgebungen).

Dem Kunden wurde am Beispiel eines der Module ein Proof of Concept zur Verfügung gestellt, ein Aktionsplan erstellt, Vorarbeiten durchgeführt (Installation, Konfiguration usw.). Es macht wahrscheinlich keinen Sinn, dies zu beschreiben. Wie man Team City installiert, kann auf der offiziellen Website nachgelesen werden. Ich werde auf einige formulierte Anforderungen für das neue System separat eingehen:

  1. Einfache Wartung mit allen Konsequenzen (Backups, Updates, Problemlösung, falls vorhanden).
  2. Universalität. Entwickeln Sie im Idealfall ein allgemeines Schema, nach dem alle Module zusammengebaut und geliefert werden, und verwenden Sie es als Vorlage.
  3. Minimieren Sie die Zeit für das Hinzufügen neuer Build-Konfigurationen und die Wartung. Clients werden hinzugefügt / entfernt. Manchmal müssen neue Einstellungen vorgenommen werden. Es ist notwendig, dass beim Erstellen eines neuen Moduls keine Verzögerung bei der Konfiguration seiner Lieferung auftritt.

Ungefähr zu diesem Zeitpunkt erinnerten wir uns an die Einstellung der Unterstützung für Quecksilber-Repositories mit einem Bitbucket, und es wurde die Anforderung hinzugefügt, das Repository an git zu übertragen und dabei die Zweige und den Verlauf der Commits beizubehalten.

Vorbereitung: Repository-Konvertierung


Es scheint, dass jemand dieses Problem klar vor uns und anstelle von uns gelöst hat. Sie müssen nur eine fertige Arbeitslösung finden. Der schnelle Export erwies sich als nicht so schnell. Außerdem hat es nicht funktioniert. Leider sind keine Protokolle und Screenshots mehr vorhanden. Tatsache ist, dass er nicht konnte. Bitbucket bietet keinen eigenen Konverter (könnte aber). Noch ein paar googelte Methoden und auch von. Ich habe beschlossen, meine eigenen Skripte zu schreiben. Dies ist jedoch nicht das einzige Quecksilber-Repository, es wird sich in Zukunft als nützlich erweisen. Hier werden frühe Entwicklungen vorgestellt (weil sie immer noch in der gleichen Form bleiben). Die Logik der Arbeit sieht ungefähr so ​​aus:

  1. Wir nehmen die Erweiterung mercurial hggit als Basis. 
  2. Wir erhalten eine Liste aller Zweige des Quecksilber-Repositorys. 
  3. Wir konvertieren Zweignamen (danke an mercurial und die Entwickler für die Leerzeichen in den Zweignamen, besonderer Dank für die Umlaute und andere Zeichen, die dem Leben Freude machen).
  4. Erstellen Sie Lesezeichen (hg-Lesezeichen) und verschieben Sie sie in das Zwischen-Repository. Wozu? Weil Bitbucket und weil Sie kein Lesezeichen mit demselben Namen wie der Name des Zweigs erstellen können (z. B. Staging). 
  5. Entfernen Sie im neuen (bereits git) Repository das Postfix aus dem Zweignamen und migrieren Sie hgignore nach gitignore. 
  6. Zum Haupt-Repository verschieben.

Auflisten von Befehlen nach Punkten:

  1. $ cd /path/to/hg/repo
    $ cat << EOF >> ./.hg/hgrc
    [extensions]
    hggit=
    EOF
    
  2. $ hg branches > ../branches
    
  3. #!/usr/bin/env bash
    hgBranchList="./branches"
    sed -i 's/:.*//g' ${hgBranchList}
    symbolsToDelete=$(awk '{print $NF}' FS=" " ${hgBranchList} > sym_to_del.tmp)
     
    i=0
    while read hgBranch; do
      hgBranches[$i]=${hgBranch}
      i=$((i+1))
    done <${hgBranchList}
     
    i=0
    while read str; do
      strToDel[$i]=${str}
      i=$((i+1))
    done < ./sym_to_del.tmp
     
    for i in ${!strToDel[@]}
    do
      echo ${hgBranches[$i]} | sed "s/${strToDel[$i]}//" >> result.tmp
    done
     
    sed -i 's/[ \t]*$//' result.tmp
    sed 's/^/"/g' result.tmp > branches_hg
    sed -i 's/$/"/g' branches_hg
    sed 's/ /-/g' result.tmp > branches_git
    sed -i 's/-\/-/\//g' branches_git
    sed -i 's/-\//\//g' branches_git
    sed -i 's/\/-/\//g' branches_git
    sed -i 's/---/-/g' branches_git
    sed -i 's/--/-/g' branches_git
    rm sym_to_del.tmp
    rm result.tmp
    
  4. #!/usr/bin/env bash
    gitBranchList="./branches_git"
    hgBranchList="./branches_hg"
    hgRepo="/repos/reponame"
     
    i=0
    while read hgBranch; do
      hgBranches[$i]=${hgBranch}
      i=$((i+1))
    done <${hgBranchList}
     
    i=0
    while read gitBranch; do
      gitBranches[$i]=${gitBranch}
      i=$((i+1))
    done <${gitBranchList}
     
    cd ${hgRepo}
    for i in ${!gitBranches[@]}
    do
      hg bookmark -r "${hgBranches[$i]}" "${gitBranches[$i]}-cnv"
    done
     
    hg push git+ssh://git@bitbucket.org:username/reponame-temp.git
    echo "Done."
    
  5. #!/bin/bash
    # clone repo, run git branch -a, delete remotes/origin words to leave only branch names, delete -cnv postfix, delete default branch string because we can't delete it
    repo="/repos/repo"
    gitBranchList="./branches_git"
    defaultBranch="default-cnv"
    while read gitBranch; do   gitBranches[$i]=${gitBranch};   i=$((i+1)); done < $gitBranchList
    cd $repo
    for i in ${!gitBranches[@]}; do git checkout ${gitBranches[$i]}-cnv; done
    git checkout $defaultBranch
    for i in ${!gitBranches[@]}; do
        git branch -m ${gitBranches[$i]}-cnv ${gitBranches[$i]}
        git push origin :${gitBranches[$i]}-cnv ${gitBranches[$i]}
        git push origin -u ${gitBranches[$i]}
    done
    
  6. #!/bin/bash
    # clone repo, run git branch -a, delete remotes/origin words to leave only branch names, delete -cnv postfix, delete default branch string because we can't delete it
    repo="/repos/repo"
    gitBranchList="./branches_git"
    defaultBranch="default"
    while read gitBranch; do   gitBranches[$i]=${gitBranch};   i=$((i+1)); done < $gitBranchList
    cd $repo
    for i in ${!gitBranches[@]}; do
        git checkout ${gitBranches[$i]}
        sed -i '1d' .hgignore
        mv .hgignore .gitignore
        git add .
        git commit -m "Migrated ignore file"
    done
    

Ich werde versuchen, die Bedeutung einiger Aktionen zu erläutern, nämlich die Verwendung eines Zwischen-Repositorys. Im Repository enthalten die Filialnamen nach der Konvertierung zunächst das Postfix „-cnv“. Dies liegt an der hg-Lesezeichenfunktion. Sie müssen diesen Postfix entfernen und anstelle von hgignore auch Gitignore-Dateien erstellen. All dies fügt den Verlauf hinzu und vergrößert daher das Repository (und dies in unangemessener Weise). Als weiteres Beispiel kann ich Folgendes anführen: Versuchen Sie, ein Repository zu erstellen, und verschieben Sie das erste Commit mit dem darin enthaltenen Code auf 300 MB. Fügen Sie es dann zu gitignore hinzu und schieben Sie es ohne es. Er wird in der Geschichte bleiben. Versuchen Sie nun, es aus dem Verlauf zu entfernen (Git-Filter-Zweig). Bei einer bestimmten Anzahl von Commits wird die resultierende Repository-Größe nicht verringert, sondern erhöht. Dies wird durch Optimierung gelöst, kann jedoch nicht auf Bitbucket initiiert werden.Es wird nur beim Importieren des Repositorys ausgeführt. Daher werden alle groben Vorgänge mit einem Zwischenprodukt ausgeführt und anschließend in ein neues importiert. Die Größe des Zwischenrepositorys im Finale betrug 1,15 G und die Größe der resultierenden 350 M. 

Fazit


Der gesamte Migrationsprozess war in mehrere Phasen unterteilt:

  • Vorbereitung (Demo für den Kunden anhand eines Beispiels für einen Build, Softwareinstallation, Repository-Konvertierung, Aktualisierung vorhandener ccnet-Konfigurationen);
  • CI / CD-Konfiguration für die Entwicklungsumgebung und ihre Tests (das alte System arbeitet weiterhin parallel);
  • CI / CD-Einstellungen für die verbleibenden Umgebungen (parallel zu den vorhandenen "gut") und Tests;
  • Migrationsentwickler, Staging und Test;
  • Migrieren der Produktion und Übertragen von Domänen von alten IIS-Instanzen auf neue.

Die Beschreibung der erfolgreich abgeschlossenen Vorbereitungsphase wird derzeit abgeschlossen. Einige großartige Erfolge wurden hier nicht erzielt, außer dass das bestehende System nicht zusammenbrach und das Quecksilber-Repository in Git migriert wurde. Ohne eine Beschreibung dieser Prozesse gibt es jedoch keinen Kontext für technischere Teile. Im nächsten Teil wird der Prozess zum Einrichten eines CI-Systems basierend auf Teamcity beschrieben.

All Articles