Jak dzielić się danymi między zadaniami w GitHub Actions (przykłady)
Ostatnio miałem okazję pracować w GitHub Actions - musiałem współdzielić zbudowany projekt frontendowy między wieloma zadaniami. Trochę pogrzebałem i odkryłem wszystkie sposoby, na jakie można to zrobić. W tym artykule się z Wami nimi podzielę. GitHub Actions to sposób na automatyzację pracy dzięki CI/CD działającemu bezpośrednio na repozytorium na GitHubie, które można włączyć poprzez dodanie pliku YAML.
Skupię się tutaj na tym, jak udostępniać dane między zadaniami, które wykonujemy w GHA. A jeśli chcecie odświeżyć sobie podstawy, to kliknijcie tutaj.
Istnieją 2 sposoby na udostępnianie danych między zadaniami w GitHub Actions:
- Cache
- Artefakty
Cache
GitHub ma akcję o nazwie actions/cache
(repozytorium). Możemy jej użyć to załadowania cache i pobrania go z różnych zadań (dokumentacja).
Spójrzmy na następujący przykład:
- name: Cache node modules
uses: actions/cache@v2
env:
cache-name: cache-node-modules
with:
# npm cache files are stored in `~/.npm` on Linux/macOS
path: ~/.npm
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-build-${{ env.cache-name }}-
${{ runner.os }}-build-
${{ runner.os }}-
Całkiem prosto się tego używa. Same akcje mają 3 parametry:
- path(parametr wymagany):ścieżka pliku do wrzucenia do cache lub ściągnięcia z cache. path może być ścieżką absolutną lub względną do katalogu roboczego.
- key(parametr wymagany): jest to klucz utworzony podczas zapisywania cache’a, a korzysta się z niego do ich wyszukiwania. Klucz może się składać z czegokolwiek.
- restore-keys(parametr opcjonalny): lista alternatywnych kluczy, których używamy do wyszukiwania cache, jeśli nie wydarzył się żaden cache hit na
key
.
Akcja ta wyrzuca cache-hit
- możemy go również użyć do uruchomienia jakiejś akcji w następujący sposób:
- name: Cache Primes
id: cache-primes
uses: actions/cache@v2
with:
path: prime-numbers
key: ${{ runner.os }}-primes
- name: Generate Prime Numbers
if: steps.cache-primes.outputs.cache-hit != 'true'
run: /generate-primes.sh -d prime-numbe
Jak widać, jest to bardzo proste i właściwie od razu gotowe do użycia. A teraz przejdźmy do następnego sposobu.
Ładowanie i pobieranie artefaktów
Artefakty służą do zapisywania plików, dzięki czemu można używać ich po zakończeniu uruchamiania. Korzysta się z nich również do udostępniania danych między zadaniami w GHA (dokumentacja). Do stworzenia i użycia artefaktu potrzebujesz następujących akcji: Upload oraz Download.
Aby załadować plik lub katalog, wykorzystaj powyższe akcje w następujący sposób:
steps:
- uses: actions/checkout@v2
- run: mkdir -p path/to/artifact
- run: echo hello > path/to/artifact/world.txt
- uses: actions/upload-artifact@v2
with:
name: my-artifact
path: path/to/artifact/world.txt
Musisz dostarczyć jedynie 2 parametry:
- name: nazwa artefaktu
- path:ścieżka do pliku/katalogu
Następnie pobieramy artefakt. Teraz możemy z niego korzystać:
steps:
- uses: actions/checkout@v2
- uses: actions/download-artifact@v2
with:
name: my-artifact
Jedyne co musimy tutaj dostarczyć, to nazwa zapisanego artefaktu, czyli my-artifact
.
Różnice
Poznawszy oba sposoby, przyjrzyjmy się temu, w jaki sposób się między sobą różnią (dokumentacja). Oba podejścia służą do przechowywania plików na GitHubie, ale w inny sposób. Oto najważniejsza różnica między nimi.
Caching wykorzystuje się do ponownego używania danych/plików w różnych zadaniach lub przepływach pracy. Artefaktów używa się natomiast do zapisywania plików po zakończeniu pracy.
Jeśli chcesz, na przykład, udostępnić wersję w wielu zadaniach, to polecam wybrać cache, ponieważ jest to po prostu szybsze. Ładowanie artefaktów może zająć sporo czasu, zwłaszcza jeśli mamy duże rozmiary plików.
Z drugiej jednak strony, w przypadku logów, wyników testów, oraz raportów, lepiej jest użyć artefaktów.
Porównanie
Oto workflow, który wykorzystuje zarówno cache, jak i artefakty do współdzielenia zbudowanych projektów NextJS:
Widać zapewne niewielką różnicę między użyciem cache i artefaktów i to pewnie dlatego, że jest to jedynie przykład i zbudowany plik jest niewielki - bo jest praktycznie pusty.
Różnica jest znikoma, ale wyobraźcie sobie, że macie prawdziwy projekt, a wtedy różnica czasu będzie spora. Widziałem już np. takie różnice, jak: upload (około 5 minut), download (około 2 minut). A teraz porównajmy to z cache, które zazwyczaj zajmuje kilka sekund. Po załadowaniu danego artefaktu można go pobrać:
Możesz również użyć obu sposobów naraz. Na przykład, jeśli nie chcesz czekać, zanim zbudowana wersja się załaduje, ale istotne jest dla Ciebie zachowanie builda, to możesz użyć cache, a potem załadować wersję w sposób asynchroniczny jako artefakt. Wszystko to podczas działania innych zadań, a więc nie musisz czekać, aż ładowanie się zakończy.
Podsumowanie
Mam nadzieję, że powyższy artykuł pomoże Wam zrozumieć problem dzielenia się danymi między zadaniami w GitHub Actions. A tutaj jeszcze kilka linków:
- Przykładowe repozytorium
- Przykład użycia akcji
- Przykładowy plik YML
Oryginał tekstu w języku angielskim możesz przeczytać tutaj.