Wróć do katalogu
Season 24 14 Odcinki 57 min 2026

GitHub Actions

Edycja 2026. Kompleksowe, techniczne omówienie GitHub Actions, obejmujące model wykonywania, zaawansowane workflows, bramkowanie środowisk, runners oraz bezpieczeństwo. Edycja 2026.

CI/CD DevOps
GitHub Actions
Teraz odtwarzane
Click play to start
0:00
0:00
1
Argumenty za GitHub Actions w Enterprise
Zestawienie GitHub Actions z tradycyjnymi narzędziami CI/CD, takimi jak Azure DevOps i GCP Cloud Build. Omawiamy architektoniczne zalety automatyzacji sterowanej zdarzeniami (event-driven), która działa tuż obok kodu źródłowego.
4m 38s
2
Model mentalny wykonywania
Techniczna analiza hierarchii w GitHub Actions. Zrozum kluczowe relacje między Workflows, Jobs, Steps i Actions.
3m 48s
3
Triggers i filtry oparte na zdarzeniach
Szczegółowe omówienie event triggers w GitHub Actions. Dowiedz się, jak skonfigurować precyzyjne filtry ścieżek i gałęzi, aby dokładnie kontrolować, kiedy uruchamiają się Twoje workflows.
4m 12s
4
Ewaluacja stanu za pomocą Variables i Contexts
Zrozum kluczowe różnice między environment variables a GitHub Contexts. Dowiedz się, kiedy każde z nich jest ewaluowane w cyklu życia workflow.
4m 10s
5
Granica bezpieczeństwa: Secrets i GITHUB_TOKEN
Techniczne spojrzenie na zarządzanie secrets w GitHub Actions. Omawiamy efemeryczny GITHUB_TOKEN oraz hierarchię secrets na poziomie repozytorium i organizacji.
4m 20s
6
Optymalizacja danych: Caching kontra Artifacts
Poznaj dokładną różnicę między Dependency Caching a Workflow Artifacts. Przestań spowalniać swoje buildy przez użycie niewłaściwego mechanizmu przechowywania danych.
4m 41s
7
Kontrolowanie przepływu za pomocą Concurrency
Opanuj kontrolę nad wykonywaniem workflow. Dowiedz się, jak używać słowa kluczowego concurrency, aby anulować nadmiarowe uruchomienia i zapobiegać nakładającym się wdrożeniom.
3m 51s
8
Bramkowanie wdrożeń za pomocą Environments
Odkryj, jak mapować workflows GitHub Actions na zewnętrzne cele wdrożeniowe za pomocą Environments, aby wymuszać ręczne zatwierdzenia i izolować secrets.
4m 11s
9
Bezhasłowy dostęp do chmury przez OIDC
Wyeliminuj długoterminowe dane uwierzytelniające do chmury ze swoich repozytoriów. Dowiedz się, jak używać OpenID Connect (OIDC), aby bezpiecznie uwierzytelniać GitHub Actions w AWS, Azure i GCP.
4m 06s
10
Skalowanie pipelines zgodnie z DRY
Porównaj Reusable Workflows i Composite Actions. Dowiedz się, który mechanizm wybrać podczas standaryzacji pipelines CI/CD w całej organizacji.
4m 00s
11
Tworzenie Custom Actions: Docker kontra JavaScript
Przejmij kontrolę nad swoim pipeline, budując Custom Actions. Omawiamy kompromisy dotyczące wydajności i kompatybilności między akcjami w JavaScript a kontenerami Docker.
3m 47s
12
Zarządzanie flotą: Hosted kontra Self-Hosted Runners
Poruszaj się po granicach runners na GitHubie. Dowiedz się, kiedy polegać na maszynach hostowanych przez GitHuba, a kiedy Twoja architektura wymaga Self-Hosted runners.
3m 59s
13
Skalowanie w Kubernetes: Actions Runner Controller
Odkryj, jak Actions Runner Controller (ARC) orkiestruje efemeryczne, automatycznie skalujące się floty runners natywnie w Twoich klastrach Kubernetes.
3m 48s
14
Integralność łańcucha dostaw dzięki Attestations
Zabezpiecz swój łańcuch dostaw oprogramowania. Dowiedz się, jak generować niemożliwe do sfałszowania artifact attestations i provenance bezpośrednio ze swoich workflows.
3m 58s

Odcinki

1

Argumenty za GitHub Actions w Enterprise

4m 38s

Zestawienie GitHub Actions z tradycyjnymi narzędziami CI/CD, takimi jak Azure DevOps i GCP Cloud Build. Omawiamy architektoniczne zalety automatyzacji sterowanej zdarzeniami (event-driven), która działa tuż obok kodu źródłowego.

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. GitHub Actions, odcinek 1 z 14. Większość buildów w projektach enterprise traktuje się po macoszemu, w zupełnie oddzielnym narzędziu. Robisz pusha, następuje context switch i masz nadzieję, że webhook poprawnie odpali się na jakimś zdalnym serwerze gdzieś indziej. Podejście enterprise do GitHub Actions rozwiązuje ten problem, przenosząc egzekucję twojego pipeline'u bezpośrednio obok kodu źródłowego. Powszechnym błędem jest traktowanie GitHub Actions wyłącznie jako narzędzia CI/CD, jakby był to po prostu nowoczesny zamiennik Jenkinsa. Nazwij to po imieniu. To elastyczny, event-driven silnik automatyzacji, głęboko osadzony w twoim repozytorium. Reaguje na praktycznie każdą zmianę stanu na platformie kontroli wersji. Spójrz na standardowy setup enterprise wykorzystujący narzędzia takie jak GCP Cloud Build czy Azure DevOps. Kod źródłowy znajduje się w GitHubie, ale wykonanie odbywa się gdzie indziej. Wymaga to zarządzania cross-platformowymi service accountami, utrzymywania kruchych webhooków i synchronizowania kontroli dostępu między wieloma dostawcami. Kiedy pipeline wywala błąd, deweloperzy opuszczają swoje repozytorium, logują się do oddzielnej konsoli w chmurze i przekopują się przez logi odłączone od ich pull requesta. Bliskość kodu eliminuje te tarcia. Kiedy twój silnik automatyzacji jest wbudowany bezpośrednio w platformę kontroli wersji, eliminujesz koszty integracji. Tożsamość użytkownika, branch protection rules i kontekst zmiany kodu są natywnie rozumiane przez instancję obliczeniową uruchamiającą twój pipeline. Weź pod uwagę tradycyjny pipeline w oddzielnym narzędziu cloud build. Zazwyczaj nasłuchuje on commita, pobiera kod źródłowy, buduje artifact i raportuje prosty status pass lub fail z powrotem do repozytorium. Jego cały światopogląd ogranicza się do kompilacji kodu i deployu. GitHub Action działa na znacznie szerszą skalę. Ponieważ natywnie rozumie eventy z repozytorium, możesz zbudować workflow, który triggeruje się dokładnie w momencie otwarcia pull requesta. W jednym płynnym przebiegu może odczytać payload eventu, przypisać odpowiednich senior inżynierów jako reviewerów na podstawie tego, które konkretnie pliki się zmieniły, odpalić lintera i wrzucić wszelkie błędy składniowe bezpośrednio jako komentarze inline w konkretnych linijkach kodu. Deweloper rozwiązuje problemy bez opuszczania widoku pull requesta. Automatyzujesz sam workflow, a nie tylko build artifact. Z architektonicznego punktu widzenia, zmienia to twoje repozytorium z pasywnego storage'u w aktywny kontroler. Przestajesz automatyzować tylko swoje deploye, a zaczynasz automatyzować zarządzanie operacyjne. Jeśli issue zostanie oznaczone labelem critical, akcja może automatycznie sprovisionować tymczasową testową bazę danych. Jeśli luka w zabezpieczeniach zostanie wykryta przez automatyczny dependency scan, akcja może natychmiast otworzyć ticket, przypisać zespół security i zpingować twój wewnętrzny system czatu. Wszystko wykorzystuje dokładnie tę samą bazową infrastrukturę obliczeniową. W dużej organizacji możesz zdefiniować te workflowy centralnie i współdzielić je między setkami repozytoriów. Jeśli twój zespół security zaktualizuje wymaganą politykę skanowania kontenerów, aktualizuje jedną centralną akcję. Każde repozytorium wywołujące tę akcję natychmiast dziedziczy nowe wymagania security, bez konieczności przepisywania skryptów pipeline'ów przez poszczególne zespoły produktowe. Ta centralizacja zapewnia ogromną dźwignię dla zespołów platform engineering. Oto kluczowy wniosek. Architektura enterprise stale zmaga się z tool sprawlem. Każde nowe narzędzie do pipeline'ów zwiększa cognitive load, wymaga dedykowanego maintenance'u i tworzy kolejną powierzchnię dla polityk security. Konsolidując swoją warstwę egzekucji bezpośrednio w GitHubie, standaryzujesz sposób zachowania każdego repozytorium. Dokładnie ta sama infrastruktura, która deployuje twoje produkcyjne mikroserwisy, zarządza również maintenance'em twojego repozytorium. Największą zaletą architektoniczną GitHub Actions nie jest to, że ma szybsze build agenty albo lepszy caching. Chodzi o to, że usuwa granicę między deweloperskim workflowem a systemem Continuous Integration. Jeśli uważasz te odcinki za przydatne i chcesz wesprzeć program, możesz wyszukać DevStoriesEU na Patreonie. Dzięki za wysłuchanie, happy coding wszystkim!
2

