Если значение логического выражения истинно, то вычисляется выражение1, в противном случае вычисляется выражение2.

Пример:

count < < n == 2 ? «да» : «нет» ; //если n=2 то в консоль выводится «да» в противном случае «нет»

Оператор «switch»:

switch(‘выражение целого типа’)

case ‘значение1’ :

break;

case ‘значение2’ :

break;

case ‘значение n’:

break;

default

/*ветку default можно не описывать. Она выполняется, если ни один из вышестоящего выражения не удовлетворено*/

‘последовательность операторовn+1’;

Пример:

case 1 : cout < < «один» ; //если n=1 то выводится строка «один»
case 2 : cout < < «два» ; //если n=2 то выводится строка «два»

default : cout < < «не один и не два» ; //если n равно другому числу, то выводится строка «не один и не два»

Операторы цикла:

Оператор «while»:

while (‘логическое выражение’) //цикл с проверкой условия на верху

ОБЗОР КИТОВ ВСЕХ ДОНАТОВ REALLYWORLD В МАЙНКРАФТ!

Пример:

while ( n < 100 ) ++ n ; //Пока n меньше 100 прибавлять 1.

Оператор «do..while»:

do

while (‘логическое выражение’); //Цикл условия проверки внизу

Пример:

while ( ‘n>0’ ) ; //Пока n больше нуля повторять процедуру

Оператор «for»:

for(‘инициализация’; ‘проверка’; ‘новое_значение’)

Пример:

for ( i = 0 ; g [ i ] = 0 ; i ++ ) ; //В начале i=0 и пока g[i]!=0, к i прибавляется 1 и выполняется пустой оператор ;

Оператор «;»:

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

Пример:

for ( i = 0 ; g [ i ] = 0 ; i ++ ) ; //В начале i=0 и пока g[i]!=0, к i прибавляется 1 (оператор после оператора for() не нужен)

Массивы:

‘тип данных’ ‘имя массива’ [‘размер массива’];

Адресация к массивам:

‘имя массива’ [‘значение индекса’];

Пример:

int mas [ 255 ] ; //Описывается массив целых чисел mas размер его 255 элементов (первый элемент 0)
mas [ 5 ] = 0 ; //6 элементу массива массива mas присваивается значение 0

Константы:

‘тип’ ‘имя константы’ = ‘значение константы’; //Описание константы

Пример:

int a = 100 ,
c = 50 ; //Описываются две константы a,C. a равна 100, а c равна 50

Классы:

Объявление классов:

class ‘имя класса’

‘закрытые функции и переменные класса’;

public:

‘имя класса’(‘список параметров’); //Конструктор

~‘имя класса’(); //Деструктор

‘открытые функции и переменные класса’;

> ‘список объектов’;

Определение функции-члена:

‘тип возращаемого значения’ ‘имя класса’::‘имя функции’ (‘список параметров’)

‘тело функции’;

Определение конструктора:

‘имя класса’::‘имя класса’ (‘список параметров’)

НОВАЯ КОМАНДА в МАЙНКРАФТ 1.19 / Снапшот 22w18a

‘тело конструктора’;

Определение деструктора

‘имя класса’::~‘имя класса’ (‘список параметров’)

‘тело деструктора’;

Объявление класса:

‘имя класса’ ‘имя объекта’(‘список параметров’);

Обращение к членам класса:

‘имя класса’.‘член класса’;

‘имя класса’->‘член класса’;

Пример:

class myclass < //Класс с именем myclass
int a ; //Закрытый элемент класса
myclass ( int b ) ; //Конструктор
void set_a ( int num ) ; //Отрытые элементы класса
void myclass : : set_a ( int num ) //определение функции-члена set_a класса myclass
void myclass : : myclass ( int b ) //определение конструктора класса myclass
myclass clas1 ( 4 ) , clas2 ( 2 ) ; //Объявление классов clas1, clas2 типа класса myclass
clas1 . set_a ( 5 ) ; // Обращение к члену класса

