GitLab CI: 6 Funktionen aus den neuesten Versionen, auf die wir gewartet haben



Im Zeitalter des allgegenwärtigen CI / CD stehen wir vor einer Vielzahl verwandter Tools, einschließlich CI-Systemen. Es war jedoch GitLab, das uns am nächsten kam, wirklich "native". Er erlangte bemerkenswerte Popularität in der gesamten Branche *. Die Entwickler des Produkts blieben nicht hinter dem wachsenden Interesse an seiner Verwendung zurück und begeisterten regelmäßig die Community der Entwickler und DevOps-Ingenieure mit neuen Versionen.


GitLab-Repository-Monat und Tag-Aggregation

GitLab ist der Fall, wenn die aktive Entwicklung viele neue und interessante Funktionen bringt. Wenn dies für potenzielle Benutzer nur einer der Faktoren bei der Auswahl eines Tools ist, ist die Situation für vorhandene Benutzer wie folgt: Wenn Sie Ihre GitLab-Installation im letzten Monat nicht aktualisiert haben, haben Sie mit hoher Wahrscheinlichkeit etwas Interessantes verpasst. Einschließlich regelmäßig auftretender Sicherheitsupdates.

Über die bedeutendsten - d.h. Von unseren DevOps-Ingenieuren und -Kunden gefordert - Innovationen in den neuesten Versionen der Community-Edition von GitLab. Dieser Artikel wird diskutiert.

* 5 , «GitLab», : «, GitHub?». — , Google Trends 5- «gitlab» . «» , . , , «» .

№1: needs


  • job'.
  • GitLab: 12.2.
  • .

Gedanke dependencies- das ist was du brauchst? Wahrscheinlich waren wir nicht die einzigen, die den Fehler gemacht haben, diese Richtlinie zuzuweisen ... Es ist erforderlich, die vorherigen Jobs aufzulisten, deren Artefakte erforderlich sein werden. Es handelt sich um Artefakte und nicht um die Abhängigkeit von der Leistung der vorherigen Aufgabe.

Angenommen, es gibt in einer Phase Jobs, die nicht ausgeführt werden müssen, aber aus irgendeinem Grund gibt es keine Möglichkeit oder nur den Wunsch, sie in eine separate Phase zu bringen (Faulheit ist der Motor des Fortschritts, aber lassen Sie sich nicht mitreißen).

Situation:



Wie Sie sehen können, enthält Stage Deploy Schaltflächen zum Ausrollen von Produktions- und Stage- sowie Job- Selenium-Testsaus irgendeinem Grund wird nicht ausgeführt. Es ist ganz einfach: Er wartet, bis alle Aufträge aus der vorherigen Phase erfolgreich abgeschlossen wurden. Im Rahmen derselben Pipeline müssen wir jetzt keine Phase bereitstellen, um die Tests auszuführen (sie wurde früher abgepumpt, nicht innerhalb des Tags). Was ist zu tun? Dann kommen Sie zu den Rettungs Bedürfnisse !

Wir listen nur die erforderlichen vorherigen Jobs auf, um unsere Tests auszuführen:

  needs:
    - To production (Cluster 1)
    - To production (Cluster 2)

... und wir bekommen einen Job, der automatisch aufgerufen wird, nachdem nur die aufgelisteten Jobs ausgeführt wurden:



Praktisch, richtig? Aber einmal hatte ich erwartet, dass die Richtlinie so etwas funktionieren würde dependencies...

Nr. 2: erstreckt sich



Keine Lust mehr auf Rollen .gitlab-ci.yaml? Fehlt das Prinzip der Code-Wiederverwendung? Dann haben Sie es bereits versucht und wahrscheinlich erfolgreich .gitlab-ci.yamlin einen Zustand wie diesen gebracht:

.base_deploy: &base_deploy
  stage: deploy
  script:
    - my_deploy_command.sh
  variables:
    CLUSTER: "default-cluster"
    MY_VAR: "10"

Deploy Test:
  <<: *base_deploy
  environment:
    url: test.example.com
    name: test

Deploy Production:
  <<: *base_deploy
  environment:
    url: production.example.com
    name: production
  variables:
    CLUSTER: "prod-cluster"
    MY_VAR: "10"

