Я – большой фанат сервиса Azure DevOps с самых ранних его дней, когда он ещё назывался Visual Studio Online. Я использую его в профессиональных и личных целях,
и рекомендую его своим клиентам по консалтингу.
Однако сколько бы я ни расхваливал эту платформу, часто бывает тяжело убедить разработчиков на Node или Java в том, что Azure DevOps прекрасно справится и с их проектами, не хуже, чем для .NET. Вне зависимости от количества демонстраций и презентаций, опровергающих предубеждения, в любой группе находятся люди, свято верящие в то, что ADO для них не подойдёт, потому что это «инструмент от Microsoft».
Отставив в сторону философские дебаты, я могу объяснить большую часть сопротивления отсутствием понимания того, как Azure DevOps развилась из своего предшественника Team Foundation Services (TFS), и стала лучшим в своём классе набором инструментов, способных поддерживать проекты любого размера «на любом языке и любой платформе». Вопрос в том, как я могу неоспоримо доказать это раз и навсегда?
Я немного поигрался с этой идеей, а потом меня осенило. Доказательство нужно делать, не создавая очередную демку CI/CD для микросервисов SpringBoot, разворачиваемых для Kubernetes на AWS – его нужно делать с более эксцентричным подходом.
А теперь нечто совсем иное
Что, если мы перестанем концентрироваться на современных языках и платформах, и перенесёмся на 30 лет назад, чтобы посмотреть, можно ли использовать современные средства и ADO для разработки, сборки, разбивки на модули и внедрения программы, написанной для 8-битной компьютерной платформы?
Как и в случае с другими демками для ADO, создаваемыми мною в прошлом, я хотел показать совершенно законченный продукт – от редактирования кода, его проверки, и так далее, вплоть до живого окружения, в котором можно наблюдать за изменениями.
В теории всё это звучало неплохо, но реальным вопросом стало – с чего начать? Это, очевидно, была не такая ситуация, в которой можно прошерстить StackOverflow в поисках предыдущих примеров. Однако, обсудив идею с друзьями и коллегами (все они решили, что я двинулся), я начал оформлять свою идею.
Я решил, что демонстрационная программа должна быть написана в 8-битном машинном коде для Commodore 64 при помощи редактора VS Code. Исходник будет обрабатываться репозиторием Git на ADO, а конвейер CI/CD будет отвечать за билды, модули и внедрение в Azure. Я уже начал подозревать, что мои друзья были правы, и крыша моя уже поехала, но всё же эта идея казалась интересным вызовом.
Выбор редактора
Всем известна поговорка про выбор правильного инструмента для конкретной работы. Это применимо и для работы по дому, и для ремонта автомобиля, и для написания кода.
Как разработчик .NET, большую часть времени я провожу в Visual Studio 2017. Если мне надо переключиться на проект на Java или написание нативных программ для Android, я запускаю IntelliJ или Android Studio соответственно. Какой же редактор мне использовать для машинного кода C64?
Хотите – верьте, хотите – нет, но сегодня существует несколько неплохих редакторов, подходящих для написания CBM. Я поигрался с некоторыми из них, но на самом деле я хотел использовать Visual Studio Code. Я использовал VS Code для других своих проектов, и мне он показался весьма гибким, комфортабельным, да и наличие встроенной интеграции с git было приятным дополнением.
Минусом этого решения было то, что мне пришлось бы пожертвовать подсветкой синтаксиса в ассемблере 6510, и я бы просто пялился на чёрный текст на белом фоне. Эта ситуация не соответствует моему заявлению о «правильном инструменте».
Внезапно я решил сходить на Visual Studio Marketplace, и посмотреть, нет ли там уже какого-нибудь расширения для VS Code, подходящего для решения моей задачи. Я был приятно удивлён найти там несколько расширений, предназначенных для работы на ассемблере. К сожалению, ни одно из них не было заточено под ACME Cross Assembler, выбранный мною для проекта.
Меня это не остановило, и, не желая заново переживать монохромные аспекты разработки 80-х, я зарылся в документацию о создании расширений для VS Code. Через несколько дней я с радостью выпустил первую версию расширения для Visual Studio Marketplace.
И это упражнение оказалось более полезным, чем казалось изначально.
В своё время я так и не навострился в написании программ на ассемблере. Несколько раз я пытался его изучить, но обычно испытывал скуку или раздражение, и переходил к чему-то другому. Создав плагин, я не только узнал о механике создания расширений для VS Code, но и приобрёл неплохое понимание невразумительного синтаксиса и кодах операций.
Вооружившись подходящим редактором и несколькими старыми книжками по программированию из 80-х, я начал писать код. Очень быстро у меня получилась работающая программа, импортирующая музыкальный файл формата SID и проигрывающая 8-битную версию песни Beatles When I’m 64 (это старая шутка пользователей Commodore, но для данного проекта она, кажется, подходит в самый раз).
До сего момента я компилировал и тестировал программу на ноутбуке. Исходник был закомичен на репозиторий git, поэтому следующим шагом стала необходимость создать билд для Continuous Integration.
Одна из впечатляющих способностей ADO – возможность обрабатывать практически любую ситуацию с CI/CD. Прямо «из коробки» сервис предлагает множество предустановленных задач, позволяющих вам быстро создавать CI/CD цепочки для большинства современных проектов всего в несколько кликов.
Если в базовый сервис ваши потребности не входят, то Marketplace обычно предоставит вам множество различных подходящих инструментов. Если и это не сработает, можно набросать скрипт на PowerShell, выполняющий необходимую вам работу.
Очевидной проблемой проекта стало то, что несмотря на широкий спектр возможностей сервиса, кросс-ассемблера и создания образов дисков для Commodore 64 просто не было. Я, конечно, мог создать специальную виртуальную машину в Azure с необходимыми мне инструментами, или пойти по пути PowerShell, но разве это было бы интересно?
Также я недолюбливаю виртуалки в облаке, и для данного упражнения я хотел использовать Hosted Agents, поэтому выбор у меня оставался только один. Чтобы доказать то, ради чего и задумывалось всё это упражнение, я решил, что лучше всего будет создать собственное расширение для обработки всех этих задач.
Расширение ACME Cross-Assembler
Первое расширение, необходимое для моей цепочки CI, должно было компилировать мой ассемблерный код в машинный код C64. Для этого мне нужно было установить кросс-ассемблер на одного из серверных агентов сборки [hosted build agent].
Ассемблер – это программа, преобразующая человеко-читаемый язык ассемблера в реальный машинный код, предназначенный для конкретного двоичного обработчика. Обычно машинный код генерируется для процессора, используемого в машине, на которой он работает. Кросс-ассемблер делает следующий шаг в преобразовании кода, позволяя генерировать машинный код для другого процессора.
Как я уже упоминал, для своего проекта я выбрал ACME Cross-Assembler, поскольку его рекомендуют для разработки под Commodore. Он также поддерживает широкий спектр других 8-битных проектов, например, Nintendo Entertainment System или семейство Atari, использующее процессоры 65xx.
Мне потребовалась большая часть дня, чтобы на основе документации и примеров, обеспеченных Microsoft и другими источниками, чтобы написать, проверить и опубликовать на Marketplace рабочую версию расширения.
При запуске задача автоматически скачивает последнюю версию ACME Cross-Assembler и запускает его с параметрами, позволяющими создавать итоговый файл для целевой платформы. Одно из преимуществ, связанных с выбором именно ACME, состоит в том, что большая часть параметров для сборки программы встроена в исходный код, что свело к минимуму количество входных данных, которые нужно было определять в расширении.
Есть у кого дискета взаймы?
Следующий шаг цепочки – перевести программу в формат носителя, совместимого с Commodore 64, то есть, поместить её на дискету. С такой проблемой разработчики также не сталкиваются в повседневной жизни. К счастью, для выполнения этой задачи существуют отдельные приложения.
VICE – самый популярный эмулятор для Commodore. У него есть не только множество эмуляторов для каждой из различных моделей, выпускавшихся Commodore, но и несколько полезных инструментов, включая менеджер виртуальных дисков c1541. Образы дисков, созданных с его помощью, можно использовать с эмулятором, копировать на физический носитель (гибкий диск низкой плотности 5 ¼"), или загружать на microSD и использовать с эмулятором SD2IEC drive emulator.
В отличие от задачи ACME, берущей все настройки из заголовка исходного файла, дисковая утилита c1541 полагается на CLI, и пользователю доступно множество настроек управления диском. Для моего расширения я решил остановиться только на свойствах, необходимых для моей задачи, но даже и тогда передо мной встал выбор, связанный с тем, насколько основательной мне нужно было её сделать.
Commodore выпускала три различных модели дисководов, отличавшиеся методом обработки объёмов дисков на основе форматирования и типа носителя. Базовая модель, знакомая большинству пользователей, могла работать только с односторонними дисками объёмом 170 Кб (да, килобайт. Родителей спросите). Более поздняя модель, 1571, использовавшаяся на Commodore 128, могла работать с двусторонними дисками, объём которых увеличивался до 340 Кб. Я решил добавить расширению гибкости, поэтому добавил поддержку различных форматов дисков в виде настройки, которую можно выбирать в интерфейсе через выпадающее меню.
Поскольку у меня уже был рабочий пример, создание этого расширения шло гораздо быстрее. Я узнал кое-что новое, что позволило мне улучшить код и для расширения ACME.
Как и в случае кросс-ассемблера, требуемое ПО скачивается с репозитория проекта с открытым кодом и устанавливается в агента сборки. Задача создаёт образ диска в нужном формате, а потом на него копируется файл с задачи сборки. Получившийся файл перемещается в директорию Build Artifacts, откуда его можно скачать.
Это что же получается – столько работы, а в результате надо скачивать файл? Это должен быть обучающий материал по CI/CD. Если нам нужно доказать нашу позицию, нам надо развернуть программу на машине так, чтобы её можно было использовать в качестве демонстрации.
Флоппинет отключен
Работающие версии реального компьютера Commodore 64 и дисковода 1541 – вещь довольно редкая, не говоря уже о том, что большая и тяжёлая. Кроме того, они неспособны выводить картинку на современные мониторы без специальных адаптеров, а это сильно ограничивает эффективность демонстрации.
У Commodore SX-64 (первого «портативного» цветного компьютера из выпускавшихся большими партиями) был встроенный монитор, однако размером он примерно с мой чемодан для ручной клади, и весит порядка 10 кг. Представьте себе, как тяжело было бы пройти через службу безопасности аэропорта с таким монстром?
Недавно выпущенный C64 Mini имеет достаточно малый размер, чтобы с ним можно было путешествовать, возможность загружать программы с USB и выход HDMI. В некоторых случаях это был бы один из вариантов. Но он всё равно не достигает нужной цели.
Реальная проблема – не в портативности железа, а в отсутствии автоматизации. Необходимость переносить программу с ноутбука на машину при помощи флэшки не позволяет полностью раскрыть возможности ADO в презентации.
Вариант без сервера
Как я уже упоминал, VICE – самый популярный эмулятор для Commodore. Его портировали на Windows, Linux, Mac OS X, MS-DOS и множество других ОС. Однако для облачной разработки такой вариант потребовал бы настройки VM в качестве хоста, а я хотел обойтись решением, не требующим сервера.
Кроме упомянутых версий, у VICE есть вариант для JavaScript, нормально работающий в большинстве браузеров. Хотя фронтенд-разработка – не моя стихия, я смог сварганить приличную отзывчивую страницу.
Для организации цепочки выпуска я загружаю файл с образом диска в каталог в том же хранилище. Я связал это с вызовом приложения Azure Function App, возвращающего список доступных образов дисков. Выбор одного из них из выпадающего меню автоматически загружает и запускает его в JavaScript-эмуляторе.
Система работает не только с моей программой, у меня получилось создать цепочку для развёртывания и запуска программы на Commodore 64 BASIC.
10 PRINT "HELLO WORLD"
20 GOTO 10
Заканчиваем
DevOps для Commodore 64? Немыслимо!
Смысл данного упражнения заключается не только в доказательстве того, что когда про Azure DevOps заявляют, что она поддерживает «любой язык и любую платформу», имеют в виду не только всё, что связано с Microsoft (хотя версия BASIC для Commodore была куплена по лицензии у Microsoft). Оно отвлекает нас от концентрации на технологических аспектах и заставляет людей выходить за искусственные рамки, назначенные ими для самих себя.
Вне зависимости от оправданий, заявления типа «это тут не сработает» часто равнозначны заявлениям «мы всегда это делали так-то, зачем что-то менять». Обе фразы демонстрируют нежелание расти и развиваться, адаптироваться к постоянно меняющемуся технологическому ландшафту, преодолевать вызовы, порождаемые этими быстрыми и агрессивными изменениями.
DevOps – это не инструменты. Инструменты в итоге оказываются просто средствами для достижения цели, вне зависимости от того, кто их публикует.
Чтобы DevOps стали успешными для организации, необходимо поменять стиль
Создание цепочки CI/CD для 30-летнего компьютера не имеет ценности для бизнеса, кроме явной иллюстрации данной точки зрения.
Автор: SLY_G