Структуры:

struct ‘имя структуры’

‘имя структуры’(‘список параметров’);//Конструктор

~‘имя структуры’(); //Деструктор

‘открытые функции и переменные структуры’;

private:

‘закрытые функции и переменные структуры’;

> ‘список объектов’;

Определение функции-члена, конструктора, деструктора, объявление структуры, обращение к членам структуры такие же как у класса.

Встраиваемые функции:

inline ‘тип возращаемого значения’ ‘имя функции’(‘список параметров’)

‘тело функции’;

Пример:

inline int even ( int x )
return ! ( x % 2 ) ;

Встраиваемые функции в объявлении класса:

public:

‘тип возвращаемого значения’ ‘имя функции’(‘список параметров’)‘тело функции’;>

Пример:

class samp <
int devisible ( ) < return ! ( i % j ) ; >//Встраиваемая функция

Дружеские функции:

class ‘имя класса’

public:

friend ‘тип возвращаемого значения’ ‘имя функции’(‘список параметров’);

‘тип возвращаемого значения’ ‘имя функции’ (‘список параметров’);

Пример:

class myclass <
friend int istfactor ( myclass ob ) ;

ВКонтакте ( X )
Facebook ( X )

1. Точка с запятой после using namespace std не нужна;
2. В for’е то, что стоит в круглых скобках разделяется точками с запятыми, а не запятыми;
3. Для кода на любом языке всегда используй моноширинный шрифт (Courier, Courier New, Consolas, monospace), даже если этот код не выделен в отдельный абзац;
4. Там, где написано «Обращение к членам класса» используется один символ двоеточия, не верно;
5. #include без .h — это не устаревший стиль, это заголовочные файлы, пришедшие из чистого С. В C++ заголовочные файлы часто без расширения и все идентификаторы, объявленные в этих заголовочных файлах группируются в пространство имён std. А так, неплохой краткий справочник по синтаксису=)

Здравствуйте.
Большое спасибо, что вы захотели сделать мой справочник лучше, это мне очень льстит. >1. Точка с запятой после using namespace std не нужна;
К сожалению многие компиляторы с вами не согласяться. Возможно вы имели ввиду конструкцию:
namespace std

>
Тогда да, точка с зяпятой после неё дейтсвительно не нужна.
Или можете сказать название компилятора или IDE, где это работает? >2. В for’е то, что стоит в круглых скобках разделяется точками с запятыми, а не запятыми;
Да, косяк поправил. >3. Для кода на любом языке всегда используй моноширинный шрифт (Courier, Courier New, Consolas, monospace), даже если этот код не выделен в отдельный абзац;
посмотрел на Courier, стало скучнее. Лан, пусть дети привыкают. 4. Там, где написано «Обращение к членам класса» используется один символ двоеточия, не верно;
>> поменял на точку и стрелочку. >> 5. #include без .h — это не устаревший стиль, это заголовочные файлы, пришедшие из чистого С. В C++ заголовочные файлы часто без расширения и все идентификаторы, объявленные в этих заголовочных файлах группируются в пространство имён std. Убрал слова «в поздних версиях компилятора». В данное время это вызывает смущение у людей.
То, что он прешёл из C оно не отменяет «устаревший стиль», это и было «в поздних версиях компилятора». Объясню, я хотел этим сказать себе, что данный стиль объявления библиотек использовать не стоит, так как он пришёл из «прошлого» и сейчас есть механизмы намного лучше. >А так, неплохой краткий справочник по синтаксису=) И ещё раз спасибо, что обратили внимания на данную статью.

Читайте также:  Как сделать гараж в Майнкрафте механический