Model mentalny wykonywania

3m 48s

Techniczna analiza hierarchii w GitHub Actions. Zrozum kluczowe relacje między Workflows, Jobs, Steps i Actions.

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. GitHub Actions, odcinek 2 z 14. Workflow to nie tylko prosty skrypt, który wykonuje się z góry na dół. To zrównoleglona maszyna stanów, która rozdziela twój kod na wiele maszyn wirtualnych dokładnie w tym samym czasie. Jeśli napiszesz konfigurację oczekując jednego ciągłego procesu, twoje dane znikną w połowie. Zrozumienie modelu mentalnego wykonywania kodu pozwala tego uniknąć. Na najwyższym poziomie znajduje się workflow. To konfigurowalny, zautomatyzowany proces zdefiniowany w pliku YAML w twoim repozytorium. Zawiera on plan tego, co powinno się wydarzyć po jego uruchomieniu. Sam workflow nie wykonuje kodu bezpośrednio. Zarządza on kolejnym poziomem w dół. Workflow zawiera jednego lub więcej jobów. To tutaj ustalane są fizyczne granice egzekucji. Domyślnie każdy job w workflow uruchamia się równolegle. Jeśli zdefiniujesz build job i test job, GitHub stawia dla każdego z nich osobną maszynę wirtualną, zwaną runnerem. Startują one dokładnie w tym samym czasie. Nie wiedzą nic o sobie nawzajem. Build job działa na runnerze A, a test job na runnerze B. Ponieważ wykonują się na zupełnie różnych maszynach wirtualnych, nie współdzielą systemu plików, zmiennych środowiskowych ani pamięci. Wewnątrz joba model wykonywania zmienia się całkowicie. Job składa się z sekwencji stepów. Podczas gdy joby działają równolegle na różnych maszynach, stepy uruchamiają się sekwencyjnie na dokładnie tej samej maszynie. Step pierwszy kończy się, zanim zacznie się step drugi. Ponieważ działają na tym samym runnerze, stepy współdzielą dane. W naszym build jobie, step pierwszy może pobrać kod twojej aplikacji. Step drugi go kompiluje. Step trzeci go pakuje. Ponieważ te stepy wykonują się na tej samej maszynie wirtualnej, step drugi natywnie odczytuje pliki pobrane przez step pierwszy. To prowadzi do częstego nieporozumienia. Ludzie często mylą stepy z actions. Step to nie action. Step to po prostu jednostka wykonania w ramach joba. To slot w twojej sekwencji. Możesz wypełnić ten slot na dwa sposoby. Możesz napisać surową komendę shellową albo wywołać action. Action to spakowany, reużywalny blok kodu zaprojektowany do wykonania określonego, złożonego zadania, takiego jak konfiguracja środowiska językowego. Action to reużywalny payload. Step to kontener, który trzyma go wewnątrz sekwencji joba. Spójrzmy ponownie na nasz scenariusz budowania i testowania. Workflow startuje. Dwa runnery odpalają się jednocześnie. Na build runnerze, stepy wykonują się jeden po drugim. Pierwszy step wywołuje checkout action, aby pobrać repozytorium. Drugi step uruchamia komendę shellową, żeby skompilować kod. Te stepy płynnie współdzielą lokalną przestrzeń dyskową. Tymczasem na test runnerze, w izolacji wykonuje się zupełnie inna sekwencja stepów. Jeśli twój test job potrzebuje skompilowanego wyniku z build joba, nie może po prostu zajrzeć na dysk twardy. Test job znajduje się na innym serwerze. Oto kluczowy wniosek. Granica joba to fizyczna granica maszyny wirtualnej, co oznacza, że pisanie workflow w GitHub Actions to tak naprawdę ćwiczenie z mapowania infrastruktury. Dzięki za wspólny czas. Mam nadzieję, że dowiedziałeś się czegoś nowego.
3

Triggers i filtry oparte na zdarzeniach

4m 12s

Szczegółowe omówienie event triggers w GitHub Actions. Dowiedz się, jak skonfigurować precyzyjne filtry ścieżek i gałęzi, aby dokładnie kontrolować, kiedy uruchamiają się Twoje workflows.

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. GitHub Actions, odcinek 3 z 14. Pojedynczy, automatyczny commit jest pushowany do twojego repozytorium. Ten commit triggeruje workflow. Ten workflow robi kolejny commit, który znowu uruchamia workflow. W ciągu kilku minut przepalasz setki minut w przypadkowej, nieskończonej pętli. Sposobem, aby temu zapobiec i dokładnie kontrolować, kiedy wykonują się twoje workflowy, są event-driven triggery i filtry. Każdy workflow w GitHub Actions zaczyna się od słowa kluczowego on. To mówi GitHubowi, które eventy powinny obudzić twój workflow. Możesz określić pojedynczy event, taki jak push, albo wiele eventów w tablicy. Ale eventy to nie zawsze proste triggery. Niektóre eventy, takie jak issues czy pull requesty, mają wiele typów aktywności. Kiedy issue jest otwierane, edytowane lub zamykane, odpala ten sam bazowy event. Jeśli po prostu napiszesz, że workflow działa na issues, uruchomi się dla wszystkich tych aktywności. Żeby być precyzyjnym, określasz dokładne typy aktywności. Możesz powiedzieć GitHubowi, żeby uruchamiał workflow tylko wtedy, gdy issue jest otwierane, ignorując edycje czy zamknięcia. To oszczędza minuty i zapobiega niepotrzebnemu przetwarzaniu. Typy aktywności ogarniają to, co się wydarzyło, ale filtry branchy i pathów określają, gdzie to się wydarzyło. Kiedy triggerujesz workflow na push lub pull request, zazwyczaj nie chcesz, żeby odpalał się na każdym pojedynczym branchu. Używasz filtrów branchy, żeby celować w konkretne miejsca, takie jak branch main albo branche release'owe. Możesz też filtrować po pathach. Jeśli developer poprawi literówkę w pliku readme, nie musisz uruchamiać całego test suite'a. Filtry pathów pozwalają ci dołączać lub wykluczać konkretne pliki i katalogi. Oto kluczowa sprawa. Kiedy mieszasz pozytywne i negatywne filtry pathów, kolejność, w jakiej je zapiszesz, ma znaczenie. Pozytywny filtr mówi workflowowi, żeby się uruchomił, jeśli konkretny path się zmieni. Negatywny filtr, oznaczony wykrzyknikiem, mówi workflowowi, żeby ignorował zmiany w danym pathu. GitHub ewaluuje je z góry na dół. Jeśli umieścisz negatywny filtr po pozytywnym, ten negatywny nadpisze pozytywny dla wszystkich pasujących plików. Przećwiczmy to w praktyce. Chcesz ztriggerować build za każdym razem, gdy kod jest pushowany do brancha main, ale chcesz zaoszczędzić pieniądze, ignorując zmiany, które wpływają tylko na dokumentację. Pod słowem kluczowym on określasz event push. Poniżej definiujesz filtr brancha dla main. Następnie dodajesz filtr paths. Możesz zacząć od pozytywnego filtra dla wszystkiego, używając wildcarda. Tuż pod nim dodajesz negatywny filtr dla folderu docs, celując konkretnie w pliki markdown. Jeśli commit modyfikuje tylko plik markdown w folderze docs, workflow pozostaje uśpiony. Jeśli commit modyfikuje plik pythona i plik markdown, workflow rusza, ponieważ plik pythona triggeruje pozytywny filtr. A teraz wróćmy do tej nieskończonej pętli. Kiedy twój workflow działa, GitHub dostarcza tymczasowe dane uwierzytelniające, zwane GitHub Token, żeby uwierzytelnić się w repozytorium. Z założenia, żadne eventy ztriggerowane przy użyciu tego konkretnego tokena nie utworzą nowych uruchomień workflowu. To wbudowany mechanizm bezpieczeństwa, który zapobiega rekurencyjnym pętlom. Jednak jeśli twój workflow używa Personal Access Token, żeby commitować kod albo pushować tagi, ta siatka bezpieczeństwa znika. Nowy commit ztriggeruje kolejne uruchomienie workflowu, które zrobi kolejny commit, tworząc nieskończoną pętlę. Jeśli musisz użyć Personal Access Token, musisz być niezwykle zdyscyplinowany ze swoimi filtrami branchy i pathów, żeby upewnić się, że automatyczny commit nie spełnia warunków triggera dla tego workflowu. Najskuteczniejszym sposobem na optymalizację kosztów obliczeniowych nie jest pisanie szybszego kodu, ale po prostu upewnienie się, że twoje workflowy uruchamiają się tylko wtedy, kiedy absolutnie muszą. Dzięki za wysłuchanie, udanego kodowania wszystkim!
4

