Les Gitlab Pages (et Github Pages) permettent via un processus de construction d’artefact de publier un site web au travers d’un pipeline.
Un repository Debian étant simplement constitué de fichiers statiques, nous pouvons donc faire un rapprochement entre les pipelines de build et un repository Debian.
Pour réaliser notre repository Debian hébergé sur des gitlab pages nous aurons besoin:
Créer un répertoire sur votre machine et initialisez le lien avec Gitlab:
mkdir debianrepo
cd debianrepo
git init
git remote add origin git@gitlab.com:nerzhul/debianrepo.git
Dans un premier temps nous aurons besoin d’une clef GPG pour notre repository. Générez une clef:
gpg --gen-key
On va ensuite exporter la clef publique et la clef privée dans notre repository local:
gpg --export-secret-keys -a BDB31B849949AD389C76573EF02015F1E3A69CF2 > gpg-private.key
Note: exposer la clef privée dans le repository n’est pas recommandé, il est plus judicieux d’utiliser les secret variables de Gitlab pour stocker le contenu de la clef privée. Il s’agit juste de simplifier l’exercice ici
Dans les variables CI/CD de Gitlab nous allons avoir besoin de 3 variables:
GPG_KEY_ID
(type chaîne, protected, masked): l’ID de clef GPG à publierGPG_PASSPHRASE
(type chaîne, protected): la passphrase associée à la clef afin de signer le repositoryGPG_PRIVATE_KEY
(type fichier, protected): le contenu de la clef GPG privée extraite précédemment dans gpg-private.key
Le pipeline de repository s’appuie sur le fichier .gitlab-ci.yml de Gitlab. Voici le fichier que nous allons utiliser, nous le détaillerons juste après:
---
image: debian:buster
stages:
- package
- test
- pages
variables:
DEBIAN_VERSION: "buster"
ETCD_VERSION: 3.4.16
RUNDECK_VERSION: 2.9.3-1
package:etcd:
stage: package
before_script:
- find etcd -type d -exec chmod 755 {} \;
- find etcd -type f -not -name postinst -exec chmod 644 {} \;
- find etcd -type f -name postinst -exec chmod 755 {} \;
- mkdir -p build/ dist/
- apt-get -qy update > /dev/null
- apt-get -qyy install wget > /dev/null
script:
- sed -i 's/%%ETCD_VERSION%%/'${ETCD_VERSION}'/g' etcd/DEBIAN/control
- mkdir -p etcd/usr/bin/
- cd build/
- wget https://github.com/coreos/etcd/releases/download/v${ETCD_VERSION}/etcd-v${ETCD_VERSION}-linux-amd64.tar.gz
- tar xzf etcd-v${ETCD_VERSION}-linux-amd64.tar.gz
- cp etcd-v${ETCD_VERSION}-linux-amd64/etcd etcd-v${ETCD_VERSION}-linux-amd64/etcdctl ../etcd/usr/bin/
- cd ..
- dpkg-deb -b etcd/
- mv etcd.deb dist/
artifacts:
when: on_success
expire_in: 1 week
paths:
- dist/*
package:rundeck:
stage: package
before_script:
- apt-get -qy update > /dev/null
- apt-get -qyy install wget > /dev/null
- mkdir dist/
script:
- cd dist/
- wget http://dl.bintray.com/rundeck/rundeck-deb/rundeck-${RUNDECK_VERSION}-GA.deb
artifacts:
when: on_success
expire_in: 1 week
paths:
- dist/*
# This step test that the packages are installable
test:
stage: test
needs:
- package:etcd
- package:rundeck
dependencies:
- package:etcd
- package:rundeck
script:
- dpkg -i dist/*.deb
pages:
stage: pages
needs:
- package:etcd
- package:rundeck
dependencies:
- package:etcd
- package:rundeck
before_script:
- apt-get update -qy > /dev/null
- apt-get install gpg gnupg2 -qy
- apt-key adv --keyserver pool.sks-keyservers.net --recv-keys ED75B5A4483DA07C
- echo "deb http://repo.aptly.info/ squeeze main" >> /etc/apt/sources.list.d/aptly.list
- apt-get update -qy > /dev/null
- apt-get install aptly -qy
- gpg --import --no-tty --batch --yes ${GPG_PRIVATE_KEY}
- aptly repo create -distribution=buster -component=main public
- echo -e "use-agent\npinentry-mode loopback" > ~/.gnupg/gpg.conf
- echo "allow-loopback-pinentry" > ~/.gnupg/gpg-agent.conf
only:
- master
script:
- aptly repo add public ./dist/
- aptly publish repo -batch -passphrase="${GPG_PASSPHRASE}" -gpg-key="${GPG_KEY_ID}" public
- mv ~/.aptly/public .
- gpg --armor --output public/gpg.key --export ${GPG_KEY_ID}
artifacts:
paths:
- public
Notre pipeline se décompose en 3 phases:
La phase de déploiement nécessite de connaître les paquets Debian construits. Par convention les paquets Debian construits seront placés dans le répertoire dist/ qui sera transféré à la phase de déploiement des Gitlab Pages.
Nous avons ici 2 paquets différents, Etcd et Rundeck qui sont 2 outils libres. Le premier ne fournit pas de paquet Debian, le second oui.
Commençons par Rundeck, le plus simple.
package:rundeck:
stage: package
before_script:
- apt-get -qy update > /dev/null
- apt-get -qyy install wget > /dev/null
- mkdir dist/
script:
- cd dist/
- wget http://dl.bintray.com/rundeck/rundeck-deb/rundeck-${RUNDECK_VERSION}-GA.deb
artifacts:
when: on_success
expire_in: 1 week
paths:
- dist/*
Dans la section before_script, nous mettons ce qui ne concerne pas le build, ici l’installation de wget pour télécharger le paquet.
Nous nous plaçons ensuite dans le répertoire dist et téléchargeons la version de Rundeck spécifiée dans les variables du CI, plus haut.
Les artefacts intermédiaires sont ensuite sauvegardés pour 1 semaine. Pour rappel on peut télécharger les artefacts depuis l’interface de Gitlab sur chaque pipeline.
Passons maintenant au paquet etcd:
package:etcd:
stage: package
before_script:
- find etcd -type d -exec chmod 755 {} \;
- find etcd -type f -not -name postinst -exec chmod 644 {} \;
- find etcd -type f -name postinst -exec chmod 755 {} \;
- mkdir -p build/ dist/
- apt-get -qy update > /dev/null
- apt-get -qyy install wget > /dev/null
script:
- sed -i 's/%%ETCD_VERSION%%/'${ETCD_VERSION}'/g' etcd/DEBIAN/control
- mkdir -p etcd/usr/bin/
- cd build/
- wget https://github.com/coreos/etcd/releases/download/v${ETCD_VERSION}/etcd-v${ETCD_VERSION}-linux-amd64.tar.gz
- tar xzf etcd-v${ETCD_VERSION}-linux-amd64.tar.gz
- cp etcd-v${ETCD_VERSION}-linux-amd64/etcd etcd-v${ETCD_VERSION}-linux-amd64/etcdctl ../etcd/usr/bin/
- cd ..
- dpkg-deb -b etcd/
- mv etcd.deb dist/
artifacts:
when: on_success
expire_in: 1 week
paths:
- dist/*
Pour etcd nous construisons un paquet Debian depuis des binaires fournis par les développeurs. Le répertoire etcd contient l’arborescence minimale du paquet, à savoir la configuration, l’unit system et les fichiers control et postinst de Debian.
Dans l’étape before_script nous avons également besoin de wget, mais également de corriger les permissions sur le répertoire etcd du repository, le Gitlab CI changeant les droits sur les fichiers. Je n’ai pas réussi à comprendre pourquoi, celles-ci sont correctes dans git.
L’étape de build se décompose ensuite de la manière suivante:
Enfin, tout comme pour Rundeck, on archive l’artefact.
Notre dernière tâche consiste à créer le repository Debian pour l’exposer via les Gitlab Pages
pages:
stage: pages
needs:
- package:amd64
- package:arm64
dependencies:
- package:amd64
- package:arm64
before_script:
- apt-get update -qy > /dev/null
- apt-get install gpg gnupg2 -qy
- apt-key adv --keyserver pool.sks-keyservers.net --recv-keys ED75B5A4483DA07C
- echo "deb http://repo.aptly.info/ squeeze main" >> /etc/apt/sources.list.d/aptly.list
- apt-get update -qy > /dev/null
- apt-get install aptly -qy
- gpg --import --no-tty --batch --yes ${GPG_PRIVATE_KEY}
- aptly repo create -distribution=buster -component=main public
- echo -e "use-agent\npinentry-mode loopback" > ~/.gnupg/gpg.conf
- echo "allow-loopback-pinentry" > ~/.gnupg/gpg-agent.conf
only:
- master
script:
- aptly repo add public ./dist/
- aptly publish repo -batch -passphrase="${GPG_PASSPHRASE}" -gpg-key="${GPG_KEY_ID}" public
- mv ~/.aptly/public .
- gpg --armor --output public/gpg.key --export ${GPG_KEY_ID}
artifacts:
paths:
- public
when: on_success
expire_in: 1 year
L’étape du pipeline doit obligatoirement se nommer pages par convention de Gitlab et le livrable du repository doit se situer dans le répertoire public.
Nous ajoutons nos deux étapes de construction de paquets en dépendances, afin d’avoir les artefacts à disposition pour cette étape, puis nous installons aptly qui va nous permettre de construire un repository Debian facilement, et nous importons la clef GPG privées dans le trousseau du conteneur de build. sitory
Enfin nous archivons le repository pour une durée de 1 an, afin d’assurer sa pérennité dans le temps.
Vous savez désormais construire une repository Debian en ajoutant dynamiquement des paquets construits à partir d’un pipeline Gitlab. Je vous invite à consulter le repository de référence associé à cet article.