Ещё одна проблема:
n=2 ? str=’да’ : str=’нет’;
некорректно.
Используй следующее:
str = (n == 2 ? «да» : «нет»);
Обрати внимание, что строки-константы заключаются в двойные кавычки.
Весь тернарный оператор возвращает либо часть между символами «?» и «:», либо часть после символа «:». Возвращать результат операции присваивания является избыточным, как в твоём примере.
Сорре, что так много написал, кратко просмотрел, просто хотелось, чтобы справочник был лучше, он же вылез одним из первых в google-поисковике, а значит меньше ошибок должно быть, особенно таких критических.

Я очень люблю фидбеки. Так что извинятся вообще не стоит.
здесь был вопрос в понятности этого написания для не подготовленного человека.
здесь str = (n == 2 ? «да» : «нет»); сильно много равно рядом, и глазу не за что зацепиться решил разбавить написал:
count

Источник: coolcode.ru

Напишите плиз какие нибудь команды для игры Lineage 2(например: /unstuck это телепорт)

ДРУЗЬЯ / ИГНОР
/friendlistВыводит в чат список «друзей». Здесь указывается статус персонажей — в игре (Online) или вне игры (Offline).
/friendinvite [персонаж] Посылает указанному персонажу приглашение стать «другом». Если персонаж ответит утвердительно, то он появится в списке «друзей».
/frienddel [персонаж] Удаляет указанного персонажа из списка «друзей».
/blocklistВыводит список «игнора». От персонажей, входящих в список, не отображаются фразы в любом чате, и автоматически отменяются предложения поторговать.
/block [персонаж] Добавляет указанного игрока в список «игнора». Указанному персонажу будет отправлено сообщение об этом.
/unblock [персонаж] Удаляет указанного персонажа из списка «игнора».
/allblockВключить режим «тишины». В чате не отображаются фразы любых персонажей, и автоматически отменяются предложения поторговать от любых персонажей.
/allunblockВыключить режим «тишины».
/evaluateРекомендовать другого персонажа.

НАСТРОЕНИЕ / ОТНОШЕНИЕ
/socialnoПерсонаж мотает головой. «А Баба-Яга против! «
/socialyesПерсонаж кивает головой. «Всеми руками за! «
/socialbowПерсонаж кланяется. «Мое почтение сударыня! «
/socialunawareПерсонаж пожимает плечами. «Крылья, ноги.. . Главное — хвост! «
/socialwaitingПерсонаж разминается. «Семерых одним махом. «
/sociallaughПерсонаж смеется. «Гы, сынок, лол! «
/socialhelloПерсонаж здоровается. «Прювет, чампиены! «
/socialvictoryПерсонаж победно вскидывает оружие. «Братва, победа! «
/socialchargeПерсонаж зовет в бой. «За Родину! За Сталина! «
/socialdanceПерсонаж танцует. «I like to move it, move it!»
/socialsadПерсонаж плачет. «Птичку. *хлип* жалко! «
/socialapplauseПерсонаж апплодирует. «Ну-ка по хорошему, хлопайте в ладоши нам! «

ОБЩЕНИЕ С GM’ами
/gm [сообщение] Отправить петицию GMу. Пишите только точное описание проблемы. Простой треп будет игнорироваться и может закончиться наложением режима «молчания».
/petition [сообщение] Аналогично команде /gm.
/gmcancelУдалить отправленную петицию GMу. В случае, если проблема разрешилась.
/petitioncancel [сообщение] Аналогично команде /gmcancel.
/gmlistПосмотреть список GMов, находящихся в игре. Можно напрямую обращаться к GMам через приватное сообщение.

ПЕРЕДВИЖЕНИЕ
/locПоказывает в чате текущие координаты персонажа в формате X Y Z.
/sitПерсонаж садится.
/standПерсонаж встает.
/walkПерсонаж будет перемещаться шагом.
/runПерсонаж будет перемещаться бегом.
/pickupПерсонаж подбирает ближайший к нему предмет с земли.
/mountdismountПерсонаж садится на ездового дракона (страйдера) или слезает с него.
/unstuckПрименяйте, если персонаж застрял, не может двигаться, и у него нет Scroll of Escape. Через 5 минут он окажется в ближайшем городе.

