Так случается, что команда решает вынести часть проекта в open source и использовать ее как внешнюю зависимость. Как правило, это самостоятельный пакет или инструмент, лишенный какой-либо бизнес-специфики, способный принести пользу сообществу и получить дальнейшее развитие. Большинство коммерческих разработчиков имеет персональные профили на открытых платформах и поддерживает собственные портфолио, поэтому при переносе мы хотим сохранить авторство и историю коммитов. Основная сложность здесь в том, что необходимо полностью исключить всю внутреннюю корпоративную информацию: названия репозиториев и проектов, имена и имейлы сотрудников, внутренние идентификаторы тикетов и любые формулировки, отражающие задачи продукта. Важно, чтобы такая информация отсутствовала по всему дереву коммитов. Для этого мы будем пользоваться такими инструментами, как git grep,

git filter-branch и git rebase --interactive. В статье приводятся порядок шагов и общие рекомендации по оформлению открытого проекта.

Меня зовут Константин Соколов. Я из бэкенд-разработки в Positive Technologies. Люблю программировать на Go.

Итак, наш план действий:

  1. Вынести часть проекта, сохранив историю.

  2. Отредактировать сообщения коммитов.

  3. Отредактировать информацию об авторах.

  4. Убрать приватную информацию из кода.

  5. Поместить пакет в репозиторий.

  6. Оформить новый проект.

  7. Завендорить пакет в проект.

1. Вынести часть проекта

Для примера будем использовать вымышленный проект go-fructuous, из которого хотим вынести пакет jmagic.

Склонировать весь проект во временный каталог:

git clone git@example.com:group/go-fructuous.git
cd go-fructuous/ 

Пакет, который хотим вынести, находится в go-fructuous/pkg/jmagic

~/go/src/tmp/go-fructuous $ tree
.
...
├── pkg
    ...
│   ├── jmagic
│   │   ├── benchmark.md
│   │   ├── jmagic.go
│   │   └── jmagic_test.go
...

Извлечь историю и содержимое только этого каталога с дефолтной ветки:

git filter-branch --subdirectory-filter pkg/jmagic

После выполнения в go-fructuous/ останется только содержимое каталога jmagic.

~/go/src/tmp/go-fructuous $ tree
.
├── benchmark.md
├── jmagic.go
└── jmagic_test.go

Также в Git останется история только одного этого каталога.

2. Отредактировать сообщения коммитов

Сообщения коммитов могут содержать корпоративную информацию или разную продуктовую специфику, которую необходимо скрыть.

Удалить префиксы и номера тикетов из сообщений. Например, MYPROJ-12345-add-new-function --> add-new-function :

git filter-branch -f --msg-filter 'sed -e "s/MYPROJ-[[:digit:]]\+-//"'

Проверить, что в сообщениях нет упоминаний внутренних ID тикетов и присутствуют только нужные коммиты:

git log --oneline

Для лучшей визуализации информации о коммитах и авторах можно использовать утилиту gitk.

3. Отредактировать информацию об авторах

Нужно сменить корпоративные имейлы на личные, а имена авторов — на GitHub-профили.

Получить список имен и имейлов всех авторов и коммитеров:

git log --pretty="%an %ae%n%cn %ce" | sort -u

Поменять имя и имэйл одного автора и коммитера в истории коммитов:

git filter-branch -f --env-filter '
if [ "$GIT_COMMITTER_EMAIL" = "iivanov@example.com" ]
then
export GIT_COMMITTER_EMAIL="octocat@github.com"
fi
if [ "$GIT_AUTHOR_EMAIL" = "iivanov@example.com" ]
then
export GIT_AUTHOR_EMAIL="octocat@github.com"
fi
if [ "$GIT_COMMITTER_NAME" = "iivanov" ]
then
export GIT_COMMITTER_NAME="octocat"
fi
if [ "$GIT_AUTHOR_NAME" = "iivanov" ]
then
export GIT_AUTHOR_NAME="octocat"
fi
'

Чтобы заменить имена всех авторов сразу, как вариант, можно сделать отдельный скрипт и увеличить полотно условий. Есть также и другие варианты.

4. Отредактировать информацию в коде

Нужно исключить продуктовую специфику и корпоративную информацию из кода. В нашем случае в импортах и документации встречалось упоминание корпоративного репозитория. Важно отметить, что такую информацию нужно искать по всей истории, а не только в последнем коммите.

Найти все коммиты, пути файлов и номера строк, где встречается паттерн example:

git grep --ignore-case --recursive --line-number example $(git rev-list --all)

