• Czas czytania ~4 min
  • 25.03.2024

Przyjrzyjmy się kompilowaniu projektu w GO i temu, jak to działa w Gitlab CI.

Kompilacja

Aby zbudować, musimy wywołać go build -o binary_name.

Jeśli projekt ma importy z repozytoriów innych firm, istnieją zależności zewnętrzne. Kompilacja dla języka GO będzie wymagała całego kodu źródłowego, w tym kodu biblioteki zależności. W związku z tym należy upewnić się, że biblioteki innych firm, które mogą nie być przechowywane w repozytorium, są również dostępne do kompilacji.

Producent lub plik do pobrania

W tej chwili aktualna wersja to 1.14.2. Począwszy od wersji GO 1.11 dostępna

jest funkcjonalność modułu (go modules).Moduły GO działają w taki sposób, że GO samo ładuje wszystkie biblioteki innych firm po go runwywołaniu lub go build gdy wszystkie biblioteki są jawnie załadowane - . go get ./...

Kod źródłowy pobranych bibliotek jest zapisywany w $GOPATH/pkg/mod lub do$HOME/go/pkg/mod, jeśli zmienna środowiskowa $GOPATH nie jest ustawiona.

Istnieje podejście do radzenia sobie z zależnościami zwane dostarczaniem. Moduły GO obsługują vendoring, więc jeśli określisz -mod=vendor_dir, zależności zostaną pobrane do folderuvendor_dir. Ten folder może znajdować się w repozytorium i zostać wypchnięty do repozytorium Git wraz z kodem źródłowym.

W przypadku korzystania z vendoringu zależności zostaną pobrane raz i dostarczone wraz z kodem źródłowym projektu, co pozwoli na szybsze kompilacje.

Gitlab

Gitlab zapewnia możliwość wykonywania różnych zadań po wypchnięciu do repozytorium.

Aby skorzystać z tej funkcji, należy dodać .gitlab-ci.ymlplik .

Kompilacja w Gitlabie

Musisz zdefiniować etapy i konkretne akcje, które mają być wykonywane w tych krokach. Dla każdej akcji można określić obraz platformy Docker.

Kod projektu zostanie automatycznie pobrany do folderu/builds/{project_group}/{project_name}. Oznacza to, że nie ma potrzeby pobierania go ręcznie.

W poniższym kodzie zdefiniowałem krok kompilacji i tytułową akcję w nim:

stages:
  — build
build:
  image: rhaps1071/golang-1.14-alpine-git
  stage: build
  script:
    — go get ./...
    — GOARCH=amd64 GOOS=linux go build -ldflags "-extldflags '-static'" -o $CI_PROJECT_DIR/binary
  artifacts:
    paths:
      — binary

Używany jest tutaj obraz dockera mojego autorstwa rhaps1071/golang-1.14-alpine-git.
Dodaje polecenie git do . golang:1.14-alpineTa modyfikacja jest niezbędna dla polecenia go get ./..., które ładuje zależności i używa git clone.
Obraz podstawowy jest oparty na systemie Alpine Linux, ponieważ ta dystrybucja waży tylko kilka megabajtów.
Jednak rozmiar golang:1.14-alpine waży 370 MB, co jest dużo, ale nadal jest dwukrotnym wzrostem w porównaniu z golang:1.14 (809 MB) opartym na Ubuntu.

Nie używam vendoringu, więc muszę pobrać zależności, aby skompilować. Aby to zrobić, wywołaj poleceniego get ./....

Jak powiedziałem powyżej, kod w Gitlab CI znajduje się w katalogu , który znajduje się poza $GOPATHdomeną /builds/{project_name}/{project_folder}.
Aby to zadziałało, musi istnieć plik . go.modMożesz go utworzyć za pomocą go mod init. Jeśli nie masz pliku go.mod , zespół go get ./... nie będzie w stanie określić zależności.