ТОРГОВЛЯ
/trade [персонаж] Отправляет приглашение указанному персонажу начать торговлю. При согласии открывается окно обмена. Персонажи должны находиться вплотную друг к другу.
/buyОткрывает окно покупки вещей Private Buy. Можно выставить на покупку не более 3х вещей, гномы могут выставить до 5 вещей.
/vendorОткрывает окно продажи вещей Private Sell. Можно выставить на продажу не более 3х вещей, гномы могут выставить до 5 вещей.
/privatemanufactureОткрывает окно создания вещей на заказ Private Craft. Доступен только гномам. Можно выставить не более 5 рецептов.
/findprivatestore [строка] Ищет в заголовках продажи, покупки и создания вещей указанную строку и подсвечивает те заголовки, где найдена строка. Строчные и прописные буквы не различаются.
/findprivatestoreУбирает подсветку заголовков продажи, покупки и создания вещей.

СРАЖЕНИЕ
/attack [цель] Напасть на указанного монстра или персонажа (персонаж противника должен быть PK или в режиме PvP). Если цель не указана, то нападает на текущую выбранную цель.
/attackforce [цель] Принудительно напасть на указанного монстра или персонажа (персонаж противника может быть в любом режиме) . Если цель не указана, то нападает на текущую выбранную цель.
/attackstand [цель] Напасть на указанного монстр

Остальные ответы

/invite ник-добавить в группу.. (работает на любом растояние)
/friendinvite ник-добавить в друзья
|block ник-игнор
да блин их много. . посмотри на сайте ла2 любом

Источник: otvet.mail.ru

Для чего программисту Continuous Integration и с чего начинать

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

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

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

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

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

Читайте также:  Как добавить хайпиксель в Майнкрафт виндовс

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

В 1991 году Гради Буч, видимо, устал от такого безобразия, и предложил делать сборку всего проекта каждый день, чтобы выяснять несовместимости не в день релиза, а пораньше — и назвал этот подход Continuous Integration.

Действительно, компилировать программу проще, чем собирать ракету (особенно из недоделанных компонентов), так почему бы не начать это делать раз в день? В Экстремальном Программировании решили эту тему усугубить, и устраивать сборку несколько раз в день.

Что такое сборка?

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

В интерпретируемых языках типа PHP, Python и Ruby компилировать нечего. В них сборкой может являться запуск юнит-тестов, деплой веб-приложения на тестовый сервер, и прогон acceptance-тестов на этом тестовом сервере.

Итого, Continuous Integration — это практика. Назначение практики — уменьшить количество интеграционных факапов, повысить качество выпускаемого софта. Способ — запуск сборки проекта несколько раз в день.

Допускаю что Гради Буч в стародавние времена начинал практиковать CI вообще вручную, бегая по отделам своей компании, и заставляя всех давать ему дискеты с последними версиями модулей, а потом с языком наперевес все это вручную компилировал 🙂

Нам в нашем 2018 уже чуть попроще — процесс CI автоматизирован в куче систем — выбирай любую на свой вкус:

Про CI-системы

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

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

Современная разработка подразумевает что вы используете Version Control систему.
Version Control — это почти всегда git.
Git — это почти всегда GitHub или аналогичный сервис.
Best practice современной разработки — фичебранчи и пулреквесты.

CI как раз отлично вписался в историю с пулреквестами.

Вы не только видите все изменения, обсуждаете разработку конкретной фичи в одном месте, у вас тут же показывается статус соответствующей CI-сборки:

(здесь сборка провалилась — надо идти в Details, выяснять что где поломалось и чинить)

Починили, закоммитили, запушили, и процесс начинается по новой — CI-система детектит новые изменения на ветке и запускает новую сборку:

