Автоматическая сборка snap пакетов в CI/CD
Моей основной задаче было реализовать автоматическую сборка snap пакетов с помощью GitLab CI/CD. И так как в сети я нашел не очень много информации о том, как это сделать — я решился на написание этого поста.
Вроде бы задача кажется не такой уж и сложной со стороны, но в ней много подводных камней.
Начнем с написания snapcraft.yaml, который нужен для работы snapcraft.
name: yourSnapName
base: core22
version: '1.0'
summary: C++ application
description: The fed launch assembly container
confinement: classic
lint:
ignore:
- classic
- library
parts:
stub:
source: .
source-type: local
plugin: dump
build-packages:
- cmake
- make
- g++
- gcc
- clang
- build-essential
- qtbase5-dev
- qt5-qmake
- rapidjson-dev
- libstdc++6
override-build: |
cd /project/path/to/your/project
mkdir build
cd build
cmake .. -DCMAKE_CXX_COMPILER=/usr/bin/clang++ -DCMAKE_C_COMPILER=/usr/bin/clang -DCMAKE_INSTALL_PREFIX=/usr
cmake --build . -j12
cp -r /project/path/to/BAS/your/build/bin $CRAFT_PART_INSTALL/bin
chmod +rx /project/run.sh
chmod +rx $CRAFT_PART_INSTALL/bin
cp -r /project/run.sh $CRAFT_PART_INSTALL/bin
apps:
stub:
command: /bin/run.sh
plugs:
- network
- home
- system-observe
- hostname-control
- removable-media
Оставлю данный файл без лишних комментариев, так как полную информацию вы можете найти в документации. Хочу отметить только одно, что здесь мне не хватило функциональности обычного плагина cmake для сборки проекта. Поэтому я переопределил этап build:
override-build: |
cd /project/path/to/your/project
mkdir build
cd build
cmake .. -DCMAKE_CXX_COMPILER=/usr/bin/clang++ -DCMAKE_C_COMPILER=/usr/bin/clang -DCMAKE_INSTALL_PREFIX=/usr
cmake --build . -j12
cp -r /project/path/to/BAS/your/build/bin $CRAFT_PART_INSTALL/bin
chmod +rx /project/run.sh
chmod +rx $CRAFT_PART_INSTALL/bin
cp -r /project/run.sh $CRAFT_PART_INSTALL/bin
Файл run.sh:
#! /bin/sh
exec $SNAP/bin/$1 $2 $3
Далее мне пришлось собирать собственный docker образ для корректной работы snapcraft. Можно использовать уже готовые docker образы, но у меня на сервере были настроены proxy, что не давало возможности для скачивания и установки всех необходимых пакетов. Мой Dockerfile:
FROM ubuntu:jammy AS builder
ENV DEBIAN_FRONTEND=noninteractive
ARG ARCH
ENV http_proxy=http://<...>
ENV https_proxy=http://<...>
# Grab dependencies
RUN apt-get update
RUN apt-get dist-upgrade --yes
RUN apt-get install --yes \
curl \
jq \
squashfs-tools
# download and extract core22 (required for snapcraft to run)
RUN curl -L $(curl -H 'X-Ubuntu-Series: 16' -H "X-Ubuntu-Architecture: $ARCH" \
'https://api.snapcraft.io/api/v1/snaps/details/core22' | jq '.download_url' -r) --output core22.snap
RUN mkdir -p /snap/core22
RUN unsquashfs -d /snap/core22/current core22.snap
# download and extract snapcraft
RUN curl -L $(curl -H 'X-Ubuntu-Series: 16' -H "X-Ubuntu-Architecture: $ARCH" \
'https://api.snapcraft.io/api/v1/snaps/details/snapcraft' | jq '.download_url' -r) --output snapcraft.snap
RUN mkdir -p /snap/snapcraft
RUN unsquashfs -d /snap/snapcraft/current snapcraft.snap
# Fix Python3 installation: Make sure we use the interpreter from
# the snapcraft snap:
RUN unlink /snap/snapcraft/current/usr/bin/python3
RUN ln -s /snap/snapcraft/current/usr/bin/python3.* /snap/snapcraft/current/usr/bin/python3
RUN echo /snap/snapcraft/current/lib/python3.*/site-packages >> /snap/snapcraft/current/usr/lib/python3/dist-packages/site-packages.pth
# Create a snapcraft runner
RUN mkdir -p /snap/bin
RUN echo "#!/bin/sh" > /snap/bin/snapcraft
RUN snap_version="$(awk '/^version:/{print $2}' /snap/snapcraft/current/meta/snap.yaml | tr -d \')" && echo "export SNAP_VERSION=\"$snap_version\"" >> /snap/bin/snapcraft
RUN echo 'exec "/snap/snapcraft/current/bin/python3" -m snapcraft "$@"' >> /snap/bin/snapcraft
RUN chmod +x /snap/bin/snapcraft
# download and extract core24
RUN curl -L $(curl -H 'X-Ubuntu-Series: 16' -H "X-Ubuntu-Architecture: $ARCH" \
'https://api.snapcraft.io/api/v1/snaps/details/core24' | jq '.download_url' -r) --output core24.snap
RUN mkdir -p /snap/core24
RUN unsquashfs -d /snap/core24/current core24.snap
FROM ubuntu:noble
ENV DEBIAN_FRONTEND=noninteractive
COPY --from=builder /snap/core22 /snap/core22
COPY --from=builder /snap/core24 /snap/core24
COPY --from=builder /snap/snapcraft /snap/snapcraft
COPY --from=builder /snap/bin/snapcraft /snap/bin/snapcraft
ENV http_proxy=http://<...>
ENV https_proxy=http://<...>
# Generate locale and install dependencies.
RUN apt-get update && apt-get dist-upgrade --yes && apt-get install --yes snapd sudo locales git binutils && locale-gen en_US.UTF-8
RUN mkdir /snap/snapcraft/current/usr/share/snapcraft/keyrings \
/snap/snapcraft/current/usr/share/snapcraft/extensions \
/snap/snapcraft/current/usr/share/snapcraft/plugins \
/snap/snapcraft/current/usr/share/snapcraft/schema -p
RUN apt install --yes build-essential
# Set the proper environment.
ENV LANG="en_US.UTF-8"
ENV LANGUAGE="en_US:en"
ENV LC_ALL="en_US.UTF-8"
ENV PATH="/snap/snapcraft/current/libexec/snapcraft/:/snap/bin:$PATH"
ENV SNAPCRAFT_BUILD_ENVIRONMENT=host
ENV http_proxy=http://<...>
ENV https_proxy=http://<...>
COPY . /project
WORKDIR /project
Ну и после этих действий можно уже приступить к самого главному — настройки GitLab CI.
У меня всего будет два этапа сборки:
stages:
- build
- deploy
Первым шагов нужно собрать docker образ, о котором упоминалось выше.
build-image:
stage: build
script:
- docker login -u u -p p $CI_REGISTRY
- docker build --no-cache -t $IMAGE_TO_BUILD .
- echo Пушим образ $IMAGE_TO_BUILD
- docker push $IMAGE_TO_BUILD
После успешной сборки образа, можно приступить к сборки snap-пакета.
build-snap:
stage: build
needs: [build-image]
script:
- sh run-docker.sh
- docker cp :/project/ .
artifacts:
paths:
- /builds/your/path/
expire_in: 1 week
Для запуска контейнера использовался файл run-docker.sh:
docker stop && docker rm
docker run -e HTTP_PROXY=http://<...> -e HTTPS_PROXY=http://<...> \
-e NO_PROXY=localhost,127.0.0.1 --name= /backend_snapcraft:latest snapcraft
После успешной сборки snap-пакета мне нужно было сохранять файл на сервере в определенную папку. Для этого нужно вмонтировать нужную директорию в gitLab-runner.
Открываем файл /etc/gitlab‑runner/config.toml под root. И в разделе [runners.docker] в поле volumes вставляем [»/home/your/directory:/mnt/snaps»] . После этого выполняем команду.
gitlab-runner restart
Теперь у вашего gitlab-runner есть доступ к пользовательским папкам.
И копируем все в нужную папку на вашем сервере.
deploy:
stage: deploy
needs: [build-snap]
script:
- cp /builds/your/path/ /mnt/snaps/
only:
- main
Готово! Поставленная задача выполнена и наши snap-пакеты публикуются в нужную нам директорию.