Ewaluacja stanu za pomocą Variables i Contexts

4m 10s

Zrozum kluczowe różnice między environment variables a GitHub Contexts. Dowiedz się, kiedy każde z nich jest ewaluowane w cyklu życia workflow.

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. GitHub Actions, odcinek 4 z 14. Próbujesz użyć zmiennej środowiskowej runnera, aby określić, czy job powinien wystartować, a twój pipeline kończy się błędem, zanim w ogóle uruchomi maszynę. Jesteś pewien, że zmienna istnieje, ale GitHub zachowuje się, jakby była pusta. Problemem nie jest twoja zmienna, tylko twój timing. Żeby to naprawić, musimy porozmawiać o ewaluacji stanu przy użyciu zmiennych i kontekstów. W GitHub Actions stan twojego workflow jest ewaluowany w dwóch zupełnie oddzielnych fazach, które dzieją się w dwóch zupełnie różnych miejscach. To jest zasadnicza różnica między kontekstem a zmienną środowiskową. Przyjrzyjmy się najpierw kontekstom. Konteksty to zbiory informacji ewaluowane bezpośrednio przez GitHuba, zanim twój workflow w ogóle zostanie wysłany do runnera. Przechowują dane o uruchomieniu workflow, repozytorium, evencie webhooka, który ztriggerował to uruchomienie, oraz o użytkowniku, który je zainicjował. Ponieważ GitHub ewaluuje konteksty natychmiast, możesz ich użyć do kontrolowania struktury swojego pipeline'u. Dostęp do kontekstu uzyskujesz za pomocą określonej składni wyrażenia, zazwyczaj znaku dolara, po którym następują podwójne nawiasy klamrowe zawierające nazwę kontekstu. Z drugiej strony, domyślne zmienne środowiskowe są ewaluowane później, na właściwej maszynie runnera, która wykonuje twój job. Kiedy runner startuje, automatycznie ustawia kilka domyślnych zmiennych środowiskowych, takich jak nazwa repozytorium czy aktualny branch. Odwołujesz się do nich dokładnie tak samo, jak w zwykłym skrypcie bash lub PowerShell. Możesz również zdefiniować własne zmienne środowiskowe za pomocą klucza env w swoim pliku workflow. Klucz env możesz przypisać do całego workflow, pojedynczego joba lub konkretnego stepu. Oto kluczowa sprawa. Cykl życia dyktuje, czego możesz użyć i gdzie. Częstym błędem jest próba użycia zmiennej środowiskowej runnera wewnątrz warunku if na poziomie joba. Jeśli każesz jobowi uruchomić się tylko wtedy, gdy konkretna zmienna środowiskowa bash jest równa określonej wartości, workflow zakończy się błędem. Runner jeszcze nie wystartował. Maszyna nie istnieje, więc zmienna środowiskowa również nie istnieje. Żeby podejmować decyzje zanim runner wystartuje, musisz użyć kontekstu. Przyjrzyjmy się praktycznemu scenariuszowi. Chcesz, żeby deploy job uruchomił się tylko wtedy, gdy kod zostanie zmergowany do brancha main. Na poziomie joba piszesz warunek if. Używasz wyrażenia kontekstowego, żeby sprawdzić, czy kontekst github dot ref jest równy stringowi refs slash heads slash main. GitHub ewaluuje to natychmiast. Jeśli to prawda, GitHub provisionuje runnera i wysyła do niego joba. Kiedy job jest już na runnerze, a twoje stepy zaczynają się wykonywać, przechodzisz na zmienne środowiskowe. Wewnątrz stepu ze skryptem bash w tym samym jobie, możesz potrzebować nazwy brancha, żeby otagować build artifact. Tutaj po prostu wpisujesz znak dolara, a po nim GITHUB underscore REF. Runner odczytuje to ze swojego lokalnego środowiska systemu operacyjnego. Odwołujesz się do dokładnie tego samego fragmentu danych, nazwy brancha, ale uzyskujesz do niego dostęp przez zupełnie inne mechanizmy, w zależności od tego, gdzie aktualnie znajduje się wykonanie. Konteksty kierują workflow na serwerach GitHuba. Zmienne środowiskowe sterują wykonywaniem skryptów na runnerze. Jeśli kiedykolwiek będziesz walczyć z pustymi zmiennymi w logice swojego workflow, zadaj sobie pytanie, czy maszyna ewaluująca tę logikę w ogóle już wystartowała. Jak zawsze, dziękuję za wysłuchanie. Do zobaczenia w następnym odcinku.
5

Granica bezpieczeństwa: Secrets i GITHUB_TOKEN

4m 20s

