CI/CD to podstawa każdego dobrze prowadzonego projektu. Bez tego ciężko utrzymać projekt w dobrym stanie. Konfiguracja odbywa się najczęściej raz na początku projektu i potem aktualizacje od czasu do czasu. Na początku wydaje się to skomplikowane, ale po pierwszej konfiguracji jest już prosto
Jeśli wolisz video od tekstu, to zerknij na poniższy film na YT. Krok po kroku pokazuję jak stworzyć workflow, jak go skonfigurować i jak wygląda uruchamianie tego skryptu. Workflow jest stworzony dla projektu JavaScript, ale możesz go w prosty sposób dostosować do swoich potrzeb. Sam skrypt znajdziesz na dole tego wpisu.
W ostanich latach powstało bardzo dużo narzędzi do tworzenia i zarządzania skryptami CI/CD. Każdy serwer git ma swoje rozwiązanie + istnieje wiele zewnętrznych serwisów np.:
W każdym proces wygląda podobnie i można go opisać jako - test, build and deploy. Jeśli naucz się jednego narzędzia, to pozostałe działają podobnie. Różnią się tylko szczegółami i cennikiem. Github Actions jest idealne na początek bo pewnie i tak masz swój projekt na Github.
Github Actions jest narzędziem do tworzenia skryptów CI/CD. Jesteśmy w stanie puszczać testy, sprawdzać jakość naszej aplikacji, budować ja i robić deploy na odpowiednie środowiska. Jest dostępny dla każdego repozytorium w Github. Możesz z niego korzystać dla dowolnego języka np.: JavaScript, PHP, Python, Java itd.
Github Actions pozwala zautomatyzować wiele zadań w obrębie repozytorium. Istnieje parę standardowych zastosowań, ale możesz to dostosować do swoich potrzeb w projekcie. Przykładowe zastosowania to:
Github Actions jest darmowe dla publicznych repozytoriów. Dotyczy to zarówno Github-hosted runners jak i self-hosted runners. Dla prywatnych repozytoriów github są dostępne darmowe minuty:
Zanim przejdę do tego co najważniejsze, czyli kodu i rozwiązań konkretnych problemów, mam słowniczek pojęć. Pozwoli nam się sprawniej porozumiewać i posługiwać tymi samymi określeniami
Automatyczna procedura dodana do naszego repozytorium. Workflow może się składać z jednego lub więcej zadań (job), które mogą aktywować się na konkretne zdarzenie lub ręcznie.
Zdarzenie, jest aktywnością w naszym repozytorium, która będzie aktywowała konkretny workflow. Do takich aktywności zaliczamy np.: wypuszczenie kodu na gałąź (branch), utworzenie pull-request’a czy też utworzenie release’a. Do najczęściej wykorzystywanych będą:
Zadanie składa się z wykonywanych sekwencyjnie kroków (steps). Zadania są wykonywane w Github Actions równolegle. Można na szczęście konfigurować zadania tak aby wykonywały się po kolei, jedna po drugiej.
Pojedyncze zadanie wykonywane w ramach zadania. Może być zarówno poleceniem konsolowym jak i akcją. Kroki w obrbie zadania są wykonywane w tym samym środowisku i mogą dzielić dane między sobą.
Najmniejszy jednostka budulcowa w Github Actions. Są komponowane w kroki (steps) by budować zadania (jobs).
Środowisko w którym uruchamiane są zadania. Technicznie jest to serwer z zainstalowaną aplikacją Github Actions runner. Może to być zarówno środowisko, które dostarcza Github (Windows Server, Ubuntu, macOs) jak i własny serwer.
name: CI
on:
pull_request:
branches: [main]
jobs:
build_and_test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '18.x'
- name: Installing dependencies
run: npm ci
- name: Lint
run: npm run lint
- name: Build
run: npm run build
Pierwszym krokiem jest stworzenie pliku yaml w folderze .github/workflows. Dobrze, aby ten plik miał nazwę, która opisuje cel w którym został stworzony, Dzięki temu będzie łatwiej tym zarządzać. Pamiętaj, by dodać do repozytorium git.
name: CI
W pierwszej linii masz nazwę skryptu. Ona potem się pojawia na portalu Github w zakładce Actions więc powinna być maksymalnie opisowa. Jak będziesz mieć setki skryptów, to warto wiedzieć, co się dzieje i gdzie.
on:
pull_request:
branches: [main]
Dalej w sekcji on jest konfiguracja dla jakich zdarzeń nasz skrypt ma się aktywować. Przykładowy workflow uruchomi się gdy ktoś otworzy pull request do brancha main. W nawiasach kwadratowych możesz zmienić nazwę brancha lub dopisać inne np.: [master, develop]
jobs:
build_and_test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '18.x'
- name: Installing dependencies
run: npm ci
- name: Lint
run: npm run lint
- name: Build
run: npm run build
Następnie jest już sekcja jobs, która definiuje jakie są konkretne zadania dla tego skryptu. W przypadku tego skryptu jest tylko jeden job o nazwie build_and_test, który działa się na maszynie linuks (ustawiamy to opcją runs-on).
W każdym zadaniu trzeba skonfigurować poszczególne kroki które będą po kolei wykonywane. Pierwszym z nich zazwyczaj będzie akcja checkout, która pobiera najnowszy kod i pozwala pozostałym krokom operować na kodzie. Opcja uses informuje nas, że korzystamy z akcji, która istnieje w Github Marketplace - jest to kawałek kodu, który ktoś przygotował, by ułatwić nam pracę
Uwaga. Zanim skorzytasz z takiego gotowca, to sprawdź czy nie zawiera potencjalnie szkodliwego kodu.
Takie skrypty mają często opcje przekazywania dodatkowych parametrów, co widać podczas ustawiania konkretnej wersji node’a. Możesz równie programować własne akcje, ale tym tematem zajmę się w innym wpisie.
Pozostałe akcje korzystają ze skryptów stworzonych w pliku package.json. Najpierw instaluję wszystkie zależności, następnie uruchamiam statyczną analizę kodu i na koniec proces budowania aplikacji. To ostatnie jest przydatne, by sprawdzić, czy nie błędów podczas budowania oraz jest wymagane, by wygenerować artefakt. Z takim artefaktem potem możemy budować aplikację.
Teraz możesz zmodyfikować skrypt pod siebie. Jeśli pracujesz w projekcie JavaScript, to pierwsze kroki bedą identyczne, a zmienią się tylko ostatnie skrypty. Jeśli pracujesz z innym językiem musisz więcej zmienić, ale sposób działania jest taki sam.
Jeśli poprawnie dodałeś plik z pierwszym workflow, to w ramach repozytorium zobaczysz zakładkę Actions. Zawiera ona wszystkie informacje na temat uruchamianych skryptów. Możesz też zarządzać cachem z poziomu tego panelu (Tym tematem zajmę się w osobnym wpisie. Teraz tylko wspomnę, że możesz przechowywać pewne informacje pomiędzy zadaniami, by przyspieszyć pracę ).
Jeśli wejdziesz w szczegóły workflow, to zobaczysz jakie zadania zostały, wykonane, z jakim statusem i ile trwało.
Możesz też wejśc w szczegóły joba i zobaczyć jakie kroki się wykonywały. Masz tam informacje o konkretnym kroku, czasie i tym co zostało wyświetlone w konsoli. Jest to szczególnie przydatne podczas szukania błędów.