[Из песочницы] Распространение программ на Go. Часть 1
Недавно прочел достаточно неплохую статью о инсталяции программ на Go. Где был показан простой пример того как можно реализовать установку бинарника под «любую» (unix friendly) операционную систему. Решил написать более подробный цикл статей на эту тему.
Небольшое оглавление
- Сборка и деплой приложения в github releases. Часть 1
- Сборка deb/rpm пакета для golang приложения. Часть 2 (скоро)
- Размещаем свой пакет в PPA на Launchpad. Часть 3 (скоро)
Сборка и деплой приложения в github releases. Часть 1
CI/CD
В примере я буду использовать проект TinyJPG, а собирать мы его будем в Travis-ci.
Добавим к нашему проекту файл .travis.yml в котором мы будем описывать последовательность нашей сборки
language: go
go:
- tip # The latest version of Go.
install: true
env:
global:
- MYAPP=tinyjpg
- MYEMAIL=youmail@example.com
- secure: ${GH_TOKEN}
before_install:
- sudo apt-get -qq update
install:
- go get -u github.com/OrlovEvgeny/$MYAPP
- cd $GOPATH/src/github.com/OrlovEvgeny/$MYAPP
- go install
# build the app,build the package
before_deploy:
- mkdir -p build/{386,amd64}
- GOOS=linux GOARCH=386 go build --ldflags "-X main.version=${TRAVIS_TAG} -X main.build=${TRAVIS_BUILD_NUMBER} -X main.commit=${TRAVIS_COMMIT}" -o build/386/${MYAPP}-386 *.go
- GOOS=linux GOARCH=amd64 go build --ldflags "-X main.version=${TRAVIS_TAG} -X main.build=${TRAVIS_BUILD_NUMBER} -X main.commit=${TRAVIS_COMMIT}" -o build/amd64/${MYAPP}-amd64 *.go
deploy:
provider: releases
email: ${MYEMAIL}
api_key:
secure: ${GH_TOKEN}
file:
- build/386/${MYAPP}-386
- build/amd64/${MYAPP}-amd64
skip_cleanup: true
on:
tags: true
all_branches: true
Теперь подробнее о самом важном в подкате:
— ${GH_TOKEN}: не что иное как Personal access tokens, сгенерировать его можно в настройках вашего аккаунта на github в разделе Developer settings. Ни в коем случае не передавайте его в travis.yml в открытом виде. Вы можете добавить этот ключ как Environment Variables через настройки travis-ci.
— before_deploy:
- mkdir -p build/{386,amd64}
- GOOS=linux GOARCH=386 go build --ldflags "-X main.version=${TRAVIS_TAG} -X main.build=${TRAVIS_BUILD_NUMBER} -X main.commit=${TRAVIS_COMMIT}" -o build/386/${MYAPP}-386 *.go
- GOOS=linux GOARCH=amd64 go build --ldflags "-X main.version=${TRAVIS_TAG} -X main.build=${TRAVIS_BUILD_NUMBER} -X main.commit=${TRAVIS_COMMIT}" -o build/amd64/${MYAPP}-amd64 *.go
GOOS=linux — ос под которую мы собираем проект, GOARCH=386 / GOARCH=amd64 — архитектура процессора, она же x86, и x86–64. Флаг --ldflags присвоит значения глобальным переменным version, build, commit в пакете main если они были там объявлены, в нашем случае мы присвоим TRAVIS_TAG в качестве версии нашего проекта, номер сборки TRAVIS_BUILD_NUMBER, и хеш коммита TRAVIS_COMMIT из которого собрался наш проект. Такой подход очень удобен и я считаю, что его нужно использовать в каждой Вашей сборке.
— deploy:
И наконец публикация бинарников в github releases, пожалуй тут самое важное что можно отметить — это наш provider: releases, токен о котором писал чуть выше secure: ${GH_TOKEN}, и триггер tags: true, говорящий о том, что деплоить мы будем только при появлении тэга в гите, tags: true нужно для того что-бы поддерживать удобную версионность наших сборок.
И так, после окончания сборки мы получим оповещение на email о успешности/провале сборки и если все хорошо то в github.com/OrlovEvgeny/TinyJPG/releases мы увидим Assets, c двумя нашими бинарниками собранными под архитектуры i386 и amd64. И архивы Source code, с упакованными исходниками после сборки.
В данном примере я специально не вносил в .travis.yml сборку под ос OSX и Windows, дабы не раздувать статью однотипной информацией.
Возможные значения GOOS:
- linux
- windows
- freebsd
- darwin
Возможные значения GOARCH:
- 386
- amd64
- arm
В целом с linux, windows и freebsd все понятно. Darwin — это MacOS. А если хочеться скомпилировать под Android (да, так тоже можно :), то нужно выбрать GOOS=Linux и GOARCH=arm.
Install
Со сборкой покончено, что дальше? Вы можете воспользоваться примером установки из статьи
или сделать немного красивее с помощью скрипта
VERSION="$1"
PATH="$PATH:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin"
TARGET_DIR=/usr/local/bin/tinyjpg
CONF_DIR=/etc/tinyjpg
LOG_DIR=/var/log/tinyjpg
PERM="chmod +x /usr/local/bin/tinyjpg"
if [ `getconf LONG_BIT` = "32" ]; then
ARCH="386"
else
ARCH="amd64"
fi
URL="https://github.com/OrlovEvgeny/TinyJPG/releases/download/$VERSION/tinyjpg-$ARCH"
CONF_URL="https://raw.githubusercontent.com/OrlovEvgeny/TinyJPG/master/config.yml"
if [ -n "`which curl`" ]; then
download_cmd="curl -L $URL --output $TARGET_DIR"
conf_download_cmd="curl -L $CONF_URL --output $CONF_DIR/config.yml"
else
die "Failed to download TinyJPG: curl not found, plz install curl"
fi
mkdir -p $CONF_DIR $LOG_DIR
echo -n "Fetching TinyJPG from $URL: "
$download_cmd || die "Error when downloading TinyJPG from $URL"
$conf_download_cmd || die "Error when downloading config file TinyJPG from $CONF_URL"
/bin/echo -e "Install TinyJPG: \x1B[32m done \x1B[0m"
echo -n "Set permission execute TinyJPG: "
$PERM || die "Error permission execut TinyJPG from $TARGET_DIR"
/bin/echo -e "\x1B[32m done \x1B[0m"
tinyjpg -v
/bin/echo -e "\x1B[32m Finished \x1B[0m"
Скрипт можно закоммитить в проект, и запускать установку на любой ОС (читай unix friendly), с помощью одной простой команды в аргументы которой мы так-же можем передать версию программы которую мы хотим установить себе.
curl -L https://raw.githubusercontent.com/OrlovEvgeny/TinyJPG/master/tinyjpg_install.sh | sh -s - v0.0.8
Или через ansible
tasks:
- name: TinyJPG installed
sudo: yes
shell: "curl -L https://raw.githubusercontent.com/OrlovEvgeny/TinyJPG/master/tinyjpg_install.sh | sh -s - v0.0.8"
Думаю на этом завершим первую серию статей Распространения программ на Go. В следующей статье поговорим о том как можно собрать deb/rpm пакет из golang приложения. Буду рад Вашим замечаниям и предложениям по данной статье.
По теме:
Installation with Go Language can be Simpler
Travis Building a Go Project
Кросс-компиляция в Go