Techniczne spojrzenie na zarządzanie secrets w GitHub Actions. Omawiamy efemeryczny GITHUB_TOKEN oraz hierarchię secrets na poziomie repozytorium i organizacji.

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. GitHub Actions, odcinek 5 z 14. Programiści często generują długoterminowe Personal Access Tokens do podstawowych zadań w repozytorium, zostawiając stałe credentials w swoim codebase. Ale do większości interakcji z GitHubem w ogóle nie musisz tworzyć tokena — w każdym jobie czeka na ciebie bezpieczny, efemeryczny token. I to jest temat dzisiejszego odcinka: Granica bezpieczeństwa: secrets i GITHUB_TOKEN. Kiedy triggerujesz workflow, GitHub automatycznie dostarcza unikalny secret o nazwie GITHUB_TOKEN. To nie jest standardowy Personal Access Token. Działa on jako krótkotrwały installation access token dla GitHub App. Istnieje wyłącznie na czas trwania joba w workflow. W momencie zakończenia joba, albo po maksymalnie 24 godzinach, token wygasa i staje się całkowicie bezużyteczny. Częstym błędem jest generowanie stałego Personal Access Token tylko po to, żeby workflow mógł dodać label do issue albo wrzucić komentarz do pull requesta. To niepotrzebnie zwiększa powierzchnię ataku. Wbudowany GITHUB_TOKEN ma już uprawnienia potrzebne do interakcji z repozytorium, które ztriggerowało workflow. Jeśli twój job musi dodać label do issue, przekazujesz ten wbudowany token do stepu wykonującego API call. Żadne stałe credentials nie są nigdy tworzone, przechowywane ani ujawniane. To by było na tyle, jeśli chodzi o interakcje z samym GitHubem. Ale twój workflow nieuchronnie będzie musiał komunikować się ze światem zewnętrznym. I tutaj do gry wchodzą customowe, zaszyfrowane secrets. Kiedy tworzysz customowy secret, nie leży on jako plain text na serwerze GitHuba. Wartość jest szyfrowana lokalnie przy użyciu sealed box z biblioteki Libsodium, zanim w ogóle zostanie przesłana. Szyfrowanie opiera się na kryptografii klucza publicznego. Kiedy dodajesz secret przez web interface lub API, GitHub dostarcza klucz publiczny. Twój klient używa tego klucza, żeby zamknąć tego sealed boxa. Tylko odizolowana maszyna wirtualna runnera posiada odpowiedni klucz prywatny wymagany do otwarcia tego boxa i odszyfrowuje payload dokładnie w momencie wykonywania joba. Możesz definiować te zaszyfrowane secrets na różnych poziomach, w zależności od twojej architektury. Secrets na poziomie repozytorium dotyczą pojedynczego codebase'u. Secrets na poziomie organizacji pozwalają ci współdzielić jeden credential, na przykład hasło do produkcyjnej bazy danych, między wieloma repozytoriami. To centralizuje zarządzanie credentials, ale wymaga ścisłej kontroli. Secrets na poziomie organizacji używają access policies, w których jawnie definiujesz, które repozytoria mają prawo odczytać dany secret. Zastosujmy to do konkretnego scenariusza. Załóżmy, że masz hasło do bazy danych na poziomie organizacji, wymagane do stepu migracji bazy danych. Nie chcesz, żeby to hasło było dostępne dla całego workflow. GitHub Actions wymusza tutaj ścisłą granicę bezpieczeństwa. Secrets nie są automatycznie wstrzykiwane do środowiska każdego stepu. Musisz jawnie zmapować secret do zmiennej środowiskowej w konkretnym stepie, który go wymaga. Pisząc plik workflow, uzyskujesz dostęp do zaszyfrowanej wartości za pomocą konkretnego context reference, wywołując ją z obiektu secrets i przypisując do lokalnej zmiennej środowiskowej. Ponieważ zmapowałeś to jawnie, step przed migracją nie widzi hasła, i step po niej też go nie widzi. Oto kluczowy wniosek. Bezpieczeństwo w automatyzacji polega na minimalizowaniu czasu życia i ograniczaniu scope'u. Polegaj na efemerycznym GITHUB_TOKEN do wewnętrznych akcji w repozytorium, żeby uniknąć zarządzania stałymi credentials, i ściśle mapuj zaszyfrowane secrets tylko do poszczególnych stepów, które wymagają dostępu z zewnątrz. To tyle w tym odcinku. Do usłyszenia następnym razem!
6

Optymalizacja danych: Caching kontra Artifacts

4m 41s

Poznaj dokładną różnicę między Dependency Caching a Workflow Artifacts. Przestań spowalniać swoje buildy przez użycie niewłaściwego mechanizmu przechowywania danych.

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. GitHub Actions, odcinek 6 z 14. Konfigurujesz workflow z kilkoma jobami, i żeby upewnić się, że drugi job ma wszystko, czego potrzebuje, pakujesz cały folder z zależnościami i przekazujesz go dalej. Ale nagle twój build trwa pięć minut dłużej, a zużycie storage'u przebija sufit. Problemem jest fundamentalne pomieszanie dwóch różnych mechanizmów danych i właśnie o tym jest ten odcinek: Optymalizacja danych: Caching kontra Artefakty. Od razu to sobie wyjaśnijmy. Caching i artefakty przenoszą pliki między twoimi runnerami w GitHub Actions, ale rozwiązują zupełnie inne problemy. Pomyśl o artefaktach jako o tym, co twój workflow produkuje. Pomyśl o cachingu jako o tym, co twój workflow konsumuje. Jeśli zamienisz te role, po cichu stworzysz wąskie gardło w całym swoim pipeline. Artefakty to wygenerowane pliki, które chcesz zachować po zakończeniu joba. Może to być skompilowana binarka, raport z test coverage, albo spakowane archiwum katalogu z twoim finalnym buildem. Istnieją z dwóch głównych powodów. Po pierwsze, żeby pozwolić ci pobrać końcowy wynik twojego workflow po jego zakończeniu. Po drugie, żeby przekazywać wygenerowane dane między różnymi jobami w ramach dokładnie tego samego workflow run. Ponieważ każdy job działa na świeżej maszynie wirtualnej, wszelkie pliki utworzone w pierwszym jobie są natychmiast tracone po jego zakończeniu, chyba że jawnie je zuploadujesz. Używając akcji upload artifact, zapisujesz te pliki w storage'u GitHuba. Następnie, drugi job używa akcji download artifact, żeby zaciągnąć je do swojego własnego, czystego workspace'u. Teraz porównaj to z cachingiem zależności. Caching to czysta optymalizacja wydajności, zaprojektowana, żeby przyspieszyć twój workflow w różnych uruchomieniach na przestrzeni czasu. Kiedy budujesz soft, zazwyczaj pobierasz tysiące zewnętrznych zależności, takich jak pakiety z NPM czy pip. Pobieranie ich przez sieć przy każdym pojedynczym uruchomieniu jest wolne. Zamiast pobierać świeże zależności za każdym razem, akcja cache zapisuje twój pobrany folder z zależnościami na serwerach cache. Przypisuje temu cache'owi unikalny klucz, prawie zawsze na podstawie hasha twojego lock file'a. Przy jutrzejszym workflow run, GitHub sprawdza, czy lock file pasuje do istniejącego klucza. Jeśli tak, przywraca folder bezpośrednio do twojego runnera w kilka sekund, całkowicie omijając package registry. Oto najważniejsza rzecz. Największym błędem, jaki możesz popełnić, jest użycie akcji upload artifact do przenoszenia ogromnego folderu z zależnościami, takiego jak node modules, między jobami. Artefakty przetwarzają dane poprzez ich zipowanie, uploadowanie, pobieranie i rozpakowywanie. Robienie tego z dziesiątkami tysięcy małych plików tekstowych dodaje ogromne opóźnienia sieciowe do twojego czasu wykonania i zżera limity storage'u na twoim koncie. Artefakty nie są stworzone dla czystej prędkości; są zbudowane z myślą o bezpiecznym transferze danych i ich trwałym przechowywaniu. Z drugiej strony, cache jest wysoce zoptymalizowany pod kątem szybkiego zaciągania ciężkich drzew zależności, a do tego automatycznie wygasa i usuwa się, żeby oszczędzać miejsce. Wyobraź sobie poprawny pipeline, który właściwie wykorzystuje oba te mechanizmy. Masz workflow z jobem build i jobem deploy. W jobie build, twój pierwszy krok używa akcji cache, żeby natychmiast przywrócić twoje zależności NPM z wczorajszego uruchomienia. Twój kod kompiluje się szybko, produkując finalną binarkę aplikacji. Następnie używasz akcji upload artifact, żeby zapisać tylko ten jeden plik binarny. Job build się kończy, a runner zostaje zniszczony. Job deploy odpala się na nowym runnerze. Nie potrzebuje cache'u i nie potrzebuje zależności NPM. Używa po prostu akcji download artifact, żeby zgarnąć skompilowaną binarkę, którą właśnie zbudowałeś, a następnie wypycha ją na twój serwer produkcyjny. Caching to tymczasowy skrót dla rzeczy, które pobierasz, podczas gdy artefakty to niezbędne przekazanie rzeczy, które tworzysz. Dzięki, że wpadłeś. Mam nadzieję, że dowiedziałeś się czegoś nowego.
7

Kontrolowanie przepływu za pomocą Concurrency

3m 51s

