• Час читання ~4 хв
  • 25.03.2024

Давайте розглянемо компіляцію проекту в GO і як це працює в Gitlab CI.

Компіляція

Для збірки нам потрібно викликати go build -o binary_name.

Якщо у вашому проекті є імпорт зі сторонніх репозиторіїв, то існують зовнішні залежності. Компіляція для GO вимагатиме всього вихідного коду, включаючи код бібліотеки залежностей. Тому потрібно переконатися, що сторонні бібліотеки, які можуть не зберігатися у вашому репозиторії, також доступні для компіляції.

Постачальник або завантажити

На даний момент поточною версією є 1.14.2. Починаючи з версії GO 1.11, доступний

функціонал модуля (go modules).Модулі GO працюють таким чином, що GO сам завантажує всі сторонні бібліотеки при go runвиклику , go build або коли всі бібліотеки явно завантажені - . go get ./...

Початковий код отриманих бібліотек буде збережено до або $GOPATH/pkg/mod до, $HOME/go/pkg/modякщо змінну середовища $GOPATH не встановлено.

Існує підхід до роботи з залежностями, який називається вендорінгом. Модулі GO підтримують vendoring, так що якщо ви вкажете -mod=vendor_dir, то залежності будуть завантажені в папкуvendor_dir. Ця тека може знаходитися всередині вашого репозиторію і записуватися в репозиторій Git разом з вашим вихідним кодом.

При використанні вендорингу залежності будуть завантажені один раз і поставляються з вихідним кодом проекту, що дозволить швидше збирати.

Gitlab

Gitlab надає можливість виконання різних завдань після надсилання до репозиторію.

Щоб скористатися цим функціоналом, потрібно додати .gitlab-ci.yml.

Компіляція в Gitlab

Вам потрібно визначити етапи та конкретні дії, які будуть виконані на цих кроках. Для кожної дії ви можете вказати образ Docker.

Код вашого проекту буде автоматично завантажений в папку/builds/{project_group}/{project_name}. Це означає, що немає необхідності завантажувати його вручну.

У наведеному нижче коді я визначив крок збірки та однойменну дію в ньому:

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

Тут використано docker-образ мого авторства rhaps1071/golang-1.14-alpine-git.
Він додає команду git до файлу golang:1.14-alpine. Ця модифікація необхідна для команди go get ./..., яка завантажує залежності та використовує git clone.
Базовий образ заснований на Alpine Linux, так як важить цей дистрибутив всього кілька мегабайт.
Тим не менш, розмір golang:1.14-alpine важить 370 МБ, що багато, але все одно вдвічі більше в порівнянні з golang:1.14 (809 МБ) на базі Ubuntu.

Я не використовую vendoring, тому мені потрібно завантажити залежності для збірки. Для цього викличте командуgo get ./....

Як я вже говорив вище, код в Gitlab CI знаходиться в файлі , який знаходиться за межами $GOPATH/builds/{project_name}/{project_folder}.
Для того, щоб це спрацювало, має бути . Ви go.modможете створити його за допомогою go mod initкнопки . Якщо у вас немає файлу go.mod , команда go get ./... не зможе з'ясувати залежності.

Якщо у вашому проекті не використовуються модулі GO, вам потрібно буде перемістити вихідний код у файл $GOPATH.
У Gitlab CI ця копія виглядатиме так:
- cp /builds/* $GOPATH/src/

Інструкція Artifacts дозволяє зберегти будь-який з .gitlab-ci.yml файлів або папок для скачування, а також для використання на наступних етапах Gitlab CI.

Розгортання SSH

Давайте розглянемо розгортання отриманого двійкового файлу за допомогою 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'

Тут знову використовується кастомізований образ Alpine Linux — розміром 12,1 МБkroniak/ssh-client. Цього разу він додатково встановлений разом із клієнтом ssh, завдяки якому ssh scp

команди та .Логіка розгортання наступна:

  • Увімкнено такі змінні Gitlab: $SSH_PRIVATE_KEY - приватний ключ для доступу до сервера;
    $SSH_USER, $SSH_HOST, - $SSH_PORT логін та адреса сервера для розгортання;
    $SSH_KNOWN_HOSTS - Запис для файла .ssh/known_hosts, за допомогою якого перевіряється сервер.
    $CONFIG – вміст конфігураційного файлу нашого сервісу у форматі JSON;
  • При розгортанні спочатку заповніть всі необхідні файли даними зі змінних Gitlab;
  • Всі необхідні файли копіюються на сервер за допомогою scp. Можна використовувати rsync, оскільки він копіює лише файли, які змінилися, і копіює їх в архівному вигляді. Однак, коли справа доходить до 1-2 файлів, виграшу майже немає.
  • Останнім кроком є заміна бінарного файлу та перезапуск нашого сервісу;

Отриманий файл .gitlab-ci.yml виглядає так:

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'

Інші статті

Comments

No comments yet
Yurij Finiv

Yurij Finiv

Full stack

Про мене

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

Про автора CrazyBoy49z
WORK EXPERIENCE
Контакти
Ukraine, Lutsk
+380979856297