Мета-инструмент разработки: FutoIn CID

    use cases


    Сейчас мало кого удивишь инструментами управления зависимостями проекта вроде npm, composer, bundler, pip, maven, cargo и других. Их общий недостаток — невозможность управлять непосредственно средой выполнения. Такая задача решается через nvm, php-build, rvm, virtualenv, sdkman, rustup и прочие глобальные "манагеры" версий runtime, обычно написанные под Bash/Zsh.


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


    Далее разброд и шатание настегает Continuous Integration & Delivery, где ручные танцы с бубном установки инструментов и активирования конкретных версий совершенно не приветствуются, а в идеале требуется в принципе максимально абстрагироваться от используемых технологий и довести процесс до примитивных нейтральных команд: подготовить к релизу, затегить, скачать, подготовить, построить, упаковать, выложить, проверить, одобрить(подписать), выкатить.


    Тут сам собой напрашивается инструмент, унифицировано работающий поверх уже существующих технологий,
    который из себя и представляет FutoIn CID — FutoIn Continuous Integration & Delivery tool.


    Философия FutoIn CID


    1. Использовать специализированные проекты внутри, а не заменять их.
    2. Работать без конфигурации и автоматически определять используемые технологии.
    3. Избавить пользователя-разработчика от деталей установки зависимостей проекта.
    4. Работать даже на "голом" Python 2.7 и 3.x
    5. Оставлять возможность настройки CID и переопределения команд по-умолчанию.
    6. Обособленная спецификация FTN16, допускающая альтернативные реализации.
    7. Поддержка всех распространённых операционных систем и неограниченного количества инструментов разработки.
    8. Полная абстракция от конкретного инструмента и его особенностей. Лишь деление инструментов по типу применения: для сборки, для тестирования, система контроля версий, система управления релизами, среда исполнения, миграции данных и т.п.
    9. Вынужденная унификация и ограничение слишком вольных инструментов (например Subversion в плане веток и тегов).
    10. Всё состояние хранится в древовидной структуре, которая полностью отражает конфигурационные опции, среду развёртывания и динамические значения параметров командной строки.

    Базовые операции


    • cid tag — подготовить код к релизу, затегить.
    • cid prepare — получить и подготовить код к чистой сборке, установить все зависимости.
    • cid build — собрать проект.
    • cid package — подготовить бинарный артефакт.
    • cid check — запустить тесты, не требующие развёртывания.
    • cid promote — отправить бинарный артефакт в RMS или же продвинуть ранее
      загруженный в другой пул.
    • cid deploy — развернуть из бинарного артефакта, из VCS тега или же из ветки.
    • cid run — запустить проект по конфигурации "точек входа", по конкретной точке входа или же по именованной команде.
    • cid ci_buildprepare, build, package и promote в одном флаконе для выполнения на CI сервере.
    • cid tool (install|uninstall|update|test|env) — интерфейс для управления инструментами.
    • cid tool (prepare|build|check|package|migrate) — вызов стандартный операций для конкретного инструмента.
    • cid tool (list|describe) — список поддерживаемых инструментов и более подробное описание.
    • cid init — инициализация файла конфигурации futoin.json.

    Немного реальных действий


    Всё происходит на девственно чистом vagrant боксе debian/jessie64.


    1. Устанавливаем на примере APT-based дистрибутива (Debian, Ubuntu и прочие форки).


    sudo apt-get install -y python-pip
    sudo pip install futoin-cid
    # Наша импровизированная RMS
    mkdir -p ~/Releases/Builds ~/Releases/Prod

    2. Настройка sudo


    В целях нахождения баланса между паранойей и удобством предлагается разрешить только установку пакетов без пароля. Подробнее в README.


    Для некоторых случаев Docker и JRE/JDK от Zulu требуется возможность устанавливать ключи для проверки подписи и дополнительные репозитории. Если есть опасения в рамках sudo, то это не так уж сложно сделать и руками, т.к. все исполняемые команды выводятся.


    В случае Vagrant'а нам можно всё по умолчанию.


    3. Попробуем собрать какой-нибудь HelloWorld.


    cid ci_build master Builds --vcsRepo=git:https://github.com/laravel/quickstart-basic.git --rmsRepo=scp:${HOME}/Releases

    ci_build_1
    много буковок
    ci_build_2


    А теперь посмотрим, что же вышло.


    tar tJf ~/Releases/Builds/laravel-CI-*.txz --exclude="*/*/*"

    ./
    ./composer.json
    ./storage/
    ./vendor/
    ./resources/
    ./.package.checksums
    ./LICENSE.txt
    ./composer.lock
    ./database/
    ./.env.example
    ./.env
    ./LICENSE.txt.gz
    ./node_modules/
    ./artisan
    ./.gitattributes
    ./phpunit.xml
    ./tests/
    ./gulpfile.js
    ./app/
    ./gulpfile.js.gz
    ./config/
    ./package.json
    ./public/
    ./server.php
    ./composer.json.gz
    ./readme.md
    ./package.json.gz
    ./bootstrap/
    

    Мы видим полноценный бинарный артефакт, готовый для развёртывания. По умолчанию, CID также сделает GZIP версии найденных .js, .json, .css, .svg и *.txt файлов для использования вместе с модулем gzip_static в nginx.


    В качестве импровизированного манифеста создаётся файл .package.checksums с хешами SHA-512.


    Примечание: упаковка корня проекта лишь стандартное действие в отсутствии иной реализации. Например, maven или puppet сами создают артефакты


    4. Развёртываем с RMS


    cid deploy Builds --rmsRepo=scp:${HOME}/Releases --deployDir=deploy

    cid deploy rms


    Примечание: по умолчанию CID сам находит наиболее поздний артефакт в выбранном пуле для развёртывания, если явно не указывать название. То же относится к тегам.


    Разумеется, для развёртывания на одной машине не очень серьёзного проекта такой шаг возможно пропустить и разворачивать прямо с VCS тега.


    5. Развёртываем прямо с VCS


    Ввиду отсутствия тегов в примере, будем использовать живую ветку проекта.


    cid deploy vcsref master --vcsRepo=git:https://github.com/laravel/quickstart-basic.git  --deployDir=deploy

    cid deploy vcs 1
    много буковок
    cid deploy vcs 3


    Повторим без изменений ветки и получим предупреждение об уже развёрнутой ревизии. С тегами и артефактами будет то же самое.


    cid deploy vcsref master --vcsRepo=git:https://github.com/laravel/quickstart-basic.git  --deployDir=deploy

    cid deploy vcs 3


    Пример подготовки кода проекта к релизу


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


    cid tag master 1.0.0

    Релиз следующей инкрементальной версии, не имея локальной копии на момент вызова.


    cid tag master --vcsRepo=git:user@somehost:project.git

    Стандартные действия: синхронизация с удалённым репозиторием, обновление всех возможных файлов метаданных, коммит, создание тега. Пример релиза самого CID:
    cid tag


    Проект может использовать дополнительные плагины. Например, CID обновляет версию в исходном коде и в CHANGELOG.


    Работаем с отдельными инструментами


    rubyVer=2.3 cid tool exec ruby -- -e 'puts "Hello World!"'

    cid tool exec ruby


    Если инструмент ещё не установлен, то будут сделаны все необходимые операции. В данном случае установлен RVM, а потом уже и актуальный Ruby 2.3.*. При этом RVM не будет грузиться при запуске шелла и стандартные переменные окружения не будут загрязнены.


    Информация об инструменте


    cid tool describe maven

    cid tool describe maven


    Чуток технических деталей


    Файл futoin.json


    По аналогии с небезызвестными package.json, composer.json, Cargo.toml и прочими представляет из себя описание проекта, если располагается в его корне. В нём допускается задавать общие настройки проекта, но наличие файла не является обязательным.


    При запуске, CID ищет возможные настройки среды развёртывания в корневой папке развёртывания — позволяет задать и настройки проекта, и настройки окружения (узел .env), а в домашней папке активного пользователя и в /etc/futoin/futoin.json — только узел .env.


    Примечание: узел .env не является аналогом и не заменяет "dotenv" файлы.


    Более подробно допустимые значения документированы в FTN16.


    Самые интересные узлы:


    • actions — позволяет переопределить или дополнить стандартные операции tag/prepare/build/package/check.
    • plugins — позволяет добавить дополнительные инструменты.
    • tools — позволяет жёстко указать список используемых инструментов и опционально их версии.
      • Версия '*' и true — требует версию по умолчанию
      • Иначе, версия попадает прямо в переменную среды {tool}Ver и доступна в плагинах как узел .env.{tool}Ver глобального состояния.
    • toolTune — возможность специфичной тонкой настройки каждого инструмента. Детали доступны в cid tool describe {tool}.
    • entryPoints — указание именованных точек входа.
    • persistent — список read-write путей в проекте. Специфично для веба.

    Пример файла futoin.json в корне проекта:


    {
        "name": "example-package",
        "version": "0.4.2",
        "actions": {
            "package": []
        },
        "plugins": {
            "examplerelease": "some.project.specific.release",
            "examplehelper": "some.other.helpertool"
        },
        "vcs": "git",
        "tools": {
            "examplerelease": true,
            "python": "*",
            "node": "stable",
            "gradle": "*"
        },
        "toolTune" : {
            "gradle": {
                "package": "jar"
            }
        },
        "rms": "scp",
        "rmsRepo": "rms@somehost",
        "rmsPool": "ReleaseBuilds",
        "entryPoints": {
            "app": {
                "tool": "python",
                "path": "app.py",
                "tune": {}
            }
        }
    }

    Нюансы развёртывания


    • {.deployDir} — наша условная корневая папка для развёртывания конкретного проекта.
    • {.deployDir}/persistent — область хранения read-write файлов. В кластере подразумевается область сетевой файловой системы.
    • {.deployDir}/current — символическая ссылка на актуальную версию.
    • {.deployDir}/{version_dir} — конечное размещение конкретной версии:
      • {artifact} — название пакета из RMS без расширения,
      • {vcsref}_{vcsrevision} — в случае развёртывания из ветки,
      • {vcstag} — в случае развёртывания из тега.
    • {.deployDir}/{version_dir}.tmp — временная папка в обработке.
    • {.deployDir}/{version_dir}.{ext} — не распакованный бинарный артефакт в режиме rms.
    • {.deployDir}/vcs — локальная копия репозитория в режиме vcsref и vcstag.
    • {.deployDir}/.futoin-deploy.lock — файл блокировки, а также фича безопасности от непреднамеренной зачистки неправильно указанной целевой папки.
    • всё остальное зачищается.

    Немного о кишках для добавления инструментов


    Все инструменты делятся на несколько типов. Один инструмент может сразу относится к нескольким. В перспективе, их может стать больше.


    • SubTool — база, интерфейс авто-определения, определения зависимостей, установки, обновления, удаления.
    • BuildTool — база для инструментов сборки (prepare, build, package).
    • MigrationTool — база для инструментов миграции (migrate).
    • RmsTool — база для RMS (promote) и внутренний API.
    • RunEnvTool — база для version manager'ов (nvm, rvm, gvm и т.п.).
    • RuntimeTool — база для инструментов запуска (run). Сюда входят: java, python, ruby и т.д.
    • TestTool — база для инструментов, поддерживающих тестирование (check).
    • VcsTool — база для VCS (tag) и внутренний API

    Для вспомогательных нужд существует набор mixin'ов, часть из которых уже включена в SubTool.


    Что есть на данный момент?


    Поддерживаются практически все распространённые дистрибутивы Linux: от CentOS и Debian до ArchLinux и Gentoo.


    Добавлена экспериментальная поддержка macOS. Нет подходящего оборудования — помощь в тестировании крайне приветствуется.


    В качеству proof-of-concept поддерживаются самые различные языки программирования и сопутствующие инструменты: от PHP, Python и Ruby до Go, Rust и Scala. Возможность по расширению и добавлению кастомных плагинов почти неограниченна.


    Также поддерживаются три разных VCS: Git, Mercurial и Subversion.


    Чего ещё нет?


    Поддержка RMS реализована принципиально. Для целей тестирования пока работает только scp, но основной прицел на Archiva, Artifactory и Nexus.


    Поддержка unit test'ов полагается на инструменты сборки проектов (make, gradle, grunt и т.д.), а вот сбор результатов пока не определён. Рекомендации также приветствуются.


    Процесс криптографического подписывания пока не определён. Требуется проанализировать и найти общий знаменатель для use case'ов.


    В случае необходимости поддержка *BSD предположительно потребует минимальных усилий, а вот поддержка Windows с упором на .Net скорее потребует альтернативную специализированную реализацию.


    Интерфейс для миграции данных предусмотрен, но пока не имеет стандартной реализации.


    Подытожим


    Движимая ленью, патологическим неприятием монотонной возни и страстью к автоматизации, родилась обобщающая концепция для практически всех возможных технологий. К ней добавилась реализация в виде конкретного инструмента FutoIn CID. Безусловно требуется серьёзная шлифовка и обкатка на практике. Помимо упрощения жизни разработчика, дальним прицелом является автоматизация инфраструктуры DevOps.


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


    Ссылки на проект:


    GitHub
    Python Package Index
    FTN16 Draft

    Share post

    Comments 3

      0
      На первый взгляд кажется, что от CI инструментов вроде TeamCity ваш отличается только тем, что может по выданному ему репозиторию сам определить необходимые действия сборки и деплоя без какой-либо конфигурации. Но ведь это до первой технологии, которая будет неизвестна вашему мета-сборщику. Может я что-то пропустил или вообще не понял концепции? Объясните, пожалуйста.
        0

        Из того, что возможно почерпнуть из документации TeamCity не особо похоже уже с самого начала:


        Make sure to have Ruby interpreter...

        Разумеется, тут не машинное обучение и требуется создавать плагины для каждой поддерживаемой технологии. В большинстве случаев эти плагины умещаются в 20-30 строк кода.


        Во-вторых, CI-сервер это один из кейсов. В первую очередь инструмент предназначен для рабочей среды разработчика, потом для CI сервера и частично для CD,

        0

        del

        Only users with full accounts can post comments. Log in, please.