Opanuj kontrolę nad wykonywaniem workflow. Dowiedz się, jak używać słowa kluczowego concurrency, aby anulować nadmiarowe uruchomienia i zapobiegać nakładającym się wdrożeniom.

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. GitHub Actions, odcinek 7 z 14. Programista w ciągu pięciu minut pushuje trzy szybkie commity do otwartego pull requestu. Jeśli twój serwer CI mieli trzy nadmiarowe zestawy testów, przepalasz pieniądze. Potrzebujesz sposobu, żeby powiedzieć systemowi, że liczy się tylko najnowszy kod, i dokładnie to robi kontrolowanie flow za pomocą concurrency. Domyślnie GitHub Actions uruchamia ztriggerowane workflowy równolegle. Jeśli zrobisz pusha pięć razy, odpali pięć niezależnych runnerów. Przy podstawowych checkach, marnuje to minuty runnera. Przy deployach jest to wręcz niebezpieczne. Jeśli dwa runy workflow próbują zrobić deploy na to samo środowisko stagingowe w tym samym czasie, tworzysz race condition. Starszy commit może nawet skończyć deploy po tym nowszym, nadpisując twoje zmiany i zostawiając środowisko w przestarzałym stanie. Możesz to naprawić używając słowa kluczowego concurrency. Możesz je dodać na najwyższym poziomie całego workflow albo ograniczyć do konkretnego joba. Ten mechanizm opiera się całkowicie na grupach concurrency. Grupa concurrency to po prostu string z nazwą, którą definiujesz. Jeśli dwa runy mają dokładnie tę samą nazwę grupy, GitHub wymusza między nimi limity concurrency. Wiele osób robi błąd i hardkoduje tego stringa. Jeśli ustawisz nazwę grupy po prostu na słowo deploy, to push do twojego brancha testowego anuluje aktywny deploy na głównym branchu produkcyjnym. Nazwa grupy musi być dynamiczna. Budujesz ją używając zmiennych kontekstowych, takich jak referencja do obecnego brancha. Jeśli nazwiesz grupę używając numeru pull requestu, to limity concurrency będą dotyczyć tylko pushy w ramach tego konkretnego pull requestu. Twój main branch pozostaje całkowicie nienaruszony. Kiedy nowy workflow zostanie ztriggerowany, GitHub sprawdza, czy jakiś run jest już aktywny dla tej grupy concurrency. Jeśli tak, domyślnym zachowaniem jest umieszczenie nowego runa w stanie pending. Czeka on w kolejce. I tu jest kluczowa sprawa. Kolejka mieści tylko jednego pending joba. Jeśli trzeci run zostanie ztriggerowany, podczas gdy pierwszy jest w trakcie działania, a drugi jest pending, to ten drugi run zostaje wyrzucony z kolejki. Tylko absolutnie najnowszy run ma szansę poczekać. Czekanie jest bezpieczniejsze dla deployów, ale przy testowaniu pull requestów, czekanie wciąż zżera niepotrzebnie czas. I tu wchodzi do gry ustawienie cancel-in-progress. To flaga boolean, którą dodajesz pod definicją swojej grupy concurrency. Kiedy ustawisz cancel-in-progress na true, zmieniasz zachowanie z kolejkowania na przerywanie. Wróćmy do dewelopera, który pushuje trzy szybkie commity. Pierwszy push triggeruje zestaw testów. Dwie minuty później robi kolejnego pusha. Ponieważ ustawiłeś grupę concurrency na nazwę brancha i włączyłeś cancel-in-progress, GitHub widzi nowy run, natychmiast przerywa aktywny zestaw testów dla pierwszego commita i zaczyna testować drugiego commita. Kiedy minutę później wlatuje trzeci push, przerywa on drugi run i odpala trzeci. Deweloper i tak dostaje ostateczny pass lub fail, ale ty zapłaciłeś za wykonanie testów tylko raz. Kontrola concurrency zmienia twoje pipeline'y CI z reaktywnego systemu, który ślepo wykonuje każdy trigger, w system świadomy stanu, który zużywa zasoby tylko na kod, który faktycznie ma znaczenie. Dzięki za wysłuchanie, udanego kodowania wszystkim!
8

Bramkowanie wdrożeń za pomocą Environments

4m 11s

Odkryj, jak mapować workflows GitHub Actions na zewnętrzne cele wdrożeniowe za pomocą Environments, aby wymuszać ręczne zatwierdzenia i izolować secrets.

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. GitHub Actions, odcinek 8 z 14. Twoje dane uwierzytelniające do produkcyjnej bazy danych nigdy nie powinny być dostępne dla losowego pull requesta z feature brancha. A jednak, jeśli wszystkie twoje sekrety są przechowywane na poziomie repozytorium, każdy workflow może je potencjalnie przejąć. Rozwiązanie tej luki w zabezpieczeniach to właśnie powód, dla którego potrzebujesz funkcji Gating Deployments with Environments. Najpierw musimy wyjaśnić powszechne nieporozumienie. Environment w GitHub Actions to nie jest fizyczny serwer. GitHub nie stawia za ciebie maszyny wirtualnej ani instancji w chmurze o nazwie production. Environment to czysto logiczna granica skonfigurowana w ustawieniach twojego repozytorium na GitHubie. Działa jak gatekeeper, kontrolując, kiedy dany job może się uruchomić i jakie dane ten job może zobaczyć. Głównym powodem istnienia tej funkcji jest egzekwowanie zasad release'ów i ochrona wrażliwych danych. Kiedy tworzysz environment, możesz bezpośrednio do niego podpiąć określone sekrety i zmienne. Możesz utworzyć jeden environment o nazwie staging i drugi o nazwie production. Każdy z nich dostaje swój własny, unikalny zestaw kluczy API, przechowywany pod dokładnie tą samą nazwą zmiennej. W pliku workflow łączysz konkretnego joba z environmentem, po prostu podając jego nazwę. Kiedy workflow startuje, job odwołujący się do environmentu staging dostaje klucze ze stagingu. Job odwołujący się do environmentu production dostaje klucze produkcyjne. To całkowicie izoluje twoje wrażliwe dane. Job odpalony na feature branchu nie może odczytać kluczy produkcyjnych, ponieważ nie działa w kontekście environmentu production. Ale izolowanie sekretów to tylko połowa możliwości environmentów. Drugą połową są protection rules. Te reguły działają jak ścisłe bramki w twoim deployment pipeline. Najpopularniejszą z protection rules jest required reviewer. Spójrzmy, jak to wygląda w prawdziwym scenariuszu. Masz workflow, który buduje twoją aplikację i automatycznie robi deploy na staging. Ten job kończy się sukcesem. Kolejny job w tym workflow jest skonfigurowany tak, aby zrobić deploy na produkcję, i odwołuje się do twojego environmentu production. Jeśli masz ustawioną regułę required reviewer dla tego environmentu, workflow zatrzymuje się w tym momencie. Job pauzuje. Nie jest wysyłany do runnera, a produkcyjne klucze API pozostają bezpiecznie zablokowane. GitHub wysyła powiadomienie do wyznaczonego menedżera lub zespołu z informacją, że deploy czeka na akceptację. Workflow będzie wisiał w tym stanie pending, dopóki nie zostanie podjęta jakaś akcja. Bramka otwiera się dopiero wtedy, gdy menedżer kliknie approve w interfejsie GitHuba. W tym dokładnie momencie job jest wysyłany do dostępnego runnera, produkcyjne sekrety są odszyfrowywane i wstrzykiwane, a skrypt deploymentu się wykonuje. Możesz nałożyć inne protection rules na manualne zatwierdzenia. Jedną z opcji jest wait timer, który wymusza opóźnienie joba o określoną liczbę minut przed jego startem. Daje ci to bufor na anulowanie rolloutu, jeśli zauważysz skok liczby błędów na swoich dashboardach monitorujących zaraz po deployu na staging. Możesz również skonfigurować deployment branches. To ogranicza environment tak, że akceptuje on tylko joby odpalane z konkretnych branchy, takich jak twój main branch albo określone release tagi. Jeśli developer spróbuje wymusić joba deploymentu na produkcję z losowego bugfix brancha, bramka environmentu po prostu odrzuci ten run. Oto kluczowy wniosek. Environmenty oddzielają mechanikę deploymentu od kontroli dostępu. Twój plik workflow opisuje dokładne kroki wymagane do zrobienia deployu twojego kodu, ale ustawienia environmentu w GitHubie dyktują, kto ma uprawnienia, by na to pozwolić, i które sekrety są wtedy odblokowywane. Jeśli podobają ci się te techniczne deep dive'y, możesz wesprzeć program, wyszukując DevStoriesEU na Patreonie. Dzięki za wysłuchanie, happy coding wszystkim!
9

Bezhasłowy dostęp do chmury przez OIDC

4m 06s