Klingt gut? Wenn Sie genau hinschauen, fällt Ihnen jedoch etwas auf ... Warum haben wir die Produktion nicht nur geändert variables.CLUSTER, sondern auch ein zweites Mal verschrieben variables.MY_VAR=10? Sollte diese Variable entnommen werden base_deploy? Es stellt sich heraus, dass dies nicht der Fall sein sollte: YAML funktioniert so, dass bei einer Neudefinition des vom Anker empfangenen Inhalts der Inhalt der übereinstimmenden Felder nicht erweitert , sondern ersetzt wird . Daher sind wir gezwungen, die uns bereits bekannten Variablen im entsprechenden Absatz aufzulisten.

Ja, "Erweitern" ist das richtige Wort: Genau so wird die betreffende Funktion genannt. ExtendsSie ermöglichen es uns nicht nur, das Feld neu zu schreiben, wie es beim Anker geschieht, sondern auch eine intelligente Zusammenführung durchzuführen:

.base_deploy: 
  stage: deploy
  script:
    - my_deploy_command.sh
  variables:
    CLUSTER: "default-cluster"
    MY_VAR: "10"

Deploy Production:
  extends: .base_deploy
  environment:
    url: production.example.com
    name: production
  variables:
    CLUSTER: "prod-cluster"

Hier im letzten Job Deploy Production gibt es sowohl eine Variable MY_VARmit einem Standardwert als auch eine überschriebene CLUSTER.

Es scheint, dass dies eine Kleinigkeit ist, aber stellen Sie sich vor: Sie haben einen base_deployund 20 Schaltkreise ähnlich eingesetzt. Sie müssen an andere weitergegeben werden cluster, environment.namewährend ein bestimmter Satz von Variablen oder andere übereinstimmende Felder erhalten bleiben ... Diese kleine Angenehmheit ermöglichte es uns, die Beschreibung des Einsatzes vieler Entwicklungsschaltungen um das 2-3-fache zu reduzieren.

Nr. 3: einschließen



.gitlab-ci.yamlEs sieht immer noch aus wie eine Faltanleitung für einen Staubsauger in 20 Sprachen (von denen Sie nur Ihre Muttersprache verstehen). Ist es schwierig, sich mit einem seiner Abschnitte zu befassen, ohne sich angesichts unbekannter Aufgaben auf dem Weg zu ändern?

Ein langjähriger Programmierfreund wird helfen include:

stages:
  - test
  - build
  - deploy

variables:
  VAR_FOR_ALL: 42

include:
  - local: .gitlab/ci/test.yml
  - local: .gitlab/ci/build.yml
  - local: .gitlab/ci/deploy-base.yml
  - local: .gitlab/ci/deploy-production.yml

Jene. Jetzt bearbeiten wir mutig die Bereitstellung in der Produktion, während Tester damit beschäftigt sind, ihre Datei zu ändern, was wir möglicherweise nicht einmal betrachten. Darüber hinaus hilft dies, Zusammenführungskonflikte zu vermeiden: Es macht nicht immer Spaß, den Code eines anderen zu verstehen.

Aber was ist, wenn wir die Pipeline unserer 20 Projekte entlang und über kennen, können wir die Logik jedes Jobs daraus erklären? Wie wird uns das helfen? Für diejenigen, die eine Aufklärung über die Wiederverwendung von Code erreicht haben, und für alle, die viele ähnliche Projekte haben, können Sie:


Ein Dutzend Projekte derselben Art mit unterschiedlichem Code, die jedoch auf dieselbe Weise bereitgestellt wurden - einfach und ohne Aktualisierung des aktuellen CI in allen Repositorys!

Ein Beispiel für die praktische Anwendung includewurde auch in diesem Artikel gegeben .

Nr. 4: nur / außer refs


  • Umfassende Bedingungen, einschließlich Variablen und Dateiänderungen.
  • Da es sich um eine ganze Familie von Funktionen handelt, wurden einige Teile in GitLab 10.0 angezeigt, während andere (z. B. changes) in 11.4 angezeigt wurden.
  • docs.gitlab.com/ce/ci/yaml/#onlyexcept-advanced

Manchmal scheint es mir, dass dies keine Pipeline ist, die uns zuhört, sondern wir ihn. Ein hervorragendes Management-Tool ist only/ except- jetzt integriert. Was bedeutet das?

Im einfachsten (und vielleicht angenehmsten) Fall überspringen Sie die Phasen:

Tests:
  only:
    - master
  except:
    refs:
    - schedules
    - triggers
    variables:
    - $CI_COMMIT_MESSAGE =~ /skip tests/