Сборка может состоять из нескольких этапов. Самые типичные — тесты, компиляция, деплой.

Естественно, CI-системе нужно объяснить что из себя представляют эти этапы.

Настройка CI-систем

Все правильные CI-системы исповедуют принцип configuration as code, когда инструкции для CI-системы — это просто еще один файл в репозитории вашего проекта. Как то так сложилось, что в большинстве систем для инструкций используется формат YAML.

Простейший файл с инструкциями для GitLab CI может выглядеть так:

test_job: script: — ls -l

Чуть более сложные инструкции (Circle СI):

version: 2 jobs: test: docker: — image: circleci/ruby:2.4-node steps: — checkout — run: rspec deploy: docker: — image: circleci/ruby:2.4-node steps: — checkout — run: cap deploy

И тут мы вспоминаем что все эти инструкции должны где-то запускаться.

Что у CI-систем под капотом

На каждый пуш в репозиторий CI-система создает виртуальную машину, внутри которой запускает ваши инструкции, забирает результаты работы, и гасит машину:

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

Некоторые CI-системы используют для этого докер, некоторые выкручиваются без него. Хинт: берите ту, что с докером 😉

(в реальности все несколько сложнее, и большинство CI-систем умеют работать в куче разных режимов, но начинать лучше с дефолтного режима — простого запуска задач внутри докер-контейнера)

Зачем это всё обычному разработчику?

  1. Чем больше аспектов разработки ты способен закрыть, тем больше твоя ценность. Если ты просто написал код, запушил, а дальше хоть трава не расти — это одно. Если ты при этом позаботился о тестах и о деплое приложения — совсем другое. Если ты это все автоматизировал в CI — третье 🙂
  2. Просто поймите, что через время CI будет такой же дефолтной штукой как и Version Control.

Ситуация №1

Два разработчика разрабатывают на разных ветках. У каждого из них тесты проходят успешно, в том числе и после мержа c мастером.

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

Сиуация №2

Команда из пятнадцати человек разрабатывает веб-приложение. У Василия на носу семейный праздник. Он отпросился у начальства уйти пораньше, не очень тщательно проверив работоспособность кода, запустил в командной строке деплой, и ушел с работы, залочив компьютер, и заодно отключив телефон — семья же важнее работы!

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

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

Читайте также:  Как нарисовать евгена бро из Майнкрафта легко

С какой CI-системы начинать

Неплохую подсказку нам дает Гитхаб:

Open source проект на GitHub скорее всего гоняет тесты в Travis CI. Вы не сможете с этим не столкнуться. Ок, берем Travis CI на заметку, но гуглить и обчитываться мануалами пока не бежим.

Если в двух словах, то исследовались текущие возможности CI-системы, потенциал для развития, и текущий размер рынка.
Кому интересна методология тестирования, читайте само исследование. Нам же интересны выводы.

В лидерах оказались:

4) CloudBees — это компания стоящая за Jenkins. Это одна из старейших CI-систем c открытым исходным кодом, и было бы странно не увидеть их в лидерах.

3) Circle CI уже во втором источнике оказался в лидерах. Значит тоже заслуживает внимания.

2) Microsoft — no comments. Огромная компания с огромным влиянием. Если вы разрабатываете софт под винду, то скорее всего у вас даже не будет стоять вопрос выбора. Если в компании куплены лицензии на майкрософтовский стек разработческих инструментов с TFS и их CI-системой, вы просто будете есть что дают, не особо смотря по сторонам

1) GitLab на первом месте. Для тех кто не следит за компанией последние несколько лет, это может оказаться полным сюрпризом. Поговорим про него поподробнее.

GitLab

Автор год работал в Гитлабе на позиции Developer Advocate, так что вы имеете полное право считать меня предвзятым и выкрутить регулятор скептичности на пару десятков процентов при прочтении следующих абзацев. Тем не менее считаю, что многие вещи про Гитлаб надо знать, а еще лучше — начинать им пользоваться.