Wyeliminuj długoterminowe dane uwierzytelniające do chmury ze swoich repozytoriów. Dowiedz się, jak używać OpenID Connect (OIDC), aby bezpiecznie uwierzytelniać GitHub Actions w AWS, Azure i GCP.

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. GitHub Actions, odcinek 9 z 14. Najbezpieczniejsze kredencjały chmurowe to te, które wygasają pięć minut po zakończeniu twojego deploymentu. Mimo to, wiele zespołów wciąż kopiuje długo żyjące klucze administratora do ustawień repozytorium, mając nadzieję, że nigdy nie wyciekną. Dzisiaj to naprawimy, przyglądając się bezhasłowemu dostępowi do chmury przez OIDC. Historycznie, łączenie workflow w GitHubie z dostawcą chmurowym oznaczało generowanie klucza dostępu w AWS, Google Cloud lub Azure i zapisywanie go jako długo żyjącego GitHub Secret. Jeśli ten Secret by wyciekł, każdy mógłby go użyć z dowolnego miejsca, dopóki administrator ręcznie by go nie unieważnił. Ludzie często myślą, że OpenID Connect, czyli OIDC, to po prostu nowy typ Secretu, który wklejasz do swojego repozytorium. Wcale tak nie jest. OIDC całkowicie zastępuje przechowywane Secrety. To protokół, który w locie generuje dynamiczny, kryptograficzny token, aby udowodnić tożsamość workflow twojemu dostawcy chmurowemu. GitHub działa tutaj jako OIDC Identity Provider. Kiedy workflow się uruchamia, może poprosić GitHuba o wystawienie JSON Web Token, czyli JWT. Żeby to było możliwe, musisz dodać odpowiednie uprawnienie do swojego pliku workflow. Ustawiasz blok permissions tak, aby zezwolić na write access dla ID tokenu. To mówi GitHubowi, że workflow jest autoryzowany do wygenerowania kredencjałów tożsamości. Oto kluczowa sprawa. Ten token sam w sobie nie przyznaje dostępu. To po prostu podpisany cyfrowo dokument zawierający claimy. Claimy to fragmenty metadanych, które określają weryfikowalne fakty o aktualnie uruchomionym workflow. Token zawiera nazwę repozytorium, organizację, branch, środowisko i event, który wyzwolił ten run. Ponieważ GitHub kryptograficznie podpisuje ten token, twój dostawca chmurowy może zaufać tym claimom. Stanowi to fundament deploymentu w modelu zero-trust. Przyjrzyjmy się jobowi deploymentowemu, który pushuje obraz do AWS Elastic Container Registry. Workflow startuje i żąda tokenu OIDC od GitHuba. Token zostaje wygenerowany i zawiera claimy weryfikujące, że pochodzi on z brancha main twojego repozytorium backendowego. Następnie workflow wysyła ten token do AWS. AWS najpierw sprawdza podpis cyfrowy, aby upewnić się, że token rzeczywiście pochodzi od GitHuba. Następnie odczytuje claimy. Sprawdza te claimy z restrykcyjną trust policy, którą zdefiniowałeś wcześniej. Ta polityka może mówić, że akceptuje tokeny tylko z twojego konkretnego repozytorium i tylko wtedy, gdy workflow działa na branchu main. Ponieważ claimy się zgadzają, AWS akceptuje token. AWS nie zwraca permanentnego klucza. Zamiast tego wydaje tymczasowy access token. Ten token może być ważny przez zaledwie piętnaście minut. Twój workflow używa tych tymczasowych kredencjałów, aby spushować obraz kontenera do registry. Kiedy job się kończy, kredencjały wygasają. Nie ma tu niczego do rotowania i niczego zapisanego w GitHubie, co atakujący mógłby wyciągnąć. Konfigurując to, zwróć szczególną uwagę na subject claim, często nazywany sub claimem. To główne pole, którego dostawcy chmurowi używają do filtrowania dostępu. Domyślnie GitHub formatuje subject claim tak, aby zawierał nazwę repozytorium i referencję git, taką jak branch lub tag. Musisz upewnić się, że twoja chmurowa trust policy ściśle weryfikuje ten subject claim. Jeśli sprawdzisz tylko nazwę organizacji, każde repozytorium w twojej organizacji będzie mogło zażądać zasobów w chmurze. Łącząc tymczasowy dostęp do chmury z konkretnymi metadanymi workflow, gwarantujesz, że skompromitowane repozytorium nie będzie mogło dotknąć twojej infrastruktury, chyba że żądanie pochodzi z dokładnego brancha i środowiska, którym wyraźnie ufasz. To wszystko w tym odcinku. Dzięki za wysłuchanie i budujcie dalej!
10

Skalowanie pipelines zgodnie z DRY

4m 00s

Porównaj Reusable Workflows i Composite Actions. Dowiedz się, który mechanizm wybrać podczas standaryzacji pipelines CI/CD w całej organizacji.

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. GitHub Actions, odcinek 10 z 14. Kiedy zarządzasz continuous integration w pięćdziesięciu repozytoriach, kopiowanie i wklejanie dokładnie tego samego YAML-a to gotowy koszmar w utrzymaniu. Zmieniasz jedno narzędzie do skanowania bezpieczeństwa i nagle musisz ręcznie aktualizować pięćdziesiąt oddzielnych plików. Ten odcinek jest o skalowaniu DRY pipelines, żeby rozwiązać dokładnie ten problem. Żeby przestać się powtarzać w GitHub Actions, masz dwa główne narzędzia: Reusable Workflows i Composite Actions. Inżynierowie często wybierają to niewłaściwe, ponieważ oba zapobiegają duplikacji kodu. Composite Action to nie jest workflow. To po prostu zestaw steps. Reusable Workflow to kompletny pipeline, który grupuje całe jobs. Jeśli twoja współdzielona logika musi obejmować wiele maszyn, orkiestrować złożone zależności między jobs, albo bezpiecznie zarządzać secrets, musisz użyć Reusable Workflow. Composite Action bierze sekwencję steps, takich jak checkout kodu, konfiguracja środowiska językowego i instalacja zależności, i pakuje je w jedną customową akcję. Kiedy workflow używa tej akcji, wszystkie te spakowane steps wykonują się sekwencyjnie wewnątrz aktualnie istniejącego joba. Composite Action nie decyduje, na jakim runnerze się wykonuje. Działa tam, gdzie umieści ją nadrzędny job. Istnieje wyłącznie po to, żeby uporządkować powtarzalną logikę steps w ramach jednego środowiska wykonawczego. Reusable Workflows działają na znacznie wyższym poziomie architektonicznym. To kompletne pliki YAML, które może wyzwolić inny workflow. Workflow wysyłający żądanie to caller workflow, a ten uruchamiany to called workflow. Ponieważ called workflow definiuje całe jobs, to on kontroluje infrastrukturę. Jeden job wewnątrz Reusable Workflow może działać na runnerze Ubuntu, żeby zbudować aplikację, podczas gdy zależny job działa na runnerze macOS, żeby ją przetestować. Wyobraź sobie zespół Platform Engineering, który standaryzuje pipeline deploymentu w Node. Chcą mieć pewność, że każdy zespół uruchamia identyczne kontrole bezpieczeństwa przed wypuszczeniem kodu. Zamiast ufać pięćdziesięciu zespołom produktowym, że będą utrzymywać identyczne pliki YAML, inżynierowie platformy tworzą jeden centralny Reusable Workflow we współdzielonym repozytorium. Ten centralny plik definiuje dokładną sekwencję jobs wymaganych do skanowania, budowania i deployu aplikacji. Wtedy pięćdziesiąt repozytoriów produktowych tworzy minimalny caller workflow. Ten caller workflow zawiera tylko jeden job, który wskazuje bezpośrednio na współdzielony plik zespołu platformy za pomocą jego ścieżki. Przekazujesz dane konfiguracyjne w dół do called workflow używając inputs, określając parametry takie jak nazwa środowiska docelowego albo wersja Node'a. Caller workflow może też przekazywać w dół secrets. Możesz jawnie zmapować konkretne secrets, albo poinstruować called workflow, żeby po prostu odziedziczył wszystkie secrets dostępne dla callera. Kiedy zespół platformy musi zrotować deployment secret albo dodać nowe narzędzie do analizy statycznej, aktualizuje centralny called workflow. Natychmiast wszystkie pięćdziesiąt repozytoriów uruchamia nową kontrolę bezpieczeństwa przy kolejnym commicie. Zespoły produktowe nie dotykają żadnej konfiguracji. Oto kluczowy wniosek. Używaj Composite Actions, żeby ukryć chaotyczną logikę steps wewnątrz jednego środowiska, ale używaj Reusable Workflows, żeby wymusić ustandaryzowaną architekturę pipelines w całej organizacji. To wszystko w tym odcinku. Dzięki za wysłuchanie i buduj dalej!
11

Tworzenie Custom Actions: Docker kontra JavaScript