Im Beispieljob wird es nur im Hauptzweig ausgeführt, kann jedoch nicht durch einen Zeitplan oder Trigger ausgelöst werden (GitLab teilt API-Aufrufe und -Trigger, obwohl dies im Wesentlichen dieselbe API ist). Der Job wird nicht ausgeführt, wenn die Festschreibungsnachricht eine Passphrase zum Überspringen von Tests enthält . Zum Beispiel wurde ein Tippfehler im README.mdProjekt oder in der Dokumentation behoben - warum auf die Testergebnisse warten?

"Hey, 2020 ist draußen!" Warum sollte ich der Eisenbox jedes Mal erklären, dass beim Ändern der Dokumentation keine Tests durchgeführt werden müssen? “ Und wirklich: only:changesSie können Tests ausführen, wenn Sie Dateien nur in bestimmten Verzeichnissen ändern. Zum Beispiel:

  only:
    refs:
      - master
      - merge_requests
    changes:
      - "front/**/*"
      - "jest.config.js"
      - "package.json"

Und für die umgekehrte Aktion - d.h. nicht laufen - ja except:changes.

Nr. 5: Regeln



Diese Anweisung ist den vorherigen sehr ähnlich, only:*hat jedoch einen wichtigen Unterschied: Sie ermöglicht die Steuerung des Parameters when. Zum Beispiel, wenn Sie die Möglichkeit, einen Job zu starten, nicht vollständig entfernen möchten. Sie können einfach die Schaltfläche verlassen, die bei Bedarf unabhängig aufgerufen wird, ohne eine neue Pipeline zu starten oder ohne ein Commit durchzuführen.

# 6: Umgebung: auto_stop_in



Wir haben diese Gelegenheit kurz vor der Veröffentlichung des Artikels kennengelernt und hatten noch nicht genug Zeit, um sie in der Praxis auszuprobieren, aber dies ist definitiv „das Gleiche“, was in mehreren Projekten so erwartet wurde.

Sie können einen Parameter in GitLab-Umgebungen angeben. Dies on_stopist sehr nützlich, wenn Sie Umgebungen dynamisch erstellen und löschen möchten, z. B. für jeden Zweig. Der mit k gekennzeichnete Job on_stopwird beispielsweise ausgeführt, wenn sich die Zusammenführung von MR im Hauptzweig befindet oder wenn der MR geschlossen wird (oder auch nur durch Klicken auf die Schaltfläche), wodurch die unnötige Umgebung automatisch gelöscht wird.

Alles ist bequem, logisch, funktioniert ... wenn nicht für den menschlichen Faktor. Viele Entwickler führen MRs nicht durch Klicken auf eine Schaltfläche in GitLab zusammen, sondern lokal über git merge. Sie können sie verstehen: es ist bequem! Aber in diesem Fall die Logikon_stopes funktioniert nicht, wir haben vergessene Umgebungen angesammelt ... Hier bieten sich die lang erwarteten an auto_stop_in.

Bonus: temporäre Hütten, wenn nicht genügend Möglichkeiten vorhanden sind


Trotz all dieser (und vieler anderer) neuer, nachgefragter Funktionen von GitLab sind die Bedingungen für die Erfüllung eines Auftrags im Rahmen der derzeit verfügbaren Funktionen leider manchmal einfach nicht zu beschreiben.

GitLab ist nicht perfekt, bietet aber die grundlegenden Tools zum Erstellen einer Traum-Pipeline ... wenn Sie bereit sind, über das bescheidene DSL hinauszugehen und in die Welt des Skripts einzutauchen. Hier sind einige Lösungen aus unserer Erfahrung, die in keiner Weise vorgeben, ideologisch korrekt oder empfohlen zu sein, sondern eher vorgestellt werden, um verschiedene Möglichkeiten mit einem Mangel an integrierter API-Funktionalität zu demonstrieren.

Problemumgehung Nr. 1: Starten Sie zwei Jobs mit einer Schaltfläche