Jeśli Twój projekt nie korzysta z modułów GO, musisz przenieść kod źródłowy do pliku $GOPATH.
W Gitlab CI ta kopia będzie wyglądać tak:
- cp /builds/* $GOPATH/src/

Instrukcja artifacts pozwala na zapisanie dowolnego z plików lub folderów .gitlab-ci.yml do pobrania, a także do wykorzystania w kolejnych etapach Gitlab CI.

Wdrożenie SSH

Przyjrzyjmy się wdrożeniu wynikowego pliku binarnego przy użyciu SSH.

deploy_stage:
  image: kroniak/ssh-client
  stage: deploy
  environment:
    name: stage
    url: http://stage.project.com
  when: manual
  script:
    — mkdir -p ~/.ssh
    — echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa
    — chmod -R 700 ~/.ssh
    — echo "$SSH_KNOWN_HOSTS" >> ~/.ssh/known_hosts
    — chmod 644 ~/.ssh/known_hosts
    — echo "$CONFIG" > ./config.json
    — scp -P$SSH_PORT -r ./config.json $SSH_USER@$SSH_HOST:/var/www/project/config/
    — scp -P$SSH_PORT -r ./binary $SSH_USER@$SSH_HOST:~/binary_tmp
    — ssh -p$SSH_PORT $SSH_USER@$SSH_HOST 'sudo service project stop && cp ~/binary_tmp /var/www/project/binary && sudo service project restart'

Również w tym przypadku używany jest dostosowany obraz Alpine Linux — rozmiar 12,1 MBkroniak/ssh-client. Tym razem dodatkowo preinstalowany z klientem ssh, dzięki czemu ssh scp

komendy i .Logika wdrażania jest następująca:

  • Włączone są następujące zmienne Gitlab: $SSH_PRIVATE_KEY - klucz prywatny umożliwiający dostęp do serwera;
    $SSH_USER, $SSH_HOST, $SSH_PORT to login i adres serwera do wdrożenia;
    $SSH_KNOWN_HOSTS - Wpis dla pliku .ssh/known_hosts, za pomocą którego serwer jest weryfikowany.
    $CONFIG – zawartość pliku konfiguracyjnego naszego serwisu w formacie json;
  • Podczas wdrażania najpierw wypełnij wszystkie niezbędne pliki danymi ze zmiennych Gitlab;
  • Wszystkie niezbędne pliki są kopiowane na serwer za pomocą scpprogramu . Może być używany rsync, ponieważ kopiuje tylko pliki, które zostały zmienione i kopiuje je w postaci zarchiwizowanej. Jednak jeśli chodzi o 1-2 pliki, prawie nie ma wygranej.
  • Ostatnim krokiem jest zastąpienie pliku binarnego i ponowne uruchomienie naszej usługi;

Wynikowy plik .gitlab-ci.yml w całości wygląda następująco:

stages:
  — build
  — deploy
build:
  image: rhaps1071/golang-1.14-alpine-git
  stage: build
  script:
    — go get ./...
    — GOARCH=amd64 GOOS=linux go build -ldflags "-extldflags '-static'" -o $CI_PROJECT_DIR/binary
  artifacts:
    paths:
      — binary

deploy_stage:
  image: kroniak/ssh-client
  stage: deploy
  environment:
    name: stage
    url: http://stage.project.com
  when: manual
  script:
    — mkdir -p ~/.ssh
    — echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa
    — chmod -R 700 ~/.ssh
    — echo "$SSH_KNOWN_HOSTS" >> ~/.ssh/known_hosts
    — chmod 644 ~/.ssh/known_hosts
    — echo "$CONFIG" > ./config.json
    — scp -P$SSH_PORT -r ./config.json $SSH_USER@$SSH_HOST:/var/www/project/config/
    — scp -P$SSH_PORT -r ./binary $SSH_USER@$SSH_HOST:~/binary_tmp
    — ssh -p$SSH_PORT $SSH_USER@$SSH_HOST 'sudo service project stop && cp ~/binary_tmp /var/www/project/binary && sudo service project restart'

Inne artykuły

Comments

No comments yet
Yurij Finiv

Yurij Finiv

Full stack

O

Professional Fullstack Developer with extensive experience in website and desktop application development. Proficient in a wide range of tools and technologies, including Bootstrap, Tailwind, HTML5, CSS3, PUG, JavaScript, Alpine.js, jQuery, PHP, MODX, and Node.js. Skilled in website development using Symfony, MODX, and Laravel. Experience: Contributed to the development and translation of MODX3 i...

O autorze CrazyBoy49z
WORK EXPERIENCE
Kontakt
Ukraine, Lutsk
+380979856297