3m 47s

Przejmij kontrolę nad swoim pipeline, budując Custom Actions. Omawiamy kompromisy dotyczące wydajności i kompatybilności między akcjami w JavaScript a kontenerami Docker.

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. GitHub Actions, odcinek 11 z 14. Kontener gwarantuje dokładne wersje narzędzi, ale wiąże się z ukrytym opóźnieniem przy każdym pojedynczym uruchomieniu workflow. Spójność twojego środowiska może spowalniać twój zespół i zamykać go w jednym systemie operacyjnym, nawet jeśli nie zdajesz sobie z tego sprawy. Tworzenie custom actions: Docker kontra JavaScript rozwiązuje ten dylemat. Custom action to logika, którą piszesz raz i reużywasz w wielu repozytoriach. Tworząc ją, musisz wybrać architekturę uruchomieniową. Dwa główne modele to JavaScript i Docker. Wielu inżynierów domyślnie wybiera Docker actions, ponieważ zależy im na absolutnym bezpieczeństwie i przewidywalnych zależnościach. Zakładają, że kontener to najpewniejszy wybór. W rzeczywistości zbudowanie Docker action trwale blokuje możliwość użycia twojego narzędzia przez runnery na macOS lub Windows. Docker actions wykonują się tylko w środowiskach linuksowych. JavaScript actions przyjmują inne podejście. Wykonują się bezpośrednio na maszynie hosta. Piszesz swoją logikę, kompilujesz ją do pojedynczego pliku ze wszystkimi zależnościami i w metadanych akcji wskazujesz na ten entry file. Kiedy workflow się uruchamia, runner używa swojego wbudowanego runtime'u Node do wykonania twojego skryptu. To uniezależnia twoją logikę od systemu operacyjnego pod spodem. Dokładnie ta sama akcja będzie działać natywnie na runnerach z Linuxem, macOS i Windowsem bez żadnych modyfikacji. Z kolei Docker container actions pakują system operacyjny, zależności systemowe i twój kod w jedną, niemutowalną jednostkę. To ty dyktujesz dokładne środowisko. Runner czyta Dockerfile dostarczony przez twoją akcję, buduje lub pulluje obraz kontenera i uruchamia twój kod w tej odizolowanej przestrzeni. Oto kluczowy wniosek. Ścisła izolacja Docker action wprowadza karę w postaci cold-startu. Wyobraź sobie zespół budujący customowe narzędzie do lintowania kodu, by udostępniać je w całej organizacji. Jeśli zbudują je jako Docker action, runner musi spullować ten obraz kontenera, zanim będzie mógł przeanalizować choćby jedną linijkę kodu. To może dodać piętnaście sekund opóźnienia na starcie każdego linting joba. Przy setkach pull requestów dziennie, ten czas bezczynności kumuluje się w godziny zmarnowanego compute'u. Jeśli zespół zbuduje identyczną logikę lintingu w JavaScript, runner po prostu pobiera plik skryptu i wykonuje go natychmiast. Twój wybór architektury dyktuje, jak twoja akcja zachowuje się w praktyce. Jeśli twoje narzędzie opiera się na złożonych systemowych binarkach, wymaga bardzo konkretnej wersji kompilatora języka lub wrappuje legacy Bash scripts, które są niestabilne poza określoną dystrybucją Linuxa, Docker jest właściwym wyborem. Płacisz ten latency tax w zamian za gwarantowaną stabilność. Jeśli twoim celem jest zbudowanie szybkiego, szeroko adoptowanego narzędzia, które działa w każdym typie projektu, JavaScript jest lepszą drogą. Wybór architektoniczny między Dockerem a JavaScriptem dla custom action nigdy nie dotyczy tego, w jakim języku programowania wolisz pisać. To twardy trade-off między ścisłą kontrolą środowiska a szybkością cross-platformowego wykonania. To tyle w tym temacie. Do usłyszenia następnym razem!
12

Zarządzanie flotą: Hosted kontra Self-Hosted Runners

3m 59s

Poruszaj się po granicach runners na GitHubie. Dowiedz się, kiedy polegać na maszynach hostowanych przez GitHuba, a kiedy Twoja architektura wymaga Self-Hosted runners.

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. GitHub Actions, odcinek 12 z 14. Cloud runnery GitHuba są niezwykle wygodne, dopóki twoje testy integracyjne nie muszą połączyć się z legacy bazą danych, bezpiecznie ukrytą za korporacyjnym firewallem. Nagle publiczny runner nie może uzyskać dostępu do twoich prywatnych danych. Właśnie tutaj do gry wchodzi temat Fleet Management: Hosted vs Self-Hosted Runners. Domyślnie GitHub Actions korzysta z runnerów hostowanych przez GitHuba. Kiedy uruchamia się workflow, GitHub stawia świeżą maszynę wirtualną. Możesz zażądać Ubuntu, Windowsa lub macOS. Runner wykonuje twojego joba, raportuje wynik, a następnie maszyna wirtualna jest natychmiast niszczona. Za każdym razem masz czystą kartę. Nie zarządzasz systemem operacyjnym, nie instalujesz łatek bezpieczeństwa i nie martwisz się o pliki pozostałe po poprzednim buildzie. Jednak ta izolacja to miecz obosieczny. Ponieważ te runnery znajdują się w infrastrukturze chmurowej GitHuba, działają na dynamicznych adresach IP i nie mają bezpośredniego dostępu do twoich sieci prywatnych. Jeśli masz wewnętrzną aplikację lub bazę danych, której nie można wystawić do publicznego internetu, potrzebujesz runnera, który działa wewnątrz twojej własnej strefy bezpieczeństwa. To jest właśnie self-hosted runner. Ty dostarczasz sprzęt. Może to być fizyczny serwer w data center, maszyna wirtualna u twojego cloud providera albo kontener. Instalujesz aplikację runnera GitHub Actions na tej maszynie. Runner łączy się na zewnątrz z GitHubem, pobiera oczekujące joby, uruchamia je lokalnie i odsyła logi. Ponieważ działa w twojej sieci, może bezpiecznie komunikować się z twoją wewnętrzną infrastrukturą bez robienia dziur w firewallu. Oto kluczowa sprawa. Jesteś właścicielem sprzętu, co oznacza, że odpowiadasz za jego utrzymanie. Odpowiadasz za aktualizacje systemu operacyjnego, bezpieczeństwo sieci i instalowanie niezbędnych zależności, takich jak runtime'y języków czy narzędzia do buildowania. Powszechnym błędem jest myślenie, że self-hosted runnery zachowują się dokładnie tak samo jak te hostowane. Otóż nie. Runnery hostowane przez GitHuba są z założenia efemeryczne. Standardowe self-hosted runnery są stateful. Kiedy job kończy się na domyślnym self-hosted runnerze, maszyna nadal działa. Jeśli twój job zapisze plik tymczasowy, uruchomi proces w tle albo pobierze duży obraz kontenera, to wszystko zostaje na dysku, gdy startuje kolejny job. Stwarza to poważne ryzyko zanieczyszczenia środowiska między jobami. Wadliwy skrypt budujący w jednym pull requeście może zostawić po sobie uszkodzone pliki, sprawiając, że job deployujący, który uruchomi się zaraz po nim, po prostu zfailuje. Musisz aktywnie skonfigurować swoją infrastrukturę self-hosted tak, aby była efemeryczna, jeśli tego właśnie chcesz, często używając webhooków do stawiania świeżych kontenerów per job. Jeśli po prostu potrzebujesz większej mocy obliczeniowej albo statycznego adresu IP, ale nadal chcesz, żeby GitHub zajmował się utrzymaniem maszyny, istnieje złoty środek o nazwie larger runners. Są to maszyny hostowane przez GitHuba, gdzie definiujesz specyfikację sprzętową i funkcje sieciowe, ale pozostają one efemeryczne i zarządzane przez GitHuba. Ostatecznie, decyzja między hosted a self-hosted rzadko sprowadza się tylko do kosztów mocy obliczeniowej. To fundamentalny trade-off między wygodą bezobsługowego, jednorazowego środowiska, a koniecznością kontrolowania własnych granic sieciowych. Dzięki za spędzenie ze mną tych kilku minut. Do usłyszenia następnym razem, trzymaj się.
13

Skalowanie w Kubernetes: Actions Runner Controller