Изменения важно вдвинуть именно в коммит, в котором первоначально была добавлена чувствительная информация. Для этого нужно сделать обычный коммит с правкой, а затем использовать rebase в интерактивном режиме:

git rebase --interactive --root

Затем необходимо подвинуть коммит к целевому коммиту и пометить как fixup.

Если правку просто сделать последним коммитом, то чувствительная информация останется в истории.

Чтобы лучше понять, как работает интерактивный rebase, рекомендуем прочитать статью.

Удалить из истории файлы, которых не должно быть в open source:

git filter-branch --index-filter 'git rm -rf --cached --ignore-unmatch path_to_file'

После всех правок нужно проверить, что код рабочий и все пути актуальны для нового репозитория.

5. Поместить пакет в новый репозиторий

Создать репозиторий на GitHub. Например, github.com/octocat/jmagic.

Для текущего каталога go-fructuous переопределить user.email и user.name:

git config --local user.email octocat@github.com
git config --local user.name octocat

Создать временный remote с алиасом github:

git remote add github git@github.com:octocat/jmagic.git

Добавить в репозиторий:

git push -u github main

После успешного добавления удалить временный каталог go-fructuous/, а для дальнейших изменений склонировать проект из GitHub.

6. Оформить новый проект

Добавить README

Исчерпывающая инструкция, как создать хорошее описание вашему проекту.

Добавить бейджи

Первым принято помещать бейдж со статусом workflow. Подробнее — в инструкции.

Пример бейджа со ссылкой на документацию:

[![Go Reference](https://pkg.go.dev/badge/github.com/spf13/cobra.svg)](https://pkg.go.dev/github.com/spf13/cobra)

Пример бейджа со ссылкой на отчет с результатами статического анализа кода:

[![Go Report Card](https://goreportcard.com/badge/github.com/spf13/cobra)](https://goreportcard.com/report/github.com/spf13/cobra)

Добавить лицензию

Если коротко, то подойдет одна из следующих лицензий: BSD 3-Clause, MIT License, Apache License 2.0.

Добавить workflow

Добавить базовые шаги в workflow: линтер, сборка, тесты. Подробнее — в инструкции.

Сделать релиз

Создать тег и релиз. Подробнее — в инструкции.

Выложить документацию на pkg.go.dev

Для того чтобы документация вашего проекта появилась на pkg.go.dev, нужно запросить ее добавление:

curl https://proxy.golang.org/github.com/octocat/jmagic/@v/v1.0.0.info

Документация будет автоматически сгенерирована из README.md и комментариев в исходном коде. Подробнее — в статье на The Go Blog.

Скрипт по добавлению документации можно встроить в workflow, чтобы происходило ее принудительное обновление при релизах.

Пример:

jobs:
  build:
    - name: Publish doc
      run: |
        # Получить последний тег с версией
        export latest="$(git describe --tags `git rev-list --tags --max-count=1`)"
        # Запросить добавление документации для версии
        curl https://proxy.golang.org/github.com/octocat/jmagic/@v/$latest.info

На pkg.go.dev существует ограничение, что документация для определенной версии может быть добавлена только один раз. На последующие запросы существующая версия документации больше не будет перестроена. Чтобы отобразить изменения, нужно создать релиз с новым тегом.

Добавить настройки безопасности (опционально)

Настроить dependabot, чтобы получать оповещения об уязвимостях в пакетах зависимостей и автоматизировать обновление версий.

Настроить CodeQL. Кроме того, нужно провести статический анализ на наличие дефектов безопасности в коде. Список CWE для анализа кода на Go доступен на GitHub Docs.

7. Завендорить пакет в проекте

Вырезать каталог pkg/jmagic из проекта.

Установить пакет:

go get github.com:octocat/jmagic@v1.0.0

Импортировать пакет в коде.

Добавить зависимость в go.mod:

go mod tidy

Добавить зависимость в vendor/:

go mod vendor

Заключение

После переноса пакета мы получили самостоятельный инструмент, оформленный в виде проекта с открытым исходным кодом, с сохранением авторства и истории создания.

К плюсам открытых проектов можно отнести то, что разработчики из сообщества получают возможность вносить свой вклад в их развитие. А значит, у такого проекта больше шансов, что будет улучшено качество кода, исправлены ошибки или появится новая функциональность. Проект открыт для обзора и аудита профессионалам широкого спектра — это повышает доверие к инструменту и позволяет выявить потенциальные уязвимости безопасности.

Комментарии (0)