Изграждане на добър CI/CD конвейер с GitHub Actions Това вече не е допълнително „за когато има време“: в съвременните екипи това е практически изискване за бързо и надеждно внедряване. Въпреки това, намирането на пълен, общ и добре обмислен пример, който можете да адаптирате към вашата компания, често е много по-сложно, отколкото изглежда.
В следващите редове ще смесим класическата теория за CI/CD с примери за имплементация от реалния свят, използващи GitHub Actions, многократно използваеми конвейери, задачи, bash скриптове, PowerShell PnP модулиВнедрявания в Kubernetes, Google Cloud и Kinsta, заедно с най-добри практики за сигурност, мониторинг и мащабируемост. Идеята е, че можете да вземете тези части, да ги впишете във вашия контекст и да избегнете много от типичните капани.
Защо ви е необходим добре изграден CI/CD конвейер
В настоящото професионално развитие, CI/CD е кръвоносната система на кода.Той интегрира промените, изпълнява тестове, изгражда артефакти и внедрява нови версии с минимална намеса. Без този работен процес всяко внедряване се превръща в бавно, податливо на грешки и ръчно изпитание.
Непрекъснатата интеграция (CI) се фокусира върху валидирането на промените Веднага щом бъдат качени в хранилището, се изпълняват модулни тестове, линтери и статични анализи, за да се открият грешки възможно най-бързо. Колкото по-бързо получите обратна връзка, толкова по-скоро можете да ги поправите и толкова по-малко болезнена ще бъде всяка регресия.
Непрекъснато внедряване (CD в смисъла на Continuous Deployment) или Непрекъснатата доставка (в зависимост от нивото на автоматизация) добавя автоматизация на частта за пускане на продукта: изграждане на образи, публикуване на пакети, внедряване в тестови, подготвителни или производствени среди и дори промяна на трафика с помощта на синьо-зелени или „канаре“ стратегии.
В компании с много остарял кодДобрият пайплайн е един от най-добрите лостове за модернизиране на екосистемата: той ви позволява да въвеждате тестове в наследени услуги, да автоматизирате задачи, които преди това са се изпълнявали ръчно, и да намалите разходите за поддръжка на инфраструктури като Jenkins или Nexus, които са остарели.
Какво представляват GitHub Actions и защо се съчетават толкова добре с CI/CD?
GitHub Actions е платформата за автоматизация, вградена в GitHub. Позволява ви да дефинирате работни процеси в YAML файлове в самото хранилище. С него можете да компилирате, тествате, анализирате и внедрявате софтуера си, без да настройвате външни CI сървъри.
Работният поток е набор от задачи и стъпки което се предизвиква от събития като push, pull_request, schedule (CRON), workflow_dispatch (ръчни) или дори действия по проблеми. Всяка задача се изпълнява в runner (например, ubuntu-latest) и се състои от стъпки, които използват повторно използваеми действия или команди run.
GitHub предлага огромен пазар за акции където имате готови интеграции за почти всичко: Docker, Kubernetes, AWS, Azure, Google Cloud, SonarCloud, Slack, Jira, анализ на сигурността, linters за хиляда езика и др. Това значително намалява времето, необходимо за настройване на разширени pavement-и.
В сравнение с решения като Jenkins или ConcourseGitHub Actions има няколко ясни предимства: това е управлявана услуга (не управлявате сървъри), тя е тясно свързана с кода, използва модел на плащане при ползване и се поддържа от огромна общност. Освен това много разработчици вече са запознати с нея от лични проекти, което значително намалява кривата на обучение.
Основни компоненти на работния процес на GitHub Actions
Всичко започва с YAML файл в .github/workflows/, например ci.yml o build-test-deploy.ymlВъпреки че синтаксисът може да се разшири значително, основната структура е сравнително проста.
Ключовите раздели на YAML са: name (име на работния процес), on (събития, които го задействат), jobs (набор от логически задачи) и в рамките на всяка задача, runs-on (бегач), steps (стъпки), env (глобални променливи) и if (условия за изпълнение на стъпки или задачи).
Работните места представляват блокове работа които могат да се изпълняват паралелно или последователно, използвайки needsВ рамките на всяка задача стъпките използват действия (uses:) или команди (run:Типичен пример включва: проверка на код, инсталиране на зависимости, изпълнение на linter, тестове и изграждане.
Тайни и променливи на средата Те се управляват на ниво хранилище, организация или среда. В работните потоци те се препращат с ${{ secrets.MI_SECRET }} и позволяват работа с API ключове, токени за внедряване или облачни идентификационни данни, без да ги излагат в хранилището.
YAML също така позволява изграждането на масиви за изпълнение с strategy.matrix, много полезно за тестване на кода ви на различни версии на Node, Python или Java, или дори на различни операционни системи, без да е необходимо да пишете един и същ блок няколко пъти.
Проектирайте модерен CI/CD конвейер, използвайки най-добрите практики
Здравословният тръбопровод обикновено е разделен на ясни фазибързи проверки (lint, модулни тестове), изграждане на артефакти, издаване (версия, етикетиране, дневник на промените, публикуване в хранилище за артефакти) и внедряване в една или повече среди.
Фазата на непрекъсната интеграция трябва да бъде възможно най-бърза. Това гарантира, че всяка заявка за push или pull получава почти незабавна обратна връзка. Често срещана практика е различните проверки да се изпълняват паралелно, използвайки отделни масиви или задачи, като се приема малко по-висока цена в замяна на намаляване на общото време на чакане.
За да се отдели тръбопроводът от конкретния езикМожете да използвате инструмент за задачи като Task (подобен на Make, но с по-лесен за ползване синтаксис). По този начин работният процес на GitHub Actions извиква само генерични задачи (task test, task lintи т.н.) и всяко хранилище определя как те са имплементирани вътрешно в зависимост от това дали е Node, Java, Python и т.н.
Версионирането и артефактите влизат в действие по време на фазата на издаване.Тук създавате Docker изображение, jar/war файл, npm пакет или друг артефакт, качвате го в съответния регистър (Docker registry, Maven, npm в Artifact Registry и др.), маркирате commits и генерирате GitHub издания или changelogs с инструменти като git-cliff или действия за освобождаване.
Накрая, фазата на внедряване Преместете този артефакт в средата за изпълнение: Kubernetes (GKE), Google App Engine, Cloud Functions, услуги на Kinsta, ваши собствени сървъри чрез SSH и др. Тук можете да свържете последващи стъпки, като например функционални тестове след внедряване или Slack известия с подробности за изданието.
Пример: Пълен конвейер с ESLint, тестове и внедряване в Kinsta
Много илюстративен пример е използването на GitHub Actions Да се валидира React приложение с ESLint и модулни тестове, а след това да се разположи в Kinsta, използвайки неговия API. Всичко е оркестрирано в един CI/CD работен процес.
Първата част на YAML дефинира тригера. и името на тръбопровода. Например, че той работи на всеки push y pull_request до клона mainи дори планирани с CRON задачи (например всеки ден в полунощ или всеки понеделник в 8:00 UTC), използвайки събитието schedule.
Първата работа в процес на разработка може да се нарече eslint и е отговорен за проверката на синтаксиса на кода. Изпълнява се в ubuntu-latest и използва набор от версии на Node (напр. 18.x, 20.x), със стъпки за проверка и конфигуриране на Node actions/setup-node, кеширане на npm зависимости, инсталиране с npm ci и хвърли npm run lint.
Втората работа, testsЗависи от eslint чрез needs: eslintтака че се изпълнява само ако проверката на синтаксиса е успешна. Вътре, шаблонът се повтаря: проверка, инсталиране на зависимости и изпълнение на npm run test на конкретна версия на Node.
Третата работа, deploy, то е свързано с верига след двете задачи използване на needs: и използва стъпка с curl за да се извика Kinsta API. За да направите това, API ключът и идентификаторът на приложението са конфигурирани като секрети в GitHub (KINSTA_API_KEY y APP_ID) и са изложени в работата чрез env за да се изгради POST заявката, която задейства внедряването.
Важно е да се разбере, че тази задача за внедряване Kinsta счита самото приемане на API за успех; ако обаче внедряването впоследствие се провали вътрешно в Kinsta, работният процес на GitHub може все още да показва зелен статус. Това трябва да се има предвид, за да се избегне самодоволство и да се допълни процесът с мониторинг след внедряването.
Разширено управление на cron и планиране на работни процеси
Синтаксисът на CRON в действията на GitHub Базиран е на UNIX формат с пет полета: минута, час, ден от месеца, месец и ден от седмицата. Всяко поле може да използва звездички, диапазони, списъци и стъпки (*, 1-5, 1,15,30, */5), което позволява планиране на задачи по поддръжка, архивиране, почистване или периодични проверки.
Например 0 0 * * * изпълнявайте работния процес всяка полунощ (UTC), докато 0 8 * * 1 Прави това всеки понеделник в 8:00 часа. Това се съчетава безпроблемно с обичайните тригери на push y pull_requestтака че един и същ YAML да може да реагира както на промени в кода, така и на планирани изпълнения.
Тази възможност е идеална за задачи, които няма смисъл да се издават във всеки commit.интензивни сканирания за сигурност (напр. с OWASP Dependency Check в Java), одити на зависимости, проверки на покритието на тестове или почистване на стари артефакти в системния регистър.
Повторно използване на работния процес: мащабиране на CI/CD до стотици хранилища
Когато вашата организация има десетки или стотици хранилищаКопирането и поставянето на един и същ YAML файл навсякъде е рецепта за хаос. Всяка промяна изисква модифициране на половината от GitHub Enterprise, което прави почти невъзможно поддържането на последователност и най-добри практики.
Решението се крие в проектирането на работни процеси за многократна употреба централизирани в хранилище за „шаблони“ на CI/CD. Тези работни потоци предоставят входни и изходни данни, а всяка услуга дефинира само малък YAML файл, който ги извиква, предавайки параметри като тип артефакт (Docker, Java библиотека, npm пакет), среда за изпълнение на внедряването (GKE, GAE, Cloud Function и др.) или елементи на задачата, които трябва да бъдат изпълнени.
Често срещан модел е разделянето на три големи работни потока за многократна употреба: един от build-check-task (непрекъсната интеграция), друга от build-release-dockerfile или други артефакти и трето разполагане (deploy-gke, deploy-gaeи др.), така че всяко хранилище да изгражда своя конвейер чрез комбинирането им.
За да се капсулира споделена логика, могат да се дефинират и персонализирани действия. en .github/actionsНапример, за да конфигурирате Gradle, Java, Node или Task, да получите метаданни за изграждане, да публикувате Docker изображения, да маркирате версии в Git с bash скрипт или да изпращате известия до Slack. Златното правило е, че хранилищата на услуги трябва да използват само работни потоци за многократна употреба, а не директно тези действия, така че обратната съвместимост да е по-лесна за управление.
Бърза непрекъсната интеграция със задачи, матрици и статичен анализ
По време на фазата на изграждане или проверка е препоръчително да се задействат много неща паралелно.Единични тестове, статичен анализ (PMD, Checkstyle, SpotBugs в Java; ESLint в JS/TS), сканиране със SonarCloud и др. Това поддържа общото време за изпълнение на конвейера разумно дори в големи кодови бази.
Задачата (Taskfile.yml) действа като слой на абстракция на специфични команди, което позволява на работния процес на CI просто да извиква task check, task test o task lintЗа Java проект тези задачи могат да бъдат делегирани на Gradle с JUnit, PMD, Checkstyle и SpotBugs; за Node проект - на Jest, ESLint и инструменти за сигурност като... npm audit или подобен.
GitHub Actions добавя частта от масива За да се изпълняват едни и същи задачи на различни версии на средата за изпълнение: например, тестване на Node библиотека на 16, 18 и 20 или Python проект на 3.10 и 3.12. Просто е като деклариране на масив от версии и използването му в конфигурацията на задачата.
Този подход е особено полезен в организации, които искат да поддържат множество стекове. (Java, Node, TypeScript, Python и др.), без да се налага пренаписване на логиката на конвейера за всяко хранилище: Задачата се адаптира към всеки език, а работните потоци за многократна употреба остават практически същите.
Фаза на издаване: версиране, маркиране и публикуване на артефакти
След като проверките са преминали, е време да се изгради артефактът, който действително ще бъде разположен.Docker образ, JAR файл, npm пакет, каквото е подходящо. Това включва както езиковите инструменти, така и регистрите и политиката за версии на организацията.
Някои Java проекти използват плъгини като Gradle Axion. да управлява версии въз основа на Git тагове. В смесени контексти (Java, Node и др.) може да е по-лесно да се използва персонализиран bash скрипт, който изчислява следващата версия (например с помощта на SemVer), създава тага, изпраща го към отдалечената система и генерира съответната версия.
Инструменти като git-cliff Те помагат за генерирането на дневници на промените Въз основа на съобщенията за коммит, промените се класифицират по тип (функция, поправка, грешка и др.). Интегрирането им в конвейера гарантира, че всяко издание идва с ясен списък с промени, без никой да се налага да го пише ръчно.
За публикуване на артефакти се комбинират подходящи действия и идентификационни данни.Регистри на Docker (Docker Hub, GitHub Container Registry, Artifact Registry), Maven хранилища, npm регистри и др. Отново, идентификационните данни се съхраняват като секрети и се инжектират в задачи само когато е необходимо.
Непрекъснато внедряване в Kubernetes, GCP, Kinsta и други среди
Разгръщането е мястото, където CI/CD взаимодейства с инфраструктурата.Тук GitHub Actions се интегрира безпроблемно с почти всяка платформа: Kubernetes, App Engine, Cloud Functions, традиционни сървъри, платформи като Kinsta и др.
За Kubernetes (например в GKE) обичайният модел Това е: удостоверяване с Google Cloud (използвайки официални действия), конфигуриране kubectl В контекста на клъстера, приложете Helm манифестите или диаграмите и, ако е необходимо, извършете контролирано внедряване (напр. с canary или blue-green) и проверете състоянието с команди от kubectl rollout status.
В случай на App Engine или Cloud FunctionsКанвалерът изгражда изображението или артефакта, публикува го в регистъра на артефактите и след това извиква командите за внедряване. gcloud подходящо, отново използвайки управлявани идентификационни данни, като например тайни и ефимерни бегачи.
Когато внедряването се извършва срещу външни API-та, като например тези на Kinstaобикновено една стъпка е достатъчна curl или специализирано действие, което изпраща заявката с токена за удостоверяване и необходимите параметри (идентификатор на приложение, клон и др.). Задачата се счита за успешна, ако API отговори правилно на новата заявка за издание.
Разгръщането почти винаги е придружено от уведомление. към Slack, Teams или други инструменти за комуникация, като се посочва коя услуга е била внедрена, в коя среда, с коя версия, кой я е задействал и се свързват с регистрационните файлове на работния процес. В производствения режим това служи и за одит и проследяване.
Контрол на качеството: сигурност, мониторинг и логове
Автоматизирането на изграждането и внедряването е чудесно, но без видимост Що се отнася до случващото се, процесът на обработка може да се превърне в черна кутия. GitHub Actions предлага подробни регистрационни файлове по изпълнение, по задача и по стъпка, което ви позволява да диагностицирате грешки при компилация, тестване или внедряване.
За по-напреднали нужди са интегрирани услуги за външна наблюдаемост. като Datadog, New Relic или Splunk, които събират показатели за работни процеси, време за изпълнение, процент на неуспехи и др., помагайки за откриване на пречки и приоритизиране на оптимизациите на процесите.
В същото време сигурността играе ключова роляуправление на криптирани тайни, минимално необходими политики за достъп, преглед на разрешенията за действия, включване на скенери за уязвимости на кода и зависимости (сканиране на код, сканиране на тайни, OWASP и др.) в самите работни процеси.
Много екипи добавят и тестване след внедряване В новообновената среда: цялостни функционални тестове, проверки на производителността, основни тестове за дим и, ако нещо се повреди, автоматизирани механизми за връщане към предишната стабилна версия.
Управление на работния процес: защитени клонове и заявки за изтегляне (pull requests)
Начинът на работа с клонове и заявки за изтегляне трябва да е съобразен с CI/CD. така че всичко да има смисъл. Най-често срещаното е да се защити главният клон (main o master) и изискват всяка промяна да преминава през PR и да преминава проверки на конвейера.
GitHub ви позволява да дефинирате правила за защита на клонове Тези правила налагат използването на заявки за изтегляне (pull requests), блокират директни коммити и изискват определени проверки на състоянието (специфични работни потоци за действия) да са „зелени“, преди да се позволи сливането. Те могат също така да изискват минимални редакции, правила за одобрение и др.
Този модел гарантира, че кодът, който достига до производствения процес Преминал е през човешка проверка и всички автоматизирани проверки на процесите, което драстично намалява риска от пропускане на сериозни грешки или уязвимости.
В компании с множество среди (разработка, подготовка, производство) внедряването в производство обикновено е запазено за сливания в основния клон, докато други клонове могат да задействат внедрявания в предишни среди за вътрешно тестване или демонстрации.
Поглеждайки в голямата картина, добре проектиран CI/CD конвейер с GitHub Actions Това се превръща в гръбнака на разработката: интегриране на промени, изпълнение на цялостни тестови пакети, изграждане и публикуване на артефакти, внедряване в множество облачни платформи, наблюдение с инструменти за наблюдаемост и управление с ясни правила за разклоняване и заявки за изтегляне. С многократно използваеми работни процеси, персонализирани действия, спомагателни инструменти като Task, Rease Action и Git Cliff, както и стабилно управление на секретни данни и разрешения, е възможно да се поддържа всичко - от прости Python приложения до сложни Kubernetes архитектури, поддържайки скорост на доставка, качество на кода и сигурност, без да се претоварва екипът с ръчни задачи.