3m 48s

Odkryj, jak Actions Runner Controller (ARC) orkiestruje efemeryczne, automatycznie skalujące się floty runners natywnie w Twoich klastrach Kubernetes.

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. GitHub Actions, odcinek 13 z 14. Masz ogromny zespół, a o dziewiątej rano stu programistów jednocześnie pushuje kod. Twoje statyczne serwery buildów albo dławią się kolejką, albo zrobiłeś over-provisioning i przez całą noc marnują drogie zasoby obliczeniowe. Kubernetes Scale: Actions Runner Controller rozwiązuje ten problem, zamieniając twój build pipeline w dynamiczny, container-native system. Standardowe self-hosted runnery to zazwyczaj statyczne maszyny wirtualne albo long-lived kontenery. Konfigurujesz je, rejestrujesz w repozytorium, a one po prostu siedzą i robią polling w poszukiwaniu zadań. Taka konfiguracja gwarantuje, że płacisz za idle time, a gdy uderzy nagły skok liczby buildów, twoja kolejka po prostu zapycha się, dopóki istniejący runner nie skończy swojego obecnego zadania. Actions Runner Controller, czyli ARC, fundamentalnie zmienia ten model. ARC to operator Kubernetesa, który orkiestruje auto-skalujące się runner scale sety. Zamiast utrzymywać długo żyjące worker node'y, provisionuje efemeryczne runnery Just-in-Time, dokładnie na podstawie rozmiaru twojej kolejki. Aby to osiągnąć bez przekraczania API rate limitów, ARC opiera się na dwóch głównych komponentach architektonicznych w twoim klastrze Kubernetesa. Pierwszym z nich jest pod Listenera. Listener używa HTTPS long poll, żeby połączyć się z GitHubem. Zamiast wymagać od ciebie otwierania inboundowych portów na firewallu do odbierania webhooków, Listener sam uderza do GitHuba i utrzymuje otwarte połączenie. Siedzi cicho i czeka, aż GitHub przekaże mu wiadomość Job Available. Kiedy Listener odbierze tę wiadomość, przekazuje informację do poda Controllera. Controller działa jako silnik provisioningu. Natychmiast gada z API Kubernetesa, żeby podnieść zupełnie nowy pod runnera specjalnie dla tego jednego pending joba. Ten pod to efemeryczny runner Just-in-Time. Bootuje się, otrzymuje short-lived registration token, wykonuje workflow, a następnie natychmiast sam się terminuje. Wróćmy do tego porannego code rusha o dziewiątej. Setka programistów pushuje commity dokładnie w tym samym czasie. Pod Listenera wykrywa nagły wysyp wiadomości Job Available z GitHuba. Alarmuje Controllera, który natychmiast requestuje sto efemerycznych podów Kubernetesa. Twój klaster robi scale out, alokując node'y jeśli to konieczne, a joby wykonują się równolegle. Kiedy każdy workflow się kończy, jego pod jest całkowicie niszczony. O dziewiątej piętnaście kolejka jest pusta, a liczba twoich runnerów skaluje się z powrotem do zera. Używałeś potężnego parallel compute przez dokładnie piętnaście minut, a potem przestałeś za niego płacić. I tu jest sedno sprawy. Ponieważ każdy pojedynczy job odpala się w świeżo sprovisionowanym, odizolowanym podzie, który jest niszczony zaraz po wykonaniu, całkowicie eliminujesz state contamination między buildami. Brudny cache, pozostały background process czy zmieniona environment variable z poprzedniego runa po prostu nie mogą zepsuć kolejnego. Zyskujesz bezpieczeństwo nieskazitelnego build environment za każdym razem, w połączeniu z dokładną wydajnością obliczeniową auto-scalingu Kubernetesa. Prawdziwą wartością Actions Runner Controllera jest to, że przestajesz traktować runnery continuous integration jako ciężką infrastrukturę, którą musisz utrzymywać, zamieniając je w czysto efemeryczny compute, który istnieje tylko wtedy, gdy job jest aktywnie wykonywany. Dzięki za spędzenie ze mną tych kilku minut. Do usłyszenia następnym razem, trzymaj się.
14

Integralność łańcucha dostaw dzięki Attestations

3m 58s

Zabezpiecz swój łańcuch dostaw oprogramowania. Dowiedz się, jak generować niemożliwe do sfałszowania artifact attestations i provenance bezpośrednio ze swoich workflows.

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. GitHub Actions, odcinek 14 z 14. Użytkownik pobiera twoje skompilowane narzędzie command line ze strony release'u. Jeśli skompromitowana zależność lub złośliwy aktor podmienił tę binarkę po jej zbudowaniu, standardowe sprawdzenie checksum w niczym nie pomoże. Standardowe hashe udowadniają tylko, że pobrany plik jest zgodny z tym hostowanym, a nie skąd tak naprawdę pochodzi. Aby zagwarantować, że plik został wygenerowany dokładnie przez twój kod, potrzebujesz Supply Chain Integrity z wykorzystaniem Attestations. Attestation to nie tylko build log czy plik tekstowy zawierający hash, leżący obok twojego release'u. To kryptograficznie podpisane, niemożliwe do sfałszowania oświadczenie o pochodzeniu artefaktu. Wiąże ono twoją końcową binarkę bezpośrednio z konkretnym commit SHA, konkretnym workflow run i tożsamością OpenID Connect środowiska builda. Ten proces odbywa się w całości wewnątrz twojego workflow w GitHub Actions. Po skompilowaniu kodu, używasz oficjalnej akcji build provenance. Ta akcja oblicza checksum twojego gotowego artefaktu i kontaktuje się ze scentralizowanym signing authority, a konkretnie z Sigstore. Workflow wymienia swój tymczasowy, przypisany do konkretnego joba token OpenID Connect na krótkotrwały signing certificate. Ponieważ ten token jest generowany przez GitHub Actions i mapowany bezpośrednio do twojego repozytorium, działa jak niepodrabialny dowód tożsamości dla workflow runnera. Ta interakcja generuje trwały rekord kryptograficzny. Ten rekord jednoznacznie stwierdza, że ten konkretny hash pliku został wygenerowany przez twoje repozytorium, wyzwolony przez konkretny commit, podczas określonego workflow run. Podpis jest dołączany do artefaktu, tworząc pakiet dowodowy, który podróżuje razem z plikiem, niezależnie od tego, gdzie jest hostowany. Oto kluczowa kwestia. Prawdziwa wartość dla bezpieczeństwa pojawia się po stronie konsumenta. Kiedy użytkownik pobiera twoje narzędzie command line, nie musi ślepo ufać dostawcy hostingu ani mirrorom. Przed uruchomieniem binarki, używa GitHub CLI do lokalnej weryfikacji attestation. Uruchamia komendę attestation verify na pobranym pliku wykonywalnym, jawnie określając właściciela twojego repozytorium jako oczekiwane źródło. CLI sprawdza podpis kryptograficzny i weryfikuje go z publicznym transparency log. Jeśli podpis jest prawidłowy, matematycznie dowodzi to, że plik został skompilowany przez twój oficjalny workflow. Jeśli złośliwy aktor przechwycił pobieranie, zmanipulował kompilację lub podmienił binarkę na stronie release'u, weryfikacja natychmiast kończy się błędem. Podpisu nie można sfałszować, ponieważ atakujący nigdy nie wejdzie w posiadanie tymczasowego tokena tożsamości OpenID Connect, wygenerowanego wewnątrz twojego bezpiecznego workflow run. Ta tożsamość jest nierozerwalnie powiązana z infrastrukturą GitHub Actions dokładnie w momencie builda. Ten mechanizm zamyka krytyczną lukę w bezpieczeństwie software supply chain. Nie prosisz już użytkowników o zaufanie do miejsca przechowywania. Zamiast tego, artefakt staje się samouwierzytelniający. Attestations zmieniają twój model bezpieczeństwa z ufania w to, gdzie plik żyje, na matematyczne udowodnienie tego, gdzie się narodził. Ponieważ to ostatni odcinek naszej serii o GitHub Actions, gorąco zachęcam cię do praktyki i samodzielnego budowania tych workflow. Odwiedź DEV STORIES DOT EU, aby zasugerować tematy, które chcesz zobaczyć w naszych przyszłych seriach. To wszystko w tym odcinku. Dzięki za słuchanie i keep building!