script:
  - > 
    export CI_PROD_CL1_JOB_ID=`curl -s -H "PRIVATE-TOKEN: ${GITLAB_API_TOKEN}" \ 
      "https://gitlab.domain/api/v4/projects/${CI_PROJECT_ID}/pipelines/${CI_PIPELINE_ID}/jobs" | \
      jq '[.[] | select(.name == "Deploy (Cluster 1)")][0] | .id'`
  - > 
    export CI_PROD_CL2_JOB_ID=`curl -s -H "PRIVATE-TOKEN: ${GITLAB_API_TOKEN}" \ 
      "https://gitlab.domain/api/v4/projects/${CI_PROJECT_ID}/pipelines/${CI_PIPELINE_ID}/jobs" | \
      jq '[.[] | select(.name == "Deploy (Cluster 2)")][0] | .id'`
  - > 
    curl -s --request POST -H "PRIVATE-TOKEN: ${GITLAB_API_TOKEN}" \ 
      "https://gitlab.domain/api/v4/projects/${CI_PROJECT_ID}/jobs/$CI_PROD_CL1_JOB_ID/play"
  - > 
    curl -s --request POST -H "PRIVATE-TOKEN: ${GITLAB_API_TOKEN}" \ 
      "https://gitlab.domain/api/v4/projects/${CI_PROJECT_ID}/jobs/$CI_PROD_CL2_JOB_ID/play"

Und warum nicht, wenn Sie wirklich wollen?

Problemumgehung Nr. 2: Übertragung in MR-RB-Dateien für Rubocop im Bild geändert


Rubocop:
  stage: test
  allow_failure: false
  script:
    ...
    - export VARFILE=$(mktemp)
    - export MASTERCOMMIT=$(git merge-base origin/master HEAD)
    - echo -ne 'CHANGED_FILES=' > ${VARFILE}
    - if [ $(git --no-pager diff --name-only ${MASTERCOMMIT} | grep '.rb$' | wc -w |awk '{print $1}') -gt 0 ]; then
        git --no-pager diff --name-only ${MASTERCOMMIT} | grep '.rb$' |tr '\n' ' ' >> ${VARFILE} ;
      fi
    - if [ $(wc -w ${VARFILE} | awk '{print $1}') -gt 1 ]; then
        werf --stages-storage :local run rails-dev --docker-options="--rm --user app --env-file=${VARFILE}" -- bash -c /scripts/rubocop.sh ;
      fi
    - rm ${VARFILE}

Da sich kein Bild darin befindet .git, musste ich aussteigen, um nur die geänderten Dateien zu überprüfen.

Hinweis: Dies ist keine sehr übliche Situation und ein verzweifelter Versuch, viele Bedingungen des Problems zu erfüllen, deren Beschreibung nicht im Umfang dieses Artikels enthalten ist.

Problemumgehung Nr. 3: Auslöser zum Starten von Jobs aus anderen Repositorys beim Rollout


  before_script:
    - |
      echo '### Trigger review: infra'
      curl -s -X POST \
        -F "token=$REVIEW_TOKEN_INFRA" \
        -F "ref=master" \
        -F "variables[REVIEW_NS]=$CI_ENVIRONMENT_SLUG" \
        -F "variables[ACTION]=auto_review_start" \
        https://gitlab.example.com/api/v4/projects/${INFRA_PROJECT_ID}/trigger/pipeline

Es scheint, dass eine so einfache und notwendige Sache (in der Welt der Mikrodienste) darin besteht, einen anderen Mikrodienst als Abhängigkeit in eine neu erstellte Schaltung einzuführen. Es ist jedoch kein API-Aufruf und eine bereits bekannte (oben beschriebene) Funktion erforderlich:

  only:
    refs:
    - triggers
    variables:
    - $ACTION == "auto_review_start"

Anmerkungen:

  • Job on Trigger ist so konzipiert, dass eine Variable an die API übergeben wird, ähnlich wie in Beispiel Nr. 1. Es ist logischer, dies auf der API mit dem übergebenen Jobnamen zu implementieren.
  • Ja, die Funktion ist in der kommerziellen (EE) Version von GitLab enthalten, wird jedoch nicht berücksichtigt.

Fazit


GitLab versucht, mit den Trends Schritt zu halten und schrittweise Funktionen zu implementieren, die von der DevOps-Community angenehm und gefragt sind. Sie sind recht einfach zu bedienen und können jederzeit mit Skripten erweitert werden, wenn die grundlegenden Funktionen nicht ausreichen. Und wenn wir sehen, dass es sich beim Support nicht so elegant und bequem herausstellt ... bleibt es, auf neue Versionen von GitLab zu warten - oder dem Projekt mit unserem Beitrag zu helfen .

PS


Lesen Sie auch in unserem Blog:


All Articles