Правила упаковки Golang
В этом документе описаны лучшие практики упаковки пакетов Golang.
|
Предыдущая версия этих правил предполагала создание отдельных пакетов |
go2rpm
go2rpm — это инструмент, автоматизирующий многие из этих шагов. Прежде чем пытаться написать SPEC вручную, рекомендуется сначала попробовать go2rpm --name NAME --profile vendor IMPORT_PATH. go2rpm создаст spec-файл, соответствующий правилам, загрузит исходные коды upstream, создаст архив vendor с помощью go_vendor_archive из Go Vendor Tools, а затем использует go_vendor_license для сканирования исходных кодов upstream и встроенных зависимостей на наличие файлов лицензий, запросит у пользователя любые лицензии, которые не смог определить, и затем сгенерирует совокупное выражение SPDX.
Путь импорта
В Golang пакеты обозначаются полными URL-адресами, перечисленными в файле go.mod проекта.
%global goipath github.com/kr/pretty
Именование
Новые пакеты библиотек Golang больше не допускаются, поэтому все пакеты Golang являются приложениями, ориентированными на пользователя, и ДОЛЖНЫ называться в соответствии со стандартными правилами именования. В частности, пакеты Go с встроенными зависимостями НЕ ДОЛЖНЫ иметь префикс golang-, если только это не является частью имени upstream проекта.
Это также относится к существующим пакетам. При преобразовании пакета с префиксом golang-, созданного по старым правилам, для использования встроенных зависимостей пакет ДОЛЖЕН пройти процесс переименования пакета. Это правило направлено на создание чёткого разделения между пакетами, созданными по старому подходу, и новым методом со встроенными зависимостями, а также на предотвращение случаев, когда подпакеты -devel удаляются из существующих пакетов golang- и затем возвращаются в стабильные ветви.
Архитектуры языка Go
Для компиляции на различных архитектурах доступны компиляторы golang и gcc-go. Компилятор golang в настоящее время поддерживает x86, x86_64, ppc64le, ppc64 (частично, см. issue#13192 upstream), s390x, armv7hl и aarch64.
Двоичные пакеты ДОЛЖНЫ устанавливать ExclusiveArch, чтобы мы пытались собирать пакеты только на этих архитектурах. Теперь это автоматически добавляется макросом %gometa с использованием макроса %{golang_arches}. Упаковщики могут исключить %ix86 (см. Changes/EncourageI686LeafRemoval), передав -f макросу %gometa. Флаг -f указывает %gometa установить ExclusiveArch: %{golang_arches_future} вместо ExclusiveArch: %{golang_arches}. %{golang_arches_future} включает те же архитектуры, что и {golang_arches}, за исключением %ix86.
Флаги компилятора Go
Сохранение флагов компилятора
Пакеты ДОЛЖНЫ сохранять флаги компилятора golang Fedora, используя макрос %gobuild или передавая соответствующие макросы %gobuild_*flags в сборочный скрипт upstream.
# Using %gobuild
%gobuild -o %{gobuilddir}/bin/%{name} %{goipath}
# Using a simple upstream build script
%make_build BUILD_OPTS=%{gobuild_baseflags_shescaped}
# Using an upstream build script that provides separate options for ldflags
%make_build \
BUILD_OPTS=%{gobuild_baseflags_shescaped} \
GO_LDFLAGS=%{gobuild_ldflags_shescaped}
Дополнительную информацию о передаче флагов компилятора в сборочный скрипт upstream см. во встроенных комментариях в macros.go-compilers-golang.
|
Рекомендуется использовать макрос |
Передача дополнительных флагов
Go поддерживает передачу дополнительных флагов компоновщика (например, для включения функциональности --version) и тегов сборки для условной компиляции. При использовании сборочного скрипта upstream они могут устанавливаться автоматически. В противном случае упаковщик должен задать их вручную.
|
Обязательно ознакомьтесь с процессом сборки и документацией upstream, чтобы определить, какие флаги компоновщика вам может потребоваться включить для правильного кодирования версии в бинарный файл для проектов, предоставляющих флаг вроде |
Флаги компоновщика
В некоторых случаях может потребоваться передать дополнительные флаги компоновщику Go. Это можно сделать, установив переменную окружения $GO_LDFLAGS, которая затем будет прочитана макросами.
# The correct value to pass to -X differs between projects; this is an example.
export GO_LDFLAGS="-X %{goipath}/internal.Version=%{version}"
Пакеты НЕ ДОЛЖНЫ задавать флаги компоновщика Go с помощью переменной окружения $LDFLAGS. Это поддерживается для обратной совместимости, но устарело.
Теги сборки
Go поддерживает теги сборки для условного включения или исключения кода из сборки. Чтобы передать теги сборки компилятору Go, установите $GO_BUILDTAGS в список тегов, разделённых пробелами.
# These tags are just examples. Each project has its own.
export GO_BUILDTAGS="systemd selinux"
Пакеты НЕ ДОЛЖНЫ задавать теги Go с помощью переменной окружения $BUILDTAGS.
Зависимости макросов
Пакеты ДОЛЖНЫ иметь BuildRequires: go-rpm-macros, чтобы подтянуть макросы и компилятор Go.
Это автоматизировано макросом %gometa.
Пакеты, использующие макросы %go_vendor_license_*, ДОЛЖНЫ иметь BuildRequires: go-vendor-tools.
Вендоренные зависимости
Пакеты ДОЛЖНЫ включать свои зависимости Go-модулей как встроенные. Упаковщикам СЛЕДУЕТ использовать команду go_vendor_archive из Go Vendor Tools для создания воспроизводимого архива vendor. Пакеты, не использующие Go Vendor Tools, должны включать скрипт или другую стандартизированную, документированную процедуру для загрузки исходных кодов с помощью go mod vendor и воспроизводимого создания архива. Упаковщикам СЛЕДУЕТ самостоятельно пересоздавать архивы vendor, даже если upstream включает каталог vendor в свои исходные коды. Это позволяет упростить обновления безопасности с помощью Go Vendor Tools.
Традиционно Source0 в spec-файле — это основной архив, а Source1 — архив vendor, и их значения автоматически заполняются с помощью макросов forge.
Source0: %{gosource}
# %%archivename is the basename as the archive provided
# by %%gosource without the extension.
Source1: %{archivename}-vendor.tar.bz2
# go-vendor-tools configuration generated by go2rpm
Source2: go-vendor-tools.toml
Затем выполните go_vendor_archive create <PACKAGE_NAME>.spec, чтобы создать архив vendor.
Предоставления встроенных пакетов
Пакеты ДОЛЖНЫ включать bundled(golang(IMPORT_PATH)) = VERSION Provides для всех встроенных Go-модулей. Это обрабатывается автоматически генератором зависимостей. Он работает с любым файлом modules.txt в каталоге лицензий. Отметьте файл vendor/modules.txt с помощью %license в %files, и затем генератор просканирует файл и создаст bundled() Provides. vendor/modules.txt по умолчанию включён в go_vendor_license_filelist (см. Установка лицензий), поэтому большинству пакетов не потребуется делать это вручную.
# Only necessary to include explicitly when not using %%go_vendor_license_filelist
%license vendor/modules.txt
Лицензирование
Пакеты должны следовать правилам лицензирования Fedora. Для пакетов Go со встроенными зависимостями это означает, что файлы лицензий основного проекта, а также всех встроенных Go-модулей ДОЛЖНЫ быть включены в пакет и помечены %license. Каждый встроенный Go-модуль ДОЛЖЕН включать файл лицензии; Go-модули, у которых отсутствуют файлы лицензий, НЕ ДОЛЖНЫ включаться во встроенные архивы до выяснения вопросов лицензирования.
Кроме того, тег License: пакета ДОЛЖЕН включать совокупное выражение SPDX, охватывающее как основной пакет, так и встроенные Go-модули.
Лицензирование с помощью Go Vendor Tools
Go Vendor Tools предоставляет команду и макросы go_vendor_license, помогающие определить правильное выражение License: и установить файлы лицензий, как предписано в предыдущем разделе.
Упаковщики ДОЛЖНЫ выполнить go_vendor_license report (напрямую, через go2rpm или с использованием макроса %go_vendor_license_check в локальной сборке mock) и перепроверить его вывод перед загрузкой исходных кодов в lookaside-кэш. Любые ошибки ДОЛЖНЫ быть устранены. Если какая-либо часть вывода неверна, поведение go_vendor_license можно изменить в разделе лицензирования файла конфигурации Go Vendor Tools.
Этот документ описывает только стандартное использование Go Vendor Tools, необходимое для соблюдения правил — обратитесь к документации Go Vendor Tools для получения подробной информации о продвинутом использовании. Упаковщики могут следовать документации по сценариям, чтобы создать новый spec-файл с помощью go2rpm или обновить существующие spec-файлы для новых версий upstream, чтобы запустить go_vendor_license, убедиться, что лицензия действительна, и при необходимости автоматически обновить её перед запуском полной сборки.
|
Хотя Go Vendor Tools предоставляет средства для сканирования лицензий и создания выражений SPDX, ответственность за выполнение базовой проверки вывода и обеспечение соответствия правилам лицензирования Fedora, включая проверку того, что все ключи в теге License являются разрешёнными лицензиями в Fedora, по-прежнему лежит на упаковщике, прежде чем загружать какие-либо исходные коды в lookaside-кэш. При необходимости выражение лицензии для отдельных файлов можно переопределить в файле конфигурации, как описано в документации по сценариям. |
go-vendor-tools.toml
Пакеты ДОЛЖНЫ включать файл go-vendor-tools.toml для указания бэкенда детектора лицензий и других параметров конфигурации. Дополнительную информацию см. в справочнике по конфигурации. Рекомендуемый подход — использовать go2rpm, который автоматически создаёт корректный go-vendor-tools.toml. Минимальная конфигурация выглядит так:
[licensing]
detector = "askalono"
Этот файл используется макросами и традиционно включается в spec-файл как Source2:, сразу под архивом upstream и tar-архивом, созданным go_vendor_archive. В этом документе %{S:2} (разворачивается в путь к Source2) будет использоваться для обозначения пути к файлу конфигурации Go Vendor Tools.
Установка go-vendor-tools
Пакеты, использующие макросы Go Vendor Tools, ДОЛЖНЫ иметь BuildRequires: go-vendor-tools и использовать макрос %go_vendor_license_buildrequires для генерации требований, необходимых для выбранного бэкенда детектора лицензий.
BuildRequires: go-vendor-tools
%generate_buildrequires
%go_vendor_license_buildrequires -c %{S:2}
Установка лицензий
Упаковщикам СЛЕДУЕТ использовать макрос %go_vendor_license_install для установки файлов лицензий основного проекта и всех встроенных Go-модулей. По умолчанию этот макрос устанавливает файлы лицензий в каталог лицензий основного пакета. Макрос также копирует файл vendor/modules.txt в каталог лицензий, чтобы включить генератор bundled() Golang (см. Предоставления встроенных пакетов).
# Install into the main package's license directory
%go_vendor_license_install -c %{S:2}
Затем макрос заполнит %{go_vendor_license_filelist} списком файлов, которые можно передать в %files -f.
%files -f %{go_vendor_license_filelist}
Проверка лицензий
Как указано, упаковщики ДОЛЖНЫ проверять лицензии с помощью Go Vendor Tools перед загрузкой исходных кодов в lookaside-кэш. Любые ошибки, вызванные go_vendor_license, ДОЛЖНЫ быть устранены.
В качестве дополнительной меры макрос %go_vendor_license_check выполняет то же сканирование лицензий, что и команда go_vendor_license report. Пакетам СЛЕДУЕТ использовать go_vendor_license_check в %check, чтобы сборка пакета завершилась неудачей при наличии ошибок лицензирования. Go Vendor Tools сканирует исходные коды upstream и встроенные библиотеки на наличие файлов лицензий и генерирует совокупное выражение SPDX. Кроме того, макрос проверяет, что выражение в теге License пакета эквивалентно (независимо от порядка или возможного упрощения выражения) тому, что ожидает go_vendor_license report.
# Scan licenses and verify that the License tag is equivalent to what
# go_vendor_license calculates.
%go_vendor_license_check -c %{S:2}
# The macro can also compare a license expression stored in a macro with
# go_vendor_license's output.
%go_vendor_license_check -c %{S:2} %{go_licenses}
В случае отсутствия лицензий
go_vendor_license проверяет, отсутствует ли файл лицензии у какого-либо Go-модуля. Опять же, Go-модули, у которых отсутствуют файлы лицензий, НЕ ДОЛЖНЫ включаться во встроенные архивы до исправления ситуации в upstream.
В некоторых случаях go mod vendor может не загрузить файл лицензии проекта, даже если он существует для соответствующей версии в репозитории upstream. Обычно это происходит потому, что файлы лицензий имеют нестандартные имена или потому что лицензии установлены в подкаталоге вместо корня модуля. В первом случае go_vendor_archive МОЖЕТ быть настроен с помощью post_commands для загрузки файла лицензии из репозитория upstream в качестве временной меры, но упаковщики ДОЛЖНЫ сообщить об этом upstream и попросить переименовать файл лицензии в формат, поддерживаемый go mod vendor. Если файл лицензии включён в подкаталог модуля, файл следует скопировать в корневой каталог, чтобы удовлетворить средство проверки лицензий Go Vendor Tools.
Тестирование
Вам СЛЕДУЕТ запускать модульные тесты.
Некоторые тесты могут быть отключены, особенно следующие виды модульных тестов несовместимы с безопасной средой сборки, такой как mock:
-
тесты, которые вызывают удалённый сервер или API через Интернет,
-
тесты, которые пытаются перенастроить систему,
-
тесты, которые полагаются на конкретное приложение, работающее в системе, например базу данных или сервер syslog.
Если тест сломан по какой-то другой причине, вы можете отключить его таким же образом. Однако вам также СЛЕДУЕТ сообщить о проблеме в upstream. Не забудьте проследить в комментарии, почему каждая проверка была отключена, со ссылками на возможные отчёты о проблемах в upstream.
Тесты можно запускать с помощью макроса %gocheck2, который внутренне вызывает go test, сохраняя флаги сборки Fedora и предоставляя дополнительные параметры для пропуска определённых тестов.
Пакеты НЕ ДОЛЖНЫ использовать устаревший макрос %gocheck.
Режим Go-модулей
Пакетам СЛЕДУЕТ включить режим Go-модулей, включив %global gomodulesmode GO111MODULE=on в spec-файл для установки переменной окружения GO111MODULE. Обычно это определение включается в начале %build перед вызовом %gobuild.
|
Go-модули — это система, которую |
Макросы
RPM-макросы, предоставляемые go-vendor-tools, используются для проверки и установки лицензий. См. документацию по RPM-макросам Go Vendor Tools и Лицензирование с помощью Go Vendor Tools.
go-rpm-macros в первую очередь отвечает за макрос %gobuild, который вызывает go build с флагами сборки Fedora.
go-rpm-macros также предоставляет обёртки вокруг макросов Forge из пакета forge-srpm-macros, которые упрощают указание URL источника и распаковку исходных кодов для проектов Go, размещённых на распространённых программных площадках, таких как Github. Эти макросы включают %gometa, %gosource и %goprep. Упаковщики могут использовать эти макросы вместо указания источников и ручного вызова %autosetup / %setup. См. отдельную документацию и пример spec-файла в этих правилах для получения дополнительной информации.
Пример
Конфигурация go-vendor-tools
Эти записи были созданы автоматически go2rpm. Все пакеты Go ДОЛЖНЫ иметь файл go-vendor-tools.toml, зафиксированный в distgit вместе с spec-файлом.
[archive]
[licensing]
detector = "askalono"
[[licensing.licenses]]
path = "vendor/github.com/google/shlex/COPYING"
sha256sum = "cfc7749b96f63bd31c3c42b5c471bf756814053e847c10f3eb003417bc523d30"
expression = "Apache-2.0"
[[licensing.licenses]]
path = "vendor/github.com/jwalton/gchalk/LICENSE-chalk"
sha256sum = "44e453533edb9f1c037cb260c58f66f1d9b2e7823a07407cd6d04320e3925fea"
expression = "MIT"
[[licensing.licenses]]
path = "vendor/github.com/jwalton/gchalk/pkg/ansistyles/LICENSE-ansi-styles"
sha256sum = "310f4b4de77142b34acc5a58de93558fde5dea75891c7822b4086f71372ec983"
expression = "MIT"
[[licensing.licenses]]
path = "vendor/github.com/jwalton/go-supportscolor/LICENSE"
sha256sum = "892282511d65ac08025fbabcd8af330d0aa94e459d81a818251ff5a934383816"
expression = "MIT"
[[licensing.licenses]]
path = "vendor/gopkg.in/yaml.v3/LICENSE"
sha256sum = "d18f6323b71b0b768bb5e9616e36da390fbd39369a81807cca352de4e4e6aa0b"
expression = "MIT AND (MIT AND Apache-2.0)"
Spec-файл с обёртками макросов forge
Это метод по умолчанию, используемый go2rpm, и текущее соглашение для пакетов Go.
# Generated by go2rpm 1.17.1 (with extra code comments added manually)
%bcond check 1
# https://github.com/noborus/ov
%global goipath github.com/noborus/ov
Version: 0.43.0
%gometa -L -f
Name: ov
Release: %autorelease
Summary: Feature-rich terminal-based text viewer
# Generated by go-vendor-tools
License: Apache-2.0 AND BSD-3-Clause AND MIT AND MPL-2.0
URL: %{gourl}
Source0: %{gosource}
# Generated by go-vendor-tools
Source1: %{archivename}-vendor.tar.bz2
# Go Vendor Tools configuration generated by go2rpm
Source2: go-vendor-tools.toml
BuildRequires: go-vendor-tools
%description
Feature-rich terminal-based text viewer. It is a so-called terminal pager.
%prep
# Unpack upstream sources (Source0) and apply patches if they exist.
# This also creates the %%{gobuilddir} directory used to store the binary built
# during %%build.
%goprep -p1
# Unpack the vendor archive in Source1.
tar -xf %{S:1}
%generate_buildrequires
# Install license scanner dependencies.
%go_vendor_license_buildrequires -c %{S:2}
%build
# Enable Go modules mode as required by the Guidelines.
%global gomodulesmode GO111MODULE=on
# Set version in binary. The exact value to pass to -X differs by project.
export GO_LDFLAGS="-X main.Version=%{version}"
# Build the binary
%gobuild -o %{gobuilddir}/bin/ov %{goipath}
# Generate shell completions
%{gobuilddir}/bin/%{name} --completion bash > %{name}.bash
%{gobuilddir}/bin/%{name} --completion fish > %{name}.fish
%{gobuilddir}/bin/%{name} --completion zsh > %{name}.zsh
%install
# Install license files
%go_vendor_license_install -c %{S:2}
# Install binaries built during %%build
install -m 0755 -vd %{buildroot}%{_bindir}
install -m 0755 -vp %{gobuilddir}/bin/* %{buildroot}%{_bindir}/
# Install shell completions generated during %%build
install -Dpm 0644 ov.bash %{buildroot}%{bash_completions_dir}/ov
install -Dpm 0644 ov.fish %{buildroot}%{fish_completions_dir}/ov.fish
install -Dpm 0644 ov.zsh %{buildroot}%{zsh_completions_dir}/_ov
%check
# Perform license check
%go_vendor_license_check -c %{S:2}
# Run Go unit tests
%if %{with check}
%gocheck2
%endif
%files -f %{go_vendor_license_filelist}
%doc README.md
%{_bindir}/ov
%{bash_completions_dir}/ov
%{fish_completions_dir}/ov.fish
%{zsh_completions_dir}/_ov
%changelog
%autochangelog
Spec-файл с ручными определениями
Приведённый выше подход используется по умолчанию в go2rpm, но пакеты Go можно также собирать без макросов forge. Обязательно включите ручную зависимость от go-rpm-macros и соответствующий вызов ExclusiveArch.
%bcond check 1
Name: ov
Version: 0.43.0
Release: %autorelease
Summary: Feature-rich terminal-based text viewer
# Generated by go-vendor-tools
License: Apache-2.0 AND BSD-3-Clause AND MIT AND MPL-2.0
URL: https://github.com/noborus/ov
Source0: %{url}/archive/v%{version}/ov-%{version}.tar.gz
# Generated by go-vendor-tools
Source1: ov-%{version}-vendor.tar.bz2
Source2: go-vendor-tools.toml
ExclusiveArch: %{golang_arches_future}
BuildRequires: go-rpm-macros
BuildRequires: go-vendor-tools
%description
Feature-rich terminal-based text viewer. It is a so-called terminal pager.
%prep
# Unpack upstream sources (Source0) and apply patches if they exist.
%autosetup -p1
# Unpack the vendor archive in Source1.
tar -xf %{S:1}
%generate_buildrequires
# Install license scanner dependencies.
%go_vendor_license_buildrequires -c %{S:2}
%build
# Enable Go modules mode as required by the Guidelines.
%global gomodulesmode GO111MODULE=on
# Set version in binary. The exact value to pass to -X differs by project.
export GO_LDFLAGS="-X main.Version=%{version}"
# Build the binary
%gobuild -o ov .
# Generate shell completions
./ov --completion bash > ov.bash
./ov --completion fish > ov.fish
./ov --completion zsh > ov.zsh
%install
# Install license files
%go_vendor_license_install -c %{S:2}
# Install binaries built during %%build
install -Dp ./ov -t %{buildroot}%{_bindir}
# Install shell completions generated during %%build
install -Dpm 0644 ov.bash %{buildroot}%{bash_completions_dir}/ov
install -Dpm 0644 ov.fish %{buildroot}%{fish_completions_dir}/ov.fish
install -Dpm 0644 ov.zsh %{buildroot}%{zsh_completions_dir}/_ov
%check
# Perform license check
%go_vendor_license_check -c %{S:2}
# Run Go unit tests
%if %{with check}
%gocheck2
%endif
%files -f %{go_vendor_license_filelist}
%doc README.md
%{_bindir}/ov
%{bash_completions_dir}/ov
%{fish_completions_dir}/ov.fish
%{zsh_completions_dir}/_ov
%changelog
%autochangelog
Want to help? Learn how to contribute to Fedora Docs ›