Важно что Гитлаб отказался считать себя просто клоном Гитхаба, и в компании решили развивать Гитлаб в сторону “системы одного окна” для разработчика. Гитлаб уже сейчас способен заместить вам Гитхаб, Трелло, CI-систему, и так далее по списку. Все инструменты уже настроены и интегрированы между собой. Результат для разработчика — минимум возни с настройками.

Исходный код Гитлаба открыт, и его при желании можно бесплатно использовать на собственном сервере. Но нас в этой истории сейчас больше всего интересует облачная версия — GitLab.com и возможности которые она дает:

  • Хостинг неограниченного количества приватных проектов
  • 2000 билд-минут в месяц для работы с встроенным CI бесплатно

Короче, вы уже догадались что моя личная рекомендация — это GitLab CI. Гитлаб имеет все шансы стать the next big thing в будущем. А быть опытным специалистом по внезапно ставшей модной штуке — это быть востребованным специалистом 😉

Если не готовы покидать Гитхаб, пробуйте Circle CI или Travis CI.

На начальных стадиях знакомства с CI избегайте Jenkins и TeamCity. В этих олдскульных системах слишком много оверхеда, так что придется больше разбираться с особенностями систем, чем фигачить сам CI.

Начнете думать что Jenkins это и есть CI, а это тупо. Возможное исключение — вы джавист, скалист или котлинист, и для вас там все работает прямо из коробки.

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

C каких задач начинать

Хорошие новости в том что не обязательно сразу становиться экспертом по CI. Для начала хватит и простого “быть в теме”. Поэтому начните с чего нибудь лайтового:

  1. Например, научитесь деплоить личный сайт при пуше в мастер.
  2. Впилите проверку орфографии с помощью yaspeller для текстов на личном сайте
  3. Запустите в CI второстепенного рабочего проекта пару линтеров.

Здесь мы в это углубляться не будем. Для заинтересовавшихся — ссылки в конце статьи.

А пока посмотрим как CI используется в больших проектах, и какую мощь он может вам дать.

Что дает CI в больших проектах

В больших проектах — серьезные требования. Тут уже запуском одной-двух команд не обойдешься. Легко можно представить себе логику типа такой: 1) выполняй задачу, только при коммите в определенные ветки, 2) при успехе выполняй следующие задачи, 3) игнорируй ошибки при выполнении определённых задачи и 4) жди ручной отмашки прежде чем задеплоить всё это дело.

Мой любимый пример — сам GitLab:

Там всегда кипит работа, и можно посмотреть как работает CI прямо в режиме реального времени: https://gitlab.com/gitlab-org/gitlab-ce/pipelines

Это большой проект, и его CI-конфиг я бы не рекомендовал смотреть без предварительной подготовки.

Вместо этого лучше посмотрите на визуализацию цепочки CI-задач:

1) Такое есть далеко не во всех CI-системах. Там где это есть — это дает команде визуальное представление происходящего в CI, и я считаю это дорогого стоит.

2) Кроме этого, файл настроек CI-системы становится работающей документацией процесса Continuous Integration в команде. Любой разработчик может там что-то добавить или изменить, создав пулреквест с желаемыми изменениями.

3) Наконец, CI-система становится центральным местом, в котором можно увидеть где и когда что пошло не так при деплое или прогоне тестов.

Ну и добавьте по вкусу все эти традиционные бла-бла-бла про ускорение процесса разработки, повышение надежности, и уменьшение рисков.

Куда копать дальше

(если захотелось изучить поглубже)

1) Посмотрите скринкаст с примерами как нарулить деплой на S3 и на Heroku с помощью GitLab CI.

4) После того как освоитесь с одной CI-системой, выберите и поиграйтесь с любой другой из списка перспективных, чтобы удостовериться что принципе везде общие, и заполучить еще больше уверенности в своих силах.

Источник: habr.com