Статьи

Как использовать функциональные флаги в непрерывной интеграции

Много было написано о преимуществах достижения истинной непрерывной интеграции (CI) в производственных системах. Этот учебник продемонстрирует простой рабочий процесс, который достигает CI. Мы будем использовать функциональные флаги и удаленную настройку, чтобы избежать необходимости использования ветвей функций в Git, а также в любых средах тестирования или промежуточных тестах. Для демонстрации этого подхода мы будем использовать два основных инструмента: Netlify и Bullet Train .

Что мы подразумеваем под CI и функциональными флагами

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

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

Почему CI такой мощный

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

Как флаги функций помогают непрерывной интеграции

Флаги функций обеспечивают дополнительный уровень уверенности при выпуске новых функций. Включив новые функции в флаг функции, разработчики и команда разработчиков могут быстро включать или отключать их функции по мере необходимости. Допустим, мы вводим новую функцию в производство, но сразу видим, что в новом коде есть ошибка из-за чего-то особенного в производственной среде, которое не было заметно в тестировании (давайте посмотрим правде в глаза, это случилось со всеми… более чем один раз).

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

План нашего образца проекта

Чтобы продемонстрировать интеграцию флагов функций и удаленного конфигурирования, мы собираемся основать нашу исходную кодовую базу на учебном пособии по React JS для игры в крестики-нолики. Это отличный учебник для изучения основ React, поэтому обязательно ознакомьтесь с ним, если вы этого еще не сделали.

Не беспокойтесь, если вы плохо знаете React или Javascript. Концепции, которые мы рассмотрим, связаны с процессом и инструментарием, а не с кодом.

Вместо того, чтобы повторять учебник с самого начала, мы начнем с того момента, когда у нас есть базовая игра в крестики-нолики.

На этом этапе мы будем использовать флаги функций и удаленную настройку, чтобы постоянно настраивать, выдвигать и развертывать новые функции. Чтобы довести эту концепцию до крайности, мы будем постоянно стремиться овладеть ею; никакие другие ветви не будут использоваться. Мы введем ошибку (намеренно, конечно!) И отправим исправление мастеру, чтобы продемонстрировать, что для работы с этим сценарием не требуется полный откат или дополнительное ветвление.

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

Достижение КИ

Наиболее распространенный метод автоматизации непрерывной интеграции — запуск процесса сборки при внесении изменений в ваш репозиторий git. Различные инструменты сборки достигают этого по-разному.

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

Чтобы использовать Netlify, просто зарегистрируйте бесплатную учетную запись и выберите параметр «Новый сайт из Git» в правом верхнем углу панели инструментов. После того как вы подключили свою учетную запись GitHub (или иным образом, если вы хотите использовать Bitbucket или GitLab), вам должны быть представлены варианты, показанные ниже.

На следующем шаге настройте Netlify для запуска приложения следующим образом.

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

Просмотр по этому URL должен показать вашу игру Tic Tac Toe во всей красе.

Настройка флагов функций для нашего проекта

Мы собираемся использовать функциональные флаги для управления объявлением победителя в игре в крестики-нолики. Для создания и управления нашими флагами функций мы собираемся использовать Bullet Train, поскольку он в настоящее время бесплатен, но есть много других продуктов с флагами функций. Мы позволим вам выбрать тот, который вы считаете правильным.

Чтобы продолжить работу с нами, создайте бесплатную учетную запись на Bullet Train. Нажмите на кнопку «Создать проект» и создайте свой проект. Мы назвали наш FF Tutorial.

Далее нам нужно создать новую функцию для объявления победителя.
Нажмите кнопку «Создать свою первую функцию» в нижней части следующего экрана, чтобы открыть следующую форму и добавить детали.

Обратите внимание, что мы сохранили функцию отключенной для начала.

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

Реализуйте флаг функции

Во-первых, давайте запустим этот проект в нашей среде разработки. В командной строке перейдите в папку проекта и выполните команду npm i

Затем запустите npm run devhttp://localhost:8080 Вы должны увидеть ту же игру в крестики-нолики, которую вы видели в URL-адресе Netlify.

Теперь мы собираемся внедрить наш новый флаг функции в существующий код. Начнем с установки клиента Bullet Train для JavaScript, открытия другой командной строки и запуска следующего в каталоге проекта:

npm i bullet-train-client --save

Откройте проект в предпочитаемом вами редакторе и отредактируйте ./web/App.js

Найдите функцию calculateWinner(squares) Эта функция определяет, был ли победитель или нет, основываясь на том, может ли он найти линию той же формы или нет. Мы собираемся, чтобы эта функция возвращала null

В самом верху App.js добавьте следующую строку:

 var declareWinner = true;

Теперь давайте инициализируем наш клиент Bullet Train, который мы установили ранее. Скопируйте весь пример кода 2 со страницы «Функции» в интерфейсе «Bullet Train» и вставьте его сразу под только что добавленной строкой.

Идентификатор среды в вашем фрагменте кода будет правильным идентификатором среды, связанным со средой разработки в проекте Bullet Train. Вы можете проверить это, перейдя на страницу «Настройки среды», если хотите.

Теперь нам нужно отредактировать onChange()bulletTrain.init() Замените весь код там одной строкой:

 declareWinner = bulletTrain.hasFeature("declare-winner");

Теперь вы должны иметь это в верхней части вашего App.js

 var declareWinner = true;
import bulletTrain from "bullet-train-client"; //Add this line if you're using bulletTrain via npm

bulletTrain.init({
    environmentID:"<your-environment-id>",
    onChange: (oldFlags,params)=>{ //Occurs whenever flags are changed
        declareWinner = bulletTrain.hasFeature("declare-winner");
    }
});

Прокрутите вниз до функции calculateWinner(squares)lines

 if (!declareWinner) return null;

Вот и все! Наш признак теперь будет определять, будет ли рассчитываться победитель или нет при каждом рендере игры. Обновите ваш браузер и играйте в игру. Вы больше не можете выиграть, и вместо этого вся доска теперь может быть заполнена X и Os.

Вернитесь к администратору Bullet Train и переключите функцию с помощью переключателя справа.

Обновите ваш браузер, и игра снова станет выигрышной. Проверьте код для конца этой части здесь .

Передайте и отправьте ваш код (да, все на главном), и Netlify автоматически развернет ваш код. Снова перейдите к назначенному URL-адресу Netlify и переключите флаг функции, чтобы увидеть, как он работает в производственной среде. Сладкий!

Работа над ошибкой

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

Особенность, которую мы собираемся добавить, — это выбор тех, кто идет первым в начале игры. Для этого мы добавим пару кнопок, которые появляются только в начале игры и не позволяют щелчкам на доске добавлять фигуры.

Во-первых, давайте установим наш флаг функции, чтобы обернуть новую функцию. В своем проекте Bullet Train создайте новую функцию под названием « select-who-goes-first Давайте оставим его отключенным для начала.

Теперь давайте добавим нашу новую функцию. В функции render() В верхней части возврата функции render()

 <div className="status">{status}</div>

… со следующим кодом:

 {!this.state.selected ? (
    <div>
        Who goes first?
        <button onClick={() => this.setState({selected: true})}>X</button>
        <button onClick={() => this.setState({selected: true, xIsNext: false})}>O</button>
    </div>
) : (
    <div className="status">{status}</div>
)}

Теперь мы хотим написать код для управления нашей новой функцией с помощью флага функции, который мы создали. Как и прежде, это нужно сделать в функции bulletTrain.init({...})

Сначала добавим функцию жизненного цикла componentDidMount()bulletTrain.init({...})

 class Board extends React.Component {
    componentDidMount() {
        bulletTrain.init({
            environmentID:"<your-environment-id>",
            onChange: (oldFlags,params)=>{ //Occurs whenever flags are changed
                declareWinner = bulletTrain.hasFeature("declare-winner");
            }
        });
    }

    // [rest of class]
}

Если бы мы оставили bulletTrain.init({...})this.setState()

Теперь давайте добавим код для управления нашей новой функцией. Мы хотим, чтобы приложение работало так, как оно делало до добавления этой функции, если флаг отключен. Чтобы сделать это, давайте установим значение состояния для selectedtrue Добавьте следующую строку в метод bulletTrain.init({...})declareWinner

 this.setState({selected: !bulletTrain.hasFeature("select-who-goes-first")});

Давайте продолжим и подтолкнем это (опять же прямо к мастеру). Как только он будет создан, перейдите на свой URL Netlify. Вы должны увидеть, что ничего не изменилось — это потому, что эта функция все еще отключена в нашем проекте Bullet Train.

Отправляйся в Bullet Train и включи эту функцию.

Brilliant! Теперь мы можем видеть, как это работает, но есть ошибка! Можно начать игру, не выбирая, кто идет первым. Если вы играете в такую ​​игру, вы можете видеть, что статус никогда не устанавливается, чтобы показать победителя. Это не правильно!

Вернитесь к Bullet Train и отключите эту функцию, пока мы не выясним, что не так. Здесь вам пригодятся дополнительные функции Bullet Train, такие как среда и пользователи. Мы не будем вдаваться в подробности этого руководства, но ознакомимся с документами для получения дополнительной информации об использовании нескольких сред или управлении функциями для каждого пользователя.

Возвращаясь к нашей ошибке: есть еще одна строка, которую нам нужно было добавить в самый верх handleClick() Добавьте следующее в верхней части функции handleClick()

 if (!this.state.selected) return;

Снова включите эту функцию в Bullet Train и проверьте ее в своей локальной среде, и вы увидите, что теперь мы запрещаем запуск игры, не выбирая, кто идет первым. Отлично! Снова закрепите это в master и вставьте прямо в развертывание.

Перейдите на свой URL-адрес Netlify, и вы увидите, что новая функция исправлена ​​и работает правильно.

Вы можете увидеть окончательный код в конце этого раздела здесь .

Удаленная настройка

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

В нашем уроке мы будем использовать это для изменения форм, используемых каждым игроком в нашей игре. Давайте создадим два значения удаленной конфигурации для того, какие фигуры использовать на доске. В своем проекте Bullet Train нажмите кнопку «Создать элемент», но на этот раз выберите вкладку «Удаленная настройка» вместо «Флаг элемента». Заполните данные в соответствии с ниже.

Все сделано! Теперь вернемся к коду. В функции onChange() Давайте изменим наш this.setState()

 this.setState({
    selected: !bulletTrain.hasFeature("select-who-goes-first"),
    shape1: bulletTrain.getValue("shape-1") || 'X',
    shape2: bulletTrain.getValue("shape-2") || 'O'
});

Теперь у нас есть две фигуры, и мы можем заменить все статическое использование в App.js Должно быть 3 экземпляра каждого: 1 на фигуру в handleClick()render()return Вот обновленный код для ссылки в handleClick()

 handleClick(i) {
    // ...
    squares[i] = this.state.xIsNext ? this.state.shape1 : this.state.shape2;
    // ...
}

Обратите внимание, что для экземпляров в returnrender()

 <button onClick={() => this.setState({selected: true})}>{this.state.shape1}</button>

Зафиксируйте это в master и отправьте в свой Git-репозиторий, чтобы увидеть изменения в вашем Netlify URL. Если вы сделали это правильно, игра должна играть как прежде с формами «X» и «O». Идите вперед и измените формы в админке на разные буквы и обновите страницу. Если все хорошо, теперь вы будете играть с разными формами.

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

Другие вещи, чтобы думать о

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

Например, если вы используете платформу, которая обрабатывает схему базы данных для вас, такую ​​как Django или Rails, вам нужно быть осторожным при реализации флагов функций в ваших моделях. Использование флагов функций в ваших моделях может привести к несоответствиям схемы БД, что может привести к отключению частей вашего приложения.

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

Наконец, мы использовали Bullet Train в учебнике выше, так как он бесплатный в данный момент, а также с открытым исходным кодом. Есть ряд других продуктов, которые делают то же самое или с немного другими вариантами — вы должны проверить все это, чтобы определить, что лучше для вас. Например, Launch Darkly и Airship HQ .