company_banner

Большое интервью с создателем Jenkins, Kohsuke Kawaguchi

    Пользуетесь ли вы Jenkins? Скорей всего да, потому что это самый популярный на сегодняшний день проект этого класса. Мне всегда интересно было пообщаться с кем-нибудь из разработчиков и задать пару жестких вопросов. Здесь же у нас не просто разработчик, а сам создатель Jenkins — Коске Кавагучи (Kohsuke Kawaguchi).


    Как известно, Jenkins — это открытый проект с лицензией MIT. Совсем недавно прошла конференция FOSDEM — самая большая в мире конференция, посвященная свободному программному обеспечению. Бесплатная, открытая, с десятками спикеров со всех уголков мира. Это значит, что там можно встретить кого угодно — даже создателя Jenkins. Небольшим составом друзей и коллег по JUG.ru Group мы устроили туда внезапный десант и смогли записать с создателем Дженкинса хорошее интервью.


    Итак, в нашей виртуальной студии Коске Кавагучи (который представится и всё подробно расскажет чуть ниже), Руслан Ахметзянов ARG89 из JUG.ru Group и Кирилл Толкачёв tolkkv из ЦИАН, наш неизменный докладчик, гуру Groovy, Gradle, Spring и стека технологий Netflix, которого вы можете знать по подкасту «Разбор Полётов».



    Руслан: Здравствуйте. Для начала расскажите нам немного о себе и о Jenkins?


    Коске: Меня зовут Коске, в основном я известен как создатель Jenkins и технический директор CloudBees. Jenkins — это инструмент, при помощи которого разработчики автоматизируют различные этапы процесса поставки софта. Я лично знаю нескольких программистов из России, которые пользуются Jenkins, и буду рад возможности познакомиться с другими.


    Кирилл: Тоже представлюсь — я разработчик и также организую Moscow Jenkins Area Meetup (JAM). Имею богатый опыт использования Jenkins, особенно Scripted/Declarative Pipeline. Можете рассказать, чем занимается CTO компании, развивающей Jenkins?


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


    Вы также спросили, какую функцию выполняет технический директор. Дело в том, что эта функция эволюционировала по мере роста компании. Поначалу я был чем-то наподобие ведущего программиста и выполнял много технической работы. Но по мере того, как компания развивалась, эту работу постепенно начинали делать другие люди. Например, Pipeline стала заниматься отдельная команда. Я периодически с ними общаюсь, чтобы иметь представление о том, чем они заняты, иногда даю советы. Но все решения, связанные с проектированием и разработкой, они принимают самостоятельно. В целом, эта эволюция моей роли была очень интересной, мне постоянно приходится приспосабливаться.


    Кирилл: Если я правильно вас понял, то ваш фокус переключился с технических вопросов к работе с сообществом?


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


    Кирилл: А сколько лет назад начался этот уход от технической работы в сторону организационной? Можете рассказать историю Jenkins и о том, как ваша роль менялась по мере роста проекта?


    Коске: Проект появился в 2004 году, и поначалу я занимался им вечерами и по выходным, то есть это было своего рода хобби. Но постепенно проект рос. Я потратил довольно много времени на создание этой платформы, на которой другие люди могли бы писать свои приложения. Со временем возникла экосистема и сообщество разработчиков, некоторые из которых были из России — например, Олег Ненашев (Twitter: @oleg_nenashev), написавший очень интересную подсистему поверх Jenkins. По мере того, как проект набирал популярность, более острой становилась необходимость в улучшении взаимодействия с пользователями и обучении их. Поэтому я стал больше заниматься этими вещами. Наконец, где-то в 2010 году Jenkins стал настолько популярен, что я решил посвятить ему всё своё время и создал компанию. С этого момента к работе с сообществом добавилась работа по организации компании. Компания росла, и я начал задавать себе вопрос — какую деятельность не может выполнять никто, кроме меня? И в компании, и в сообществе очень много способных людей, которые с радостью готовы взять на себя дополнительную ответственность. Постепенно они стали делать многое из того, что я раньше делал сам. Так, в общем и целом, выглядел наш путь.


    Кирилл: Спасибо. Сегодня Jenkins — самая популярная система CI. А насколько распространена коммерческая версия Jenkins по сравнению с другими коммерческими системами CI? Например, с Travis Enterprise или с системами, которые могут работать локально?


    Коске: Опенсорсный Jenkins — крупный проект, у него очень много пользователей. У CloudBees значительно меньший масштаб. Поэтому если нам удастся превратить даже один процент пользовательской базы Jenkins в пользователей CloudBees — это будет очень крупный результат. По этому принципу работают все компании, основанные на опенсорсных продуктах. Другой важный вопрос — насколько нам удаётся помочь людям, проблемы которых должен решать наш продукт. Мы подсчитываем, насколько эффективна наша техническая поддержка, и, если я правильно помню статистику, в целом наши услуги их удовлетворяют.


    Кирилл: Вы имеете в виду тех, кто пользуется платной версией? Или тех, у кого бесплатная, тоже?


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


    Кирилл: То есть вы выполняете роль посредника между разработчиками и вашими пользователями, опенсорсными и коммерческими. Я правильно понимаю, что на вас также лежат задачи продуктового видения?


    Коске: Это не совсем верно, у нас есть отдельная продуктовая команда. Я не представитель пользователя, но у меня постоянно проходят встречи со многими людьми, пользователями и не только, то есть я поддерживаю связь с сообществом. Например, у меня есть рубрика «Сводки с передовой» для других сотрудников компании. В этих постах я рассказываю, как наши пользователи пишут софт и что это значит для Jenkins. Так я пытаюсь повлиять на решения, которые принимает продуктовая команда.


    Кирилл: Судя по всему, вы играете важную роль в компании. Давайте перейдём к более личным вопросам. Какая фича в Jenkins ваша любимая, о которой вы могли бы рассказывать с утра до вечера?


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


    Кирилл: Тогда, возможно, вы помните какую-нибудь фичу, которую реализовали годы назад и которой были очень горды?


    Коске: Я могу рассказать об одной из недавних значимых фич, над которыми мы работали — думаю, пользователям это будет более интересно. Это проект прошлого года, Jenkins Configuration as Code. Мы видели, что наши пользователи постепенно переходили от управления Jenkins щелчками мыши в GUI к настройке посредством файла конфигурации в git-репозитории. Нужда в проекте Configuration as Code чувствовалась давно, и было написано много временных костылей для выполнения этой функции. Но ни одно из этих начинаний не было достаточно масштабным. Наконец, нам удалось собрать вместе тех людей из сообщества, которые были заинтересованы в этом новом проекте, и создать достаточно крупный и продуманный инструмент. Многие аспекты этого проекта получились очень хорошо, и он обрёл достаточно широкую популярность, что не может не радовать.


    Можно вспомнить и другой проект, Jenkins X, который представляет из себя эволюцию в совершенно другом направлении. Он был создан специально для работы с Kubernetes. Благодаря этой специализации мы можем добиться гладкой интеграции и скрыть сложность, возникающую из-за интеграции и из-за подключения процессов непрерывной доставки. В итоге мы позволяем с лёгкостью реализовывать лучшие, на наш взгляд, практики. Я думаю, что благодаря этому проекту Jenkins станет доступен большому количеству людей, которые выполняют вполне стандартные действия и не хотят тратить много времени на конфигурацию, которым нужно, чтобы всё просто заработало.


    Руслан: Пользуетесь ли вы Jenkins, когда пишете Jenkins?


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


    Кирилл: Вы упомянули Jenkins X. Сам Jenkins похож на швейцарский нож, с плагинами он может всё. А вот Jenkins X, наоборот, узкоспециализированный, он существует для Pipeline и работы с Kubernetes. Какой именно технической стратегии придерживаетесь вы и ваша компания? Поддерживаете ли вы только Jenkins и Jenkins X? Или, помимо этого, будет ещё Jenkins X X для кластеров Mesos, Jenkins X X X для Cloud Foundry и так далее?


    Коске: Думаю, здесь многое зависит от реакции сообщества. Иметь универсальную платформу, безусловно, очень важно. Вопрос в том, кто именно реализует эту гибкость. Сегодня пользователи, как правило, имеют прямой доступ к ней. Это удобно, если вы крупная компания и делаете нечто необычное. Но при этом я знаю много людей, которым такая гибкость не нужна. Представьте, что вы пришли в столовую и попросили, чтобы вам сделали бутерброд. Вам предлагают на выбор семь видов хлеба, пять видов масла, четыре вида сыра, и вам нужно определиться со всеми ингредиентами. Но вам не нужен весь этот выбор, вам просто нужен вкусный бутерброд, и вы не хотите разбираться в том, как его правильно сделать. Я знаю, что многие именно так относятся к Jenkins и хотят, чтобы вся гибкость осталась на нашей стороне. Jenkins X — первый серьёзный шаг в этом направлении. Если этот проект будет продолжать пользоваться успехом, я с радостью попробовал бы сделать нечто подобное для встроенного ПО и IoT, мобильных платформ или машинного обучения. Думаю, есть много вертикальных рынков, на которых людям просто нужен инструмент, который позволит быстрее довести продукт до продакшна. Вы из России, так что, скорее всего, знаете про JetBrains?


    Кирилл: Конечно.


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


    Кирилл: В течение многих лет я наблюдаю одну и ту же картину во многих сообществах, когда советую использовать те или иные плагины — кстати, сейчас мне сильно помогает https://plugins.jenkins.io, там лежат все одобренные плагины. Проблема в том, что люди пытаются для всех случаев использовать один универсальный инструмент, который зачастую не подходит для конкретного случая. Поэтому теперь я обычно рекомендую только один инструмент — Pipeline, это идеальный инструмент, который подходит во всех ситуациях. Но возникает новая проблема. Люди пытаются использовать Scripted Pipeline или Declarative Pipeline, не понимая, как они устроены внутри. Возникают неполадки с инфраструктурой, с установлением соответствия между узлами, расшариванием данных, появляется необычный трафик между агентом и мастером или проблемы с масштабированием на мастере. Какой инструмент, с вашей точки зрения, лучше: тот, который указывает единственно правильный путь решения проблемы, наподобие Jenkins X? Или инструмент вроде Scripted Pipeline, который спрашивает вас, что именно вы имели в виду?


    Коске: Не уверен, что правильно вас понял, но попробую ответить. В японском языке есть слово «ката», я не знаю, как точно его перевести. Оно используется, помимо прочего, в дзюдо. Речь идёт о строго определённых движениях, которые разучивают ученики: например, поднимать руку определённым образом, чтобы отклонить определённый удар. Я немного занимался этим, поэтому знаю самые простые из них. Задача в том, чтобы заучить набор простых движений, своего рода шаблонов или лучших практик. Но это только начало. Зная эту базу, вы дальше можете правильно от неё уходить, если этого требует ситуация, при этом не нарушая самих базовых движений. Вы изучаете своё собственное пространство, свою территорию, но при этом знание общей базы вам всё равно помогает. Если вы её не знаете, вы будете всё время спрашивать себя — правильно ли я поступаю? Даже если то, что вы написали, работает, у вас всё равно будут сомнения.


    В общем, ваш вопрос напомнил мне о ката. Мне кажется, с Jenkins у нас похожая ситуация. Jenkins X предоставляет базу, а по мере того, как вы начинаете глубже в ней разбираться, вы можете при необходимости уходить от неё при помощи плагинов и прочего. Конечно, в Jenkins X приходится жертвовать гибкостью ради того, чтобы обеспечить лучшее взаимодействие с Kubernetes. Но тот факт, что Jenkins X подталкивает вас к лучшим практикам, не значит, что вас лишают выбора. По большому счёту, это верно по отношению к любому софту. Просто с Jenkins X у нас произошла важная смена образа мышления. Раньше мы создавали только ключевые элементы системы — платформу и плагины, собрать их уже было дело пользователя. С Jenkins X сообщество перешло к новому подходу, и, на мой взгляд, это очень важный шаг.


    Кирилл: Если вы не против, у меня будет ещё два вопроса. Какая фича принесла вам больше всего неприятностей за последний год? У каждого проекта бывают тяжёлые периоды — можете рассказать, как они выглядели у вас?


    Коске: Мы действительно несколько раз серьёзно попортили себе жизнь. Проблема в том, что по мере роста Jenkins наш проект стал привлекать всё больше внимания других компаний и их команд безопасности, которые стали искать дыры в Jenkins. Поэтому количество приходящих к нам извне отчётов об уязвимостях стало расти по экспоненте. Иногда от этого становилось немного страшно, в особенности если учесть, что некоторые из этих запросов приходили с дедлайном, до которого нам нужно было закрыть уязвимость. Это было в особенности тяжело, когда речь шла о фичах, созданных сообществом. Кроме того, при установлении обновлений с устранёнными уязвимостями у пользователей иногда нарушается работа. Мы прилагаем все усилия, чтобы этого не происходило, потому что иначе пользователи будут бояться устанавливать обновления безопасности, а это крайне нежелательно.


    Кирилл: Есть ли у вас некоторый управляющий орган, который решает, какие фичи будут входить в релиз? Расскажите пожалуйста, как принимаются такие решения и могут ли пользователи попросить включить в релиз некоторую фичи? Если могут, то кому отдаётся приоритет — пользователям CouldBees или опенсорсного Jenkins? Наконец, если можно, расскажите нам о своих планах на ближайшие полгода-год.


    Коске: Тут есть достаточно интересный момент: CloudBees не является владельцем Jenkins, это два отдельных проекта, каждый со своей структурой принятия решений. CloudBees — просто крупнейший участник Jenkins, многие сотрудники CloudBees параллельно работают в сообществе. Последние несколько лет мы пытаемся создать более ясные управляющие структуры в Jenkins, которые занимались бы ровно тем, о чём вы сейчас спросили. С этой целью мы создали Jenkins Enhancement Process


    Кирилл: Извините, что перебиваю — он сокращается как JEP, так же, как и в Java?


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


    Что касается наших планов на ближайшие полгода, то, скорее всего, мы будем продолжать работать над многими из наших текущих начинаний, в т.ч. Jenkins X. Над ним работают некоторые сотрудники CloudBees и многие сторонние участники. Я надеюсь, что Configuration as Code станет более популярным среди разработчиков плагинов. По большому счёту, мы уже создали основание для неё, так что теперь нужно настроить некоторые плагины, чтобы они могли быть правильно подключены через эту систему. Наконец, если возникнут новые JEP, будем работать над ними.


    Кирилл: Что ж, будем надеяться, что JEP не запатентованы :) Вопрос к вам как к автору Jenkins – чьей идеей был Scripted Pipeline?


    Коске: Это интересный вопрос. Дело в том, что многие начинания в сообществе зачастую не доходят до критической массы и остаются на уровне эксперимента. До того, как мы начали работать над Pipeline, в том же пространстве люди уже пытались сделать нечто подобное, и у нас была возможность познакомиться с этими попытками. Так что мы не были, собственно, изобретателями Pipeline. Одним из таких предшественников был плагин Build Flow, его написал один из сотрудников CloudBees до того, как пришёл в компанию. Думаю, термин «экосистема» очень удачный — всё действительно происходит так, как в настоящей экосистеме, созданная кем-либо технология постоянно эволюционирует и изменяется.


    Руслан: А повлияли ли вы на реализацию Scripted Pipeline?


    Коске: Да, на её первоначальную версию.


    Кирилл: Как мы знаем, есть два способа реализовать любой DSL — статически и динамически. Почему для Scripted Pipeline был выбран динамический подход?


    Коске: Боюсь, я не вполне понимаю, что именно вы имеете ввиду под статическим и динамическим подходами.


    Кирилл: При статическом DSL у нас есть некоторая уверенность в нашем коде до исполнения. Например, с DSL в Java необходимо заранее знать все API и интерфейсы. При динамическом подходе мы осуществляем проверку уже непосредственно при выполнении. Даже если код недопустим, машина всё равно попытается его выполнить, просто она выбросит ошибку в случае необходимости. Декларативная версия пайплайна позволяет исключить многие ошибки за счёт сужения вариативности в скрипте сборки.


    Коске: Если честно, мне не особо важно, когда именно происходит компиляция. Но я могу рассказать об общих установках, которых мы придерживались при проектировании Scripted Pipeline. На определённом этапе значительному числу пользователей Jenkins стала сильно мешать сложность автоматизации. Нужно было обеспечить правильное взаимодействие множества компонентов. Код компилируется, запускаются тесты, затем нужно ждать, пока будет подтверждён деплоймент и так далее. Кроме того, уже тогда появилось желание писать этот процесс в виде кода — примерно тогда большую популярность имела Infrastructure as Code. Разработчики хотели, чтобы всем можно было управлять через файл в системе управления проектом. Из этих двух потребностей и родилась Scripted Pipeline. Однако его использование требовало нетривиальных знаний и не отличалось интуитивностью, поэтому мы хотели сделать более доступный Pipeline для всех, а не только для тех, кто вынужден работать со Scripted Pipeline, чтобы реализовывать сложные оркестрации. Многим нужны были ясность, удобство и доступность, а не полнота по Тьюрингу. Так возникла Declarative Pipeline.


    Кирилл: Сегодня у нас есть, во-первых, плагины Jenkins, у которых обычно статический API с аннотациями и метапрограммированием. Во-вторых, есть плагины Scripted Pipeline, которые объявляют дополнительные DSL. Declarative Pipeline делает примерно то же, просто там меньше гибкости. Что проще поддерживать — плагины для Pipeline или для обычного Jenkins? Я имею в виду, со стороны Jenkins.


    Коске: Я не хотел бы, чтобы возникло представление, будто бы речь идёт о двух отдельных языках. Мне кажется, что пока что нам не удалось найти язык для Pipeline, который одновременно был бы удобным для выполнения простых задач, доступным для новых пользователей, но при этом обладал бы большой гибкостью. Freestyle Job, на которой всегда стоял Jenkins, была изначально очень удачно спроектирована. Если в ней нужно было сделать что-либо сложное, можно было написать плагин, и Freestyle Job затем заполняла пространство между этими плагинами. Это как батончик, который получается, если залить орехи шоколадом. Думаю, в Pipeline нам нужно применить похожее решение. Мы уже делаем кое-что в этом направлении — например, фича Shared Libraries. И всё же очевидно, что нам ещё предстоит многое сделать в этой области. Я давно уже говорю об этом нашей продуктовой команде и разработчикам. Будем надеяться, что мне удалось на них повлиять.


    Кирилл: Мой последний вопрос будет касаться жизненного цикла Jenkins. Важной вехой для проекта был выход версии Jenkins 2. Многие фичи и многие API в нём имели уязвимости. Если сейчас взглянуть на исходный код Jenkins и его плагинов, то перед нами предстанет очень сложная архитектура, со значительным количеством проблем, разобраться в которой крайне тяжело, если человек сам не был частью истории проекта. С вашей точки зрения, можно ли будет нарушить совместимость с предыдущими версиями и предыдущими архитектурными решениями, если в этом будет необходимость?


    Коске: Для проекта важно, чтобы он продолжал развиваться. Действительно, по мере роста накапливается определённый технический долг. Но я не могу согласиться с вашей оценкой сложности Jenkins. Речь идёт о проекте, который пишет около 800 человек, в нём 1600 плагинов — с учётом этого, мне кажется, он очень доступен. Ситуация не настолько критическая, насколько вы её описываете. Тем не менее, развиваться действительно необходимо. В прошлом году я написал пост с заголовком «Смена передачи», в котором я, образно говоря, размахивал флагом и призывал пересмотреть некоторые из наших первоначальных обещаний пользователям, в том числе относительно строгого соблюдения обратной совместимости за исключением случаев, связанных с безопасностью. Я надеюсь, что в сообществе эта тема ещё будет обсуждаться, но пока что слышно не слишком много.


    Руслан: Будет ли ваша политика обратной совместимости похожа на ту, которой придерживается Java? Ведь у неё обратная совместимость с версиями 15-летней, а то и 20-летней давности. Или будет нечто больше похожее на ситуацию с Python 2 и Python 3, которые до сих пор друг с другом не работают? Готовы ли вы нарушить обратную совместимость для реализации важной фичи?


    Коске: Честно говоря, мне не кажется, что правильно ставить вопрос о том, будем ли мы соблюдать совместимость как Java или как Python. Надо думать о том, какого рода софт нужен пользователю. Одна из серьёзных проблем заключается в том, что плагины для Jenkins создаются независимо друг от друга, и заставить их работать вместе неоправданно сложно. Если при решении этой проблемы мы сломаем инстансы у пользователей, то такое решение никому не нужно. А если в результате мы получим систему, которая работает лучше и быстрее, то некоторые нарушения совместимости могут быть оправданы. Думаю, у нас в этом отношении больше гибкости, чем у разработчиков языков, мы не обещаем настолько же жёстко придерживаться совместимости. Мы больше думаем о том, чтобы создать новую версию, например, Jenkins X. До тех пор, пока конечный результат отвечает требованиям прямой совместимости, мы больше об этом вопросе не задумываемся.


    Руслан: Отлично, спасибо большое за ответы!


    5-6 апреля Коске выступит на конференции JPoint с докладом «Superpowers coming to your Jenkins». Кроме того, можно будет пообщаться с ним в дискуссионной зоне после доклада. Узнать подробней о JPoint и приобрести билеты можно официальном сайте конференции (не забывайте, что первого марта цены на билеты вырастут).
    • +30
    • 6,1k
    • 9
    JUG.ru Group
    934,00
    Конференции для программистов и сочувствующих. 18+
    Поделиться публикацией

    Комментарии 9

      +2
      Ни разу не пожалел, когда отказался от Дженкинса.
        0
        в пользу чего?
          +1
          В пользу Bitbucket Pipelines, но кмк это не принципиально, практически любой современный CI/CD уделывает Jenkins, обросшего кучей проблем за 20 лет разработки.
          Jenkins дошел до того момента, когда переписать с нуля, не выглядит такой уж безумной затеей.
            0

            Так они вроде бы и переписывают. Например, есть Jenkins X.

              0
              прошу прощения, но вы голословны, и паблик репозиторий это не то место где живут разработчики коммерческих проектов.
                0
                так bitbucket же можно развернуть внутри компании, Atlassian это вполне продает и вполне «разумно» поддерживает.
                  +1
                  Цена на 100 пользователей 420 000 рублей в год. Пусть и дальше продают, разумно поддерживают…
                  0
                  Простите вы меня, но голословны вы, ибо я занимаюсь коммерческой разработкой и живу на Bitbucket и Bitbucket Pipeline. Второй год, полет нормальный.
            +2

            А в кровавом энтерпрайзе мы помним самурая Коскэ, как создателя JAXB.

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

            Самое читаемое