Автоматическая проверка хеш-суммы файлов в Gitlab CI на примере Hugo
При деплое часто приходится сравнивать хеш-суммы файлов. Например, при развёртывании Hugo сайта через Gitlab CI. Заметка не позиционируется как прямое руководство к действию, а скорее как указание на то, с чем мне пришлось столкнутся. Быть может, кому-то она послужит источником полезной информации.
Официальный пример Hugo от Gitlab Pages предлагает такой способ:
image: alpine
variables:
HUGO_VERSION: '0.23'
HUGO_SHA: 'c9cf515067f396807161466c9968f10e61f762f49d766215db37b01402ca7ca7'
before_script:
- apk update && apk add openssl ca-certificates
- wget -O ${HUGO_VERSION}.tar.gz https://github.com/spf13/hugo/releases/download/v${HUGO_VERSION}/hugo_${HUGO_VERSION}_Linux-64bit.tar.gz
- echo "${HUGO_SHA} ${HUGO_VERSION}.tar.gz" | sha256sum -c
- tar xf ${HUGO_VERSION}.tar.gz && mv hugo* /usr/bin/hugo
- hugo version
test:
script:
- hugo
except:
- master
pages:
script:
- hugo
artifacts:
paths:
- public
only:
- master
Посмотреть на этот файл можно и в Gitlab
Ничего сложного, простой типичный Gitlab CI скрипт. Но если для кого-то это представляет трудности, то кратко здесь происходит следующее: мы берём последний доступный docker-образ alpine linux, скачиваем дополнительные пакеты для корректной работы с SSL. Потом скачиваем архив Hugo с номером версии из переменной HUGO_VERSION
, затем сравниваем SHA256-сумму этого файла c SHA256-суммой из переменной HUGO_SHA
. После этого распаковываем и перемещаем файл hugo по пути /usr/bin/hugo
и вызываем команду hugo version. Так мы проверяем, что Hugo работает, а заодно и номер версии узнаем. После происходит процесс тестирования и непосредственно сам деплой.
В чём минус такого решения? Каждый раз, когда нам необходимо обновить Hugo, приходится:
- изменять номер версии в переменной
HUGO_VERSION
- вычислять хеш-сумму скачиваемого архива с HUGO в переменную
HUGO_SHA
Учитывая, что в последнее время новые мажорные билды Hugo выходят слишком уж часто (приблизительно раз в месяц), этот процесс хотелось и стоило бы упростить до одного действия. А когда за неделю вышло сразу несколько минорных исправлений с исправлением кучи багфиксов, я понял, что надо срочно автоматизировать сравнение хеш-сумм, тем более, что начиная с версии v0.20.3, к каждому билду Hugo стали генерировать дополнительный текстовый файл с хешсуммами в формате SHA-256, серьёзно упростив задачу.
Для начала набросаем краткий план действий:
- Скачиваем файл hugo_checksums.txt
- Grep’аем название нашего билда
- Отрезаем вторую часть (с названием билда), разделённую от первой знаком табуляции, оставляем только хешсумму и кладём её в переменную.
- Сравниваем хешсумму из переменной с хешсуммой самого архива Hugo.
- Удаляем файл hugo_checksums.txt
Думаю, со скачиванием и с grep всё понятно без лишних объяснений, а вот чтобы отсечь лишнее, мы воспользуемся командой cut с ключом -f со значением 1:
cut -f 1
Конкретно эта команда означает то, что мы сохраняем только кусочек строки, до первого разделителя. По-умолчанию cut
использует в качестве разделителя знак табуляции и это подходит для нашего файла hugo_checksums.txt. В случае если бы в файле использовался другой разделитель, его можно было явно задать ключом -d
. Подробнее всегда можно почитать через man cut
или в других источниках.
А вот чтобы заполучить последовательный результат выполнения нескольких команд в переменную, нужно использовать следующий синтаксис:
variable=$(command1 | command2)
Конкретно в нашем случае должно получится такое:
checksum=$(grep -i "hugo_${HUGO_VERSION}_Linux-64bit.tar.gz" hugo_checksums.txt | cut -f 1)
В итоге, в переменной checksum
будет хранится контрольная хеш-сумма нашего архива. А дальше остаётся только добавить нашу переменную в строку сравнения sha256 и удалить файл hugo_checksums.txt.
Финальная версия файла gitlab-ci.yml после всех наших изменений будет выглядеть примерно так:
image: alpine
variables:
HUGO_VERSION: '0.23'
before_script:
- apk update && apk add openssl ca-certificates
- wget https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_checksums.txt
- wget -O ${HUGO_VERSION}.tar.gz https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_${HUGO_VERSION}_Linux-64bit.tar.gz
- checksum=$(grep -i "hugo_${HUGO_VERSION}_Linux-64bit.tar.gz" hugo_checksums.txt | cut -f 1)
- echo "$checksum ${HUGO_VERSION}.tar.gz" | sha256sum -c
- rm hugo_checksums.txt
- tar xf ${HUGO_VERSION}.tar.gz && mv hugo* /usr/bin/hugo
- hugo version
test:
script:
- hugo
except:
- master
pages:
script:
- hugo
artifacts:
paths:
- public
only:
- master
Теперь достаточно изменить номер версии в файле gitlab-ci.yml и сравнение хеш-суммы произойдёт при билде автоматически. Главное, чтобы разработчики Hugo ничего не «поломали» в последующих версиях. В последнее время они частенько проворачивают подобные трюки с изменением форматов своих билдов.