Wróć do katalogu
Season 26 10 Odcinki 40 min 2026

Azure Pipelines

Edycja 2026. Zapoznaj się z Azure DevOps (ADO) i dowiedz się, jak budować dobrze ustrukturyzowane pipelines. Poznaj najlepsze praktyki, zarządzaj zmiennymi i sekretami oraz zdobądź praktyczne porady dotyczące wykorzystania go w procesie tworzenia oprogramowania klasy enterprise.

CI/CD DevOps
Azure Pipelines
Teraz odtwarzane
Click play to start
0:00
0:00
1
YAML vs Classic Pipelines
Wprowadzamy do Azure DevOps Pipelines i analizujemy kluczowe przejście z klasycznych pipelines opartych na UI na Pipeline-as-Code z użyciem YAML. Dowiesz się, dlaczego przechowywanie konfiguracji pipeline razem z kodem aplikacji jest standardem branżowym dla oprogramowania klasy enterprise.
3m 52s
2
Anatomia Pipeline: Stages, Jobs i Steps
Zanurz się w hierarchię strukturalną Azure Pipelines. Dowiesz się, jak logicznie organizować proces CI/CD za pomocą Stages, rozdzielać obciążenia dzięki Jobs i wykonywać konkretne polecenia przy użyciu Steps.
4m 08s
3
Kontekst wykonania: Agents i Demands
Odkryj, jak Azure Pipelines wykonują Twój kod przy użyciu Agents. Omawiamy różnice między agentami Microsoft-hosted i Self-hosted oraz pokazujemy, jak używać Demands do kierowania zadań (jobs) do odpowiedniej infrastruktury.
4m 22s
4
Automatyzacja przepływu pracy za pomocą Triggers
Dowiedz się, jak sprawić, by Twoje pipelines automatycznie reagowały na zdarzenia. Omawiamy wyzwalacze Continuous Integration (CI), Pull Request (PR) oraz Scheduled, aby orkiestrować złożone harmonogramy wdrożeń.
3m 34s
5
Zarządzanie stanem: Variables i Variable Groups
Opanuj sztukę przekazywania stanu i konfiguracji przez Twoje pipelines. W tym odcinku szczegółowo omawiamy predefiniowane zmienne systemowe, niestandardowe zmienne pipeline oraz sposoby współdzielenia konfiguracji między projektami za pomocą Variable Groups.
4m 03s
6
Zabezpieczanie sekretów z Azure Key Vault
Przestań przechowywać wrażliwe dane uwierzytelniające w swoim narzędziu CI/CD. Wyjaśniamy, jak zintegrować Azure Key Vault z Azure Pipelines, aby dynamicznie pobierać hasła, klucze API i connection strings w trakcie działania (runtime).
4m 07s
7
Dynamiczna kontrola: Conditions i Expressions
Dowiedz się, jak sprawić, by Twoje pipelines były inteligentne i reaktywne. Zagłębiamy się w niestandardowe Conditions i Expressions, aby dynamicznie kontrolować, które jobs i steps są wykonywane na podstawie wartości zmiennych i wyników poprzednich zadań.
3m 36s
8
Reużywalność w skali enterprise: YAML Templates
Skaluj architekturę swoich pipelines na dziesiątki repozytoriów za pomocą YAML Templates. Poznaj różnicę między 'Includes' a 'Extends' i dowiedz się, jak egzekwować wymogi bezpieczeństwa w całej organizacji.
4m 12s
9
Kierowanie wdrożeniami za pomocą Environments
Przenieś swój pipeline z poziomu zwykłego 'uruchamiania kodu' do zarządzania rzeczywistymi wdrożeniami. Omawiamy typ Deployment Job, Environments oraz strategie wdrażania, takie jak runOnce i Canary.
4m 10s
10
Bramki enterprise: Approvals i Checks
Załóż bariery ochronne na swoje zautomatyzowane wdrożenia. W tym ostatnim odcinku sprawdzamy, jak skonfigurować Approvals, Branch Control i Exclusive Locks na Twoich Environments, aby chronić produkcję.
3m 56s

Odcinki

1

YAML vs Classic Pipelines

3m 52s

Wprowadzamy do Azure DevOps Pipelines i analizujemy kluczowe przejście z klasycznych pipelines opartych na UI na Pipeline-as-Code z użyciem YAML. Dowiesz się, dlaczego przechowywanie konfiguracji pipeline razem z kodem aplikacji jest standardem branżowym dla oprogramowania klasy enterprise.

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. Azure Pipelines, odcinek 1 z 10. Klikasz po interfejsie webowym, przeciągasz kilka elementów i twój build działa idealnie. Potem ktoś zmienia jedno ustawienie, build się psuje, a ty nie masz absolutnie żadnej historii, kto co zrobił i dlaczego. To pułapka edytorów wizualnych i właśnie dlatego przejście z Classic UI na pipeline'y w YAML-u to fundament nowoczesnego CI/CD. Azure Pipelines daje ci dwa różne sposoby na automatyzację dostarczania oprogramowania. Starsza metoda to interfejs Classic. Opiera się na graficznym portalu webowym, gdzie konfigurujesz taski za pomocą formularzy i rozwijanych menu. Wydaje się to przystępne, kiedy dopiero zaczynasz. Ale w miarę jak twój system rośnie, podejście Classic staje się sporym obciążeniem. Konfiguracja żyje w bazie danych Azure DevOps, całkowicie oderwana od twojego faktycznego kodu źródłowego. Pipeline'y w YAML-u zastępują to koncepcją Pipeline-as-Code. Zamiast konfigurować ustawienia w portalu webowym, definiujesz cały proces buildu i release'u w zwykłym pliku tekstowym. Robisz commit tego pliku YAML bezpośrednio do repozytorium, trzymając go tuż obok kodu aplikacji, który ma zbuildować. Niektórzy developerzy wahają się przed zmianą, obawiając się, że konfiguracja tekstowa może ograniczać funkcje w porównaniu do edytora wizualnego. Wcale tak nie jest. Pipeline'y w YAML-u oferują pełną zgodność funkcji dla Continuous Integration i Continuous Delivery. Microsoft traktuje Classic UI jako legacy i skupia nowy rozwój na YAML-u. To korporacyjny standard, jeśli chodzi o powtarzalność i audyt. Pomyśl o zespole, który migruje złożoną definicję buildu typu drag-and-drop do pliku w repozytorium. W starym systemie testowanie nowego kroku w buildzie oznaczało edycję współdzielonej konfiguracji pipeline'u, co potencjalnie mogło zepsuć build reszcie zespołu. Dzięki YAML-owi, pipeline podlega kontroli wersji, dokładnie tak jak twoja aplikacja. Jeśli tworzysz feature branch, żeby zaktualizować główną zależność, możesz zmodyfikować plik YAML dokładnie w tym samym branchu. Zaktualizowana logika buildu dotyczy tylko twojego odizolowanego brancha. Reszta zespołu dalej korzysta z pipeline'u na main branchu bez żadnych przerw. I tu jest kluczowa sprawa. Ponieważ twój pipeline to teraz po prostu plik tekstowy w Gicie, podlega on standardowemu procesowi code review. Kiedy odchodzisz od UI, nikt nie może po cichu zmienić celu deploymentu ani pominąć kroku testowania. Każda zmiana pipeline'u wymaga commita. Wymaga pull requesta. Wymaga akceptacji od współpracownika. Zyskujesz stały, niezaprzeczalny ślad audytowy każdej modyfikacji. Co więcej, stan twojego pipeline'u jest na zawsze powiązany ze stanem twojej aplikacji. Jeśli musisz zrobić rollback do release'u sprzed sześciu miesięcy, plik YAML z tamtego konkretnego momentu jest zachowany w twojej historii w Gicie. Masz gwarancję, że posiadasz poprawne instrukcje buildu dla tej konkretnej, starszej wersji kodu. Przejście na YAML polega na traktowaniu twojego mechanizmu dostarczania z dokładnie takim samym inżynieryjnym rygorem, jak oprogramowanie, które on dostarcza. Jeśli uważasz te odcinki za pomocne i chcesz wesprzeć podcast, możesz wyszukać DevStoriesEU na Patreonie. To wszystko w tym odcinku. Dzięki za wysłuchanie i buduj dalej!
2

Anatomia Pipeline: Stages, Jobs i Steps

4m 08s

Zanurz się w hierarchię strukturalną Azure Pipelines. Dowiesz się, jak logicznie organizować proces CI/CD za pomocą Stages, rozdzielać obciążenia dzięki Jobs i wykonywać konkretne polecenia przy użyciu Steps.

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. Azure Pipelines, odcinek 2 z 10. Różnica między stage'em a jobem określa dokładnie, gdzie twój pipeline się wysypie, jeśli źle zrozumiesz alokację agentów. Jeśli zrobisz to źle, możesz nagle odkryć, że twoje artefakty builda zniknęły akurat wtedy, gdy przychodzi czas na odpalenie testów. Anatomia pipeline'u — a konkretnie stage'e, joby i stepy — to struktura, która rozwiązuje ten problem. Pipeline to system hierarchiczny. Ta struktura ściśle narzuca to, jak praca jest dzielona, gdzie się uruchamia i w jakiej kolejności. Hierarchia ma trzy poziomy. Stage'e zawierają joby, a joby zawierają stepy. Stage pełni funkcję logicznej granicy. Grupuje powiązaną ze sobą pracę. W aplikacji enterprise używasz stage'y do oddzielania głównych faz cyklu dostarczania oprogramowania. Możesz zdefiniować build stage, a po nim oddzielny testing stage. Domyślnie stage'e uruchamiają się sekwencyjnie. Jeden stage musi się całkowicie zakończyć, zanim rozpocznie się kolejny. Pełnią one funkcję organizacyjnych barier dla całego twojego procesu. Oto kluczowa sprawa. Inżynierowie często mylą stage'e i joby, traktując je zamiennie. Nie służą one temu samemu celowi. Stage to czysto logiczny kontener. Job to fizyczna granica wykonania. Job definiuje rzeczywiste środowisko, w którym działa twój kod. Każdy job jest przypisany do agenta, czyli maszyny lub kontenera wykonującego twoje taski. Wszystkie operacje w ramach jednego joba wykonują się na tym jednym, konkretnym agencie. Ponieważ joby są jednostką wykonawczą, zachowują się inaczej niż stage'e. Jeśli umieścisz trzy joby w jednym stage'u, Azure Pipelines spróbuje uruchomić te trzy joby równolegle na trzech różnych agentach, zakładając, że masz dostępną pojemność. Oznacza to, że joby nie współdzielą lokalnego systemu plików ani pamięci. Jeśli job A kompiluje kod twojej aplikacji, job B nie może po prostu uzyskać dostępu do skompilowanych binarek z lokalnego dysku. Job B działa na zupełnie innej maszynie. Jeśli potrzebujesz, aby dwa procesy sekwencyjnie współdzieliły tę samą przestrzeń na lokalnym dysku, muszą zostać umieszczone w tym samym jobie. Wewnątrz joba definiujesz stepy. Step to najmniejszy element składowy pipeline'u. To konkretna instrukcja, zazwyczaj task albo skrypt. Ponieważ stepy żyją wewnątrz konkretnego joba, wszystkie uruchamiają się sekwencyjnie na dokładnie tym samym agencie. Step pierwszy może być taskiem do pobrania twojego kodu źródłowego. Step drugi może być skryptem bash, który uruchamia twój kompilator. Ponieważ współdzielą to samo środowisko wykonawcze, step drugi ma natychmiastowy, bezpośredni dostęp do plików, które step pierwszy właśnie pobrał. Zastosuj to do strukturyzowania pipeline'u typu enterprise, który buduje aplikację, odpala unit testy i pakuje wynik. Tworzysz pojedynczy stage o nazwie Continuous Integration. Wewnątrz tego stage'a definiujesz dwa oddzielne joby, aby przyspieszyć wykonywanie. Job pierwszy obsługuje główny build. Jego stepy robią checkout kodu, uruchamiają kompilator i pakują binarkę. Job drugi obsługuje statyczną analizę kodu i niezależne unit testy. Ponieważ są to oddzielne joby w ramach tego samego stage'a, uruchamiają się współbieżnie na oddzielnych agentach. Nie blokują się nawzajem, ale też nie współdzielą systemu plików. Jeśli job drugi potrzebuje binarki utworzonej przez job pierwszy, musisz jawnie poinstruować job pierwszy, aby opublikował artefakt do pipeline storage, i poinstruować job drugi, aby go pobrał. Struktura dyktuje możliwości w twojej architekturze Continuous Integration. Używaj stage'y, aby logicznie organizować swój workflow, ale polegaj na jobach, aby kontrolować dokładnie gdzie i jak twoje wykonanie skaluje się na różne maszyny. Dzięki za wspólnie spędzony czas. Mam nadzieję, że dowiedziałeś się czegoś nowego.
3

Kontekst wykonania: Agents i Demands

4m 22s

Odkryj, jak Azure Pipelines wykonują Twój kod przy użyciu Agents. Omawiamy różnice między agentami Microsoft-hosted i Self-hosted oraz pokazujemy, jak używać Demands do kierowania zadań (jobs) do odpowiedniej infrastruktury.

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. Azure Pipelines, odcinek 3 z 10. Każdy pipeline potrzebuje mocy obliczeniowej, ale wybór niewłaściwego execution context może niepostrzeżenie podwoić czas twoich buildów. Możesz napisać idealny kod pipeline'u, ale jeśli twój build musi pobierać gigabajty zależności od zera przy każdym runie, twój zespół straci godziny na czekanie. To wąskie gardło jest właśnie powodem, dla którego musisz zrozumieć Execution Context, a konkretnie Agents i Demands. Żeby zbudować kod albo zdeployować soft w Azure DevOps, potrzebujesz agenta. Agent to po prostu instalowalne oprogramowanie, które łączy się z twoją organizacją Azure DevOps, nasłuchuje czy jest coś do zrobienia i wykonuje joby jeden po drugim. Każdy agent działa na maszynie hosta, a ty zazwyczaj wybierasz między dwoma typami hostów. Możesz używać Microsoft-hosted agents albo self-hosted agents. Microsoft-hosted agents to domyślny wybór ze względu na wygodę. Prosisz o maszynę, a Microsoft dostarcza ci ją ze swojego cloud poola. Nigdy nie musisz patchować systemu operacyjnego ani upgradować oprogramowania agenta. Ale ta wygoda ma pewien haczyk, na którym łapie się wiele zespołów. Oto kluczowa sprawa. Microsoft-hosted agent daje ci zupełnie nową, całkowicie świeżą maszynę wirtualną dla każdego pojedynczego runu pipeline'u. Nie pamięta twojego ostatniego buildu. Kiedy twój job się kończy, ta maszyna jest bezpowrotnie niszczona. Jeśli twój build wymaga konkretnego, gigabajtowego cache'u pakietów, będzie go pobierał przez sieć od zera przy każdym runie, chyba że dodasz jawne kroki pipeline caching, żeby zapisać i przywrócić te dane. Jeśli chcesz uniknąć pobierania całego internetu za każdym razem, albo jeśli twój build musi sięgnąć za restrykcyjny firmowy firewall, używasz self-hosted agents. Instalujesz oprogramowanie agenta na własnej infrastrukturze. Może to być serwer w twoim lokalnym data center albo persistent virtual machine w twoim własnym cloud tenancie. Ponieważ maszyna przetrwa między runami, twoje package caches, pobrane Software Development Kits i pliki incremental build zostają dokładnie tam, gdzie je zostawiłeś. To drastycznie przyspiesza execution times. Jeśli szukasz nowoczesnego kompromisu, możesz zainteresować się Managed DevOps Pools. Działają one jako alternatywa typu scale-set, gdzie definiujesz własne base images i rozmiary, a Azure zajmuje się automatycznym provisioningiem i skalowaniem. To tyle, jeśli chodzi o to, czym są agenci. A teraz, skąd Azure DevOps wie, którego agenta użyć do konkretnego joba? Opiera się to na systemie capabilities i demands. Każdy self-hosted agent raportuje listę capabilities z powrotem do serwera. Wiele z nich jest wykrywanych automatycznie przez oprogramowanie agenta, jak na przykład typ systemu operacyjnego albo ścieżka do zainstalowanych narzędzi, takich jak Node czy Python. Możesz też zdefiniować custom user capabilities, na przykład oznaczając konkretną maszynę jako posiadającą określoną kartę graficzną. W definicji pipeline'u piszesz demands, żeby dopasować je do tych capabilities. Demand gwarantuje, że twój job zostanie zroutowany tylko do agenta, który posiada dokładnie to capability, o które prosisz. Rozważmy scenariusz, w którym budujesz aplikację na iOS. Budowanie na iOS wymaga Xcode, a to z kolei bezwzględnie wymaga sprzętu Apple. Załóżmy, że masz jeden pool dwudziestu self-hosted agents, ale tylko dwa z nich to Mac Mini. Po prostu dodajesz demand na capability macOS do swojego joba w pipeline'ie. Kiedy Azure DevOps ewaluuje run, odfiltrowuje wszystkie maszyny z Windowsem i Linuxem w poolu i routuje twój build iOS bezpośrednio do jednego z dostępnych Maców Mini. Twój wybór agenta determinuje całą architekturę pipeline'u. Microsoft-hosted zdejmuje z ciebie obowiązek utrzymania serwerów kosztem samodzielnego zarządzania stanem, podczas gdy self-hosted wymienia utrzymanie infrastruktury na czystą prędkość i persistent caches. To wszystko w tym odcinku. Dzięki za wysłuchanie i keep building!
4

Automatyzacja przepływu pracy za pomocą Triggers

3m 34s

Dowiedz się, jak sprawić, by Twoje pipelines automatycznie reagowały na zdarzenia. Omawiamy wyzwalacze Continuous Integration (CI), Pull Request (PR) oraz Scheduled, aby orkiestrować złożone harmonogramy wdrożeń.

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. Azure Pipelines, odcinek 4 z 10. Możesz myśleć, że twój pipeline wykonuje się tylko wtedy, gdy ktoś zrobi push commita. Ale w dojrzałym systemie pipeline'y są o wiele bardziej proaktywne, uruchamiając różne typy walidacji w zupełnie różnych momentach. Mówimy o automatyzacji workflow za pomocą triggerów. Triggery dokładnie definiują, jakie eventy powodują uruchomienie twojego pipeline'u. Najpopularniejszym typem jest trigger Continuous Integration, czyli CI. Trigger CI odpala się automatycznie za każdym razem, gdy kod jest wypushowany do określonego brancha. W pliku pipeline'u definiujesz to za pomocą prostego bloku trigger. Możesz mu kazać nasłuchiwać main brancha, ale ignorować określone ścieżki plików, takie jak foldery z dokumentacją. Dzięki temu twój pipeline nie marnuje czasu na budowanie aplikacji, gdy ktoś tylko poprawi literówkę w pliku tekstowym. To załatwia sprawę kodu, który już trafia do brancha. Zazwyczaj jednak chcesz wyłapać błędy, zanim nastąpi merge. I tu do akcji wkraczają triggery Pull Request. Trigger PR odpala się po otwarciu pull requestu lub gdy nowe commity zostaną wypushowane do tego istniejącego pull requestu. Jego głównym celem jest ochrona target brancha poprzez walidację przychodzącego kodu. Oto kluczowa kwestia. Istnieje typowa pułapka, w którą wpadają deweloperzy przy triggerach PR. Kiedy pull request odpala pipeline, Azure Pipelines sprawdza konfigurację na podstawie pliku YAML znajdującego się w source branchu, a nie w target branchu. Logika sterująca walidacją pochodzi z samego feature brancha. Jeśli wprowadzisz zmiany w konfiguracji pipeline'u w swoim feature branchu, te zmiany zostaną zastosowane do uruchomienia PR. Triggery PR muszą być szybkie. Jeśli konfigurujesz trigger PR, powinieneś używać go do uruchamiania szybkich operacji, takich jak testy jednostkowe i linting kodu. Chcesz, żeby deweloperzy dostawali feedback w ciągu kilku minut. Ale niektóre operacje, takie jak głęboka analiza statyczna czy ciężkie skany bezpieczeństwa, trwają znacznie dłużej. Dwugodzinny skan bezpieczeństwa sparaliżuje twój zespół, jeśli podepniesz go pod trigger PR. To prowadzi nas do trzeciego typu: triggerów Scheduled. Zamiast reagować na ruch w kodzie, triggery Scheduled uruchamiają pipeline'y w oparciu o zegar. Używają standardowej składni cron do definiowania konkretnych dni i godzin uruchomienia pipeline'u. Definiujesz blok schedules w swoim pliku YAML, określasz wyrażenie cron i wymieniasz branche, które chcesz zbudować. Możesz łączyć te triggery, żeby zbudować wydajny workflow. W ciągu dnia twoje triggery PR uruchamiają szybkie testy jednostkowe na feature branchach, żeby utrzymać płynność developmentu. W międzyczasie konfigurujesz trigger Scheduled, żeby odpalał ten dwugodzinny skan bezpieczeństwa na main branchu o każdej północy. Możesz nawet ustawić trigger Scheduled tak, żeby uruchamiał się tylko wtedy, gdy nowe commity zostały zmergowane od poprzedniej nocy. Dzięki temu całkowicie pomijasz uruchamianie w spokojny weekend, oszczędzając na kosztach obliczeniowych. Używanie tych triggerów razem pozwala ci oddzielić szybki feedback dla deweloperów od dogłębnej walidacji systemu. Triggery to nie tylko przyciski startowe; to architektoniczne mechanizmy kontrolne, które decydują o tym, jak i kiedy wykorzystywane są twoje zasoby obliczeniowe. Dzięki za wysłuchanie — do usłyszenia następnym razem.
5

Zarządzanie stanem: Variables i Variable Groups

4m 03s

Opanuj sztukę przekazywania stanu i konfiguracji przez Twoje pipelines. W tym odcinku szczegółowo omawiamy predefiniowane zmienne systemowe, niestandardowe zmienne pipeline oraz sposoby współdzielenia konfiguracji między projektami za pomocą Variable Groups.

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. Azure Pipelines, odcinek 5 z 10. Hardcodowanie nazw środowisk bezpośrednio w plikach YAML to dług techniczny, który tylko czeka, żeby eksplodować podczas twojej kolejnej migracji infrastruktury. Kiedy te nazwy się zmienią, na pewno nie chcesz przeszukiwać dziesiątek repozytoriów, żeby je zaktualizować. State Management za pomocą Variables i Variable Groups rozwiązuje ten problem, centralizując twoją konfigurację. Twój pipeline już out of the box wie bardzo dużo o swoim kontekście wykonania. Azure dostarcza predefiniowane zmienne systemowe, żeby dać twojemu pipeline'owi świadomość środowiska bez żadnego ręcznego setupu. Na przykład, jeśli musisz wiedzieć, który branch ztriggerował run, używasz Build dot SourceBranch. Jeśli potrzebujesz unikalnego ID obecnego runu, używasz Build dot BuildId. Są one automatycznie uzupełniane i gotowe do odczytu. Kiedy potrzebujesz customowej konfiguracji, definiujesz zmienne inline. Umieszczasz je bezpośrednio w swoim pliku YAML w bloku variables. To idealne rozwiązanie dla wartości specyficznych dla pojedynczego pipeline'u, takich jak flaga konfiguracji buildu czy lokalna ścieżka do pliku. Dzięki temu logika jest self-contained. Jednak zmienne inline zawodzą, kiedy zaczynasz się skalować. Weźmy scenariusz, w którym masz trzy oddzielne pipeline'y dla mikrousług. Wszystkie muszą znać nazwę docelowego środowiska deploymentu i zestaw współdzielonych adresów URL dla endpointów API. Jeśli zdefiniujesz je inline, powtarzasz się w trzech repozytoriach. Jeśli endpoint się zmieni, masz do zrobienia trzy pull requesty. Rozwiązaniem jest Library Variable Group. To scentralizowany magazyn key-value trzymany wewnątrz Azure DevOps Library. Tworzysz grupę raz w interfejsie użytkownika, uzupełniasz ją nazwami swoich środowisk i endpointami API, a następnie referujesz do tej grupy po nazwie w bloku variables wszystkich trzech pipeline'ów mikrousług. Kiedy nadchodzi dzień migracji, aktualizujesz Variable Group w portalu DevOps, a każdy pipeline natychmiast używa nowych wartości przy swoim kolejnym runie. Wymuszasz w ten sposób zasadę Don't Repeat Yourself, trzymając swoją współdzieloną konfigurację w dokładnie jednym miejscu. Oto kluczowa sprawa. To, jak wywołujesz zmienną, zmienia moment, w którym Azure ją ewaluuje. Istnieją dwie podstawowe składnie, a ich pomylenie wywali twój pipeline. Pierwsza to macro syntax, zapisywana jako znak dolara, po którym następują nawiasy okrągłe otaczające nazwę zmiennej. Macro syntax jest ewaluowana w runtime'ie. Azure podmienia zmienną tuż przed wykonaniem konkretnego taska, który jej używa. Druga to template expression syntax, zapisywana jako znak dolara, po którym następują podwójne nawiasy klamrowe zawierające słowo variables dot i nazwę twojej zmiennej. Template expressions są ewaluowane w compile time, jeszcze zanim pipeline w ogóle zacznie swój run. Jeśli próbujesz użyć zmiennej, żeby zdecydować, czy dany stage powinien w ogóle się uruchomić, albo żeby zdefiniować pętlę po liście jobów, musisz użyć template expression syntax. Pipeline potrzebuje tej wartości z góry, żeby zbudować graf wykonania. Jeśli wartość jest generowana dynamicznie podczas runu pipeline'u przez skrypt, musisz użyć macro syntax, ponieważ ta wartość po prostu nie istnieje w compile time. Opanuj różnicę między template expressions w compile time a makrami w runtime'ie, a wyeliminujesz najbardziej frustrujące błędy parsowania zmiennych podczas developmentu twojego pipeline'u. To wszystko w tym odcinku. Do usłyszenia następnym razem!
6

Zabezpieczanie sekretów z Azure Key Vault

4m 07s

Przestań przechowywać wrażliwe dane uwierzytelniające w swoim narzędziu CI/CD. Wyjaśniamy, jak zintegrować Azure Key Vault z Azure Pipelines, aby dynamicznie pobierać hasła, klucze API i connection strings w trakcie działania (runtime).

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. Azure Pipelines, odcinek 6 z 10. Maskowanie secreta w logach twojego pipeline'u nie oznacza, że jest on bezpieczny, jeśli wpisałeś go bezpośrednio w konfiguracji CI/CD. Kiedy administrator bazy danych zrotuje to hasło, twoje deploye natychmiast przestają działać, dopóki ktoś ręcznie nie zaktualizuje pipeline'u. Żeby to naprawić, pobierasz credentials dynamicznie, używając Azure Key Vault. Ludzie często definiują secret variables bezpośrednio w UI Azure DevOps. Klikasz ikonę kłódki, tekst znika i zakładasz, że jesteś bezpieczny. Przechowywanie secretów w UI pipeline'u tworzy pofragmentowany stan bezpieczeństwa. Jeśli firmowa polityka wymaga rotacji credentials co trzydzieści dni, znalezienie i zaktualizowanie każdej zmiennej pipeline'u w dziesiątkach projektów to operacyjny koszmar. Co więcej, tracisz centralny audyt tego, kto lub co uzyskało dostęp do tych danych. Podejście secure-by-design polega na dynamicznym pobieraniu secretów w czasie runtime'u z firmowego Key Vault. Pipeline nigdy nie jest właścicielem secreta. Po prostu pożycza go dokładnie wtedy, kiedy jest potrzebny. Żeby to osiągnąć, używasz taska Azure Key Vault w swoim pipeline. Najpierw pipeline potrzebuje uprawnień, żeby zajrzeć do twojego vaulta. Konfigurujesz service connection Azure Resource Manager w swoim projekcie DevOps. To połączenie opiera się na Service Principal lub Managed Identity. Następnie przyznajesz tej tożsamości jawny dostęp do odczytu secretów w twoim Key Vault, używając Azure RBAC lub vault access policies. Oto kluczowa sprawa. Pipeline działa jako ta tożsamość, udowadniając Azure, kim jest, przed pobraniem jakichkolwiek wrażliwych danych. To idealnie pasuje do modelu zero-trust. W twoim repozytorium kodu ani w definicjach pipeline'u nie ma żadnych stałych credentials. Wyobraź sobie pipeline pobierający bardzo wrażliwy connection string do bazy danych tuż przed deployem backendu. W definicji twojego pipeline'u, tuż przed stepem deploymentu, dodajesz task Azure Key Vault w wersji drugiej. Przekazujesz trzy główne inputy do tego taska. Po pierwsze, określasz nazwę service connection twojej subskrypcji Azure. Po drugie, podajesz nazwę swojego właściwego Key Vault. Po trzecie, definiujesz listę konkretnych nazw secretów, które chcesz pobrać. Możesz przekazać wildcard w postaci gwiazdki, żeby pobrać wszystko, ale zasady least-privilege nakazują, żebyś prosił tylko o to, czego dokładnie potrzebujesz. Prosisz konkretnie o secret o nazwie production-database-connection. Kiedy pipeline dotrze do tego stepu, odpytuje vaulta. Jeśli tożsamość ma uprawnienia, vault zwraca secret. Task bierze tę bezpieczną wartość i automatycznie przekształca ją w standardową zmienną pipeline'u. Nazwa nowej zmiennej pipeline'u dokładnie odpowiada nazwie secreta w vaulcie. Twój kolejny step deploymentu może teraz odwołać się do tej zmiennej, żeby skonfigurować bazę danych, zupełnie jak do każdego standardowego text inputu. Azure Pipelines rejestruje również tę pobraną wartość jako secret variable w tle. Jeśli skrypt przypadkowo wypisze connection string do konsoli, system przechwyci go i zastąpi właściwy tekst gwiazdkami w logach. Dynamiczne pobieranie gwarantuje, że kiedy zespół bazodanowy zaktualizuje główne hasło w vaulcie, twój pipeline automatycznie użyje nowego stringa przy swoim kolejnym uruchomieniu, bez żadnej ręcznej interwencji. Twój system continuous delivery powinien działać jak bezpieczny kurier, odbierając zamkniętą teczkę tuż przed dostawą, zamiast przechowywać jej stałą kopię w magazynie. To wszystko w tym odcinku. Dzięki za wysłuchanie i buduj dalej!
7

Dynamiczna kontrola: Conditions i Expressions

3m 36s

Dowiedz się, jak sprawić, by Twoje pipelines były inteligentne i reaktywne. Zagłębiamy się w niestandardowe Conditions i Expressions, aby dynamicznie kontrolować, które jobs i steps są wykonywane na podstawie wartości zmiennych i wyników poprzednich zadań.

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. Azure Pipelines, odcinek 7 z 10. Najbardziej niezawodne pipeline'y klasy enterprise nie lecą po prostu ślepo z góry na dół. Reagują dynamicznie, gdy coś idzie nie tak, usuwając infrastrukturę po crashu albo pomijając ciężkie test suite'y podczas drobnego hotfixa. Żeby zbudować taką odporność, potrzebujesz dynamicznej kontroli: Conditions i Expressions. Każdy job i step w Azure Pipelines ma przypisany condition, niezależnie od tego, czy napiszesz go jawnie, czy nie. Domyślnie system aplikuje wbudowany condition o nazwie succeeded. Oznacza to, że step wykonuje się tylko wtedy, gdy wszystkie jego poprzednie zależności zakończą się bez rzucenia błędu. Jeśli pierwszy step zaliczy faila, drugi step jest automatycznie pomijany. Ludzie często źle rozumieją, kiedy te sprawdzenia mają miejsce. Condition ewaluuje, czy step powinien się uruchomić, i robi to całkowicie przed rozpoczęciem tego stepu lub joba. Step nigdy nie może użyć condition do ewaluacji swojego własnego, wewnętrznego outputu. Condition to taki strażnik stojący przy wejściu. Sprawdza stan pipeline'u do tego konkretnego momentu i decyduje, czy step może wystartować. Czasami jawnie potrzebujesz, żeby job uruchomił się, gdy poprzedni step się wywali. Weźmy na przykład job typu deployment, który stawia tymczasową infrastrukturę testową. Jeśli deployment wywali się w połowie, domyślne zachowanie pominie resztę pipeline'u. Twoje tymczasowe serwery zostają online, po cichu przepalając twój budżet chmurowy. Naprawiasz to, dodając dedykowany job czyszczący na końcu pipeline'u, ale zmieniasz jego condition z succeeded na failed. Teraz ten job czyszczący całkowicie ignoruje udane runy. Budzi się, żeby zniszczyć tymczasową infrastrukturę tylko wtedy, gdy główne joby deploymentu zaliczą crash. Nie ograniczasz się tylko do podstawowych sprawdzeń statusu, takich jak succeeded, failed czy always. Możesz pisać własne expressions, żeby ewaluować stany zmiennych i podejmować szczegółowe decyzje o routingu. Azure Pipelines używa dla tych expressions składni funkcyjnej. Zamiast pisać symbole matematyczne, używasz nazwanych funkcji. Jeśli chcesz sprawdzić, czy zmienna równa się konkretnej wartości, używasz funkcji o nazwie eq. Otwierasz nawiasy, przekazujesz zmienną pipeline'u, którą sprawdzasz, dodajesz przecinek i podajesz oczekiwaną wartość. Możesz łączyć wiele sprawdzeń, zagnieżdżając te funkcje. Załóżmy, że masz job typu release, który powinien się uruchomić tylko wtedy, gdy pipeline ma status succeeded, a obecny branch to main. Zaczynasz od funkcji and. W jej nawiasach przekazujesz dwa argumenty. Pierwszym argumentem jest funkcja succeeded. Drugim argumentem jest twoja funkcja eq, która porównuje zmienną source branch ze stringiem tekstowym dla brancha main. Job typu release ztriggeruje się tylko wtedy, gdy oba wyrażenia zwrócą true. Używanie expressions pozwala budować pipeline'y, które adaptują się do kontekstu danego runa. Zanim skończymy, jeśli chcesz wesprzeć podcast, możesz wyszukać DevStoriesEU na Patreonie, co zawsze bardzo doceniam. A oto co jest w tym wszystkim najważniejsze. Prawdziwa odporność pipeline'u nie bierze się z zapobiegania każdemu możliwemu błędowi, ale z używania conditions, żeby upewnić się, że twój system dokładnie wie, jak obsłużyć faila, gdy ten nieuchronnie wystąpi. Dzięki za wysłuchanie. Do usłyszenia następnym razem!
8

Reużywalność w skali enterprise: YAML Templates

4m 12s

Skaluj architekturę swoich pipelines na dziesiątki repozytoriów za pomocą YAML Templates. Poznaj różnicę między 'Includes' a 'Extends' i dowiedz się, jak egzekwować wymogi bezpieczeństwa w całej organizacji.

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. Azure Pipelines, odcinek 8 z 10. Masz pięćdziesiąt microservices i właśnie zaktualizowałeś definicję builda dla jednego z nich. Teraz musisz ręcznie skopiować i wkleić ten blok YAML jeszcze czterdzieści dziewięć razy. Jeśli kopiujesz i wklejasz kod między pipelines, zaciągasz ogromny dług techniczny i uniemożliwiasz globalne aktualizacje security. Rozwiązaniem jest Enterprise Reusability: szablony YAML. Szablony pozwalają ci zdefiniować logikę pipeline'u raz i reużywać jej w dowolnym miejscu. W Azure Pipelines szablony działają na dwa zupełnie różne sposoby: Includes i Extends. Szablon typu Include działa dokładnie tak samo, jak operacja copy-paste wykonana przez kompilator pipeline'u. Bierzesz wspólną sekwencję, na przykład instalację zestawu dependencies albo publikowanie artifactu, zapisujesz ją jako osobny plik YAML, a następnie odwołujesz się do niej ze swojego głównego pipeline'u. Kiedy pipeline startuje, zaciąga zawartość tego zewnętrznego szablonu bezpośrednio do twojego aktywnego joba lub stage'a. To przydatne, żeby nie powtarzać kodu, ale nadal zostawia developerowi pełną kontrolę nad strukturą pipeline'u. To on decyduje, czy, kiedy i gdzie zaincludować twój szablon. I tu jest kluczowa sprawa. Kiedy centralny zespół platformowy musi wymusić pewne reguły, nie używa Includes. Używa Extends. Szablon typu Extends odwraca strukturę kontroli do góry nogami. Zamiast zaciągać fragmenty logiki do pipeline'u developera, pipeline developera deklaruje, że robi extends centralnego szablonu. Ten centralny szablon dyktuje dokładne stage, joby i ogólny szkielet całego pipeline'u. Developer może przekazać swoje konkretne instrukcje tylko w określone sloty, które szablon jawnie zostawia otwarte. Weźmy na przykład wymóg zespołu security. Wymagają, aby każdy microservice uruchomił skaner kodu do Static Application Security Testing, czyli SAST, zanim jakikolwiek kod się skompiluje. Aby to wymusić, piszą szablon Extends, który definiuje joba z dwoma stepami. Pierwszy step to obowiązkowy skaner SAST. Drugi step to placeholder na akcje developera. Plik pipeline'u zespołu developerskiego nie robi nic poza wskazaniem na ten centralny szablon i przekazaniem swoich konkretnych komend builda do tego placeholdera. Zespół platformowy ma gwarancję, że skaner uruchomi się jako pierwszy, za każdym razem, bez konieczności audytowania pięćdziesięciu osobnych plików YAML. Żeby przekazać te komendy lub inne informacje do szablonów, używasz Template Parameters. Ludzie często mylą parameters z variables, ale ich zachowanie jest fundamentalnie inne. Variables są ewaluowane w czasie runtime'u i zazwyczaj są po prostu luźno ustrukturyzowanym tekstem. Parameters są ewaluowane w czasie kompilacji. Zanim pipeline w ogóle zacznie się wykonywać, Azure DevOps parsuje szablony i rozwiązuje wszystkie parameters. Ponieważ dzieje się to w czasie kompilacji, parameters oferują rygorystyczne sprawdzanie bezpieczeństwa. Możesz zdefiniować precyzyjne typy parametrów, takie jak boolean, number, czy list of steps. Możesz wymusić wartości domyślne albo ograniczyć input do predefiniowanej listy dozwolonych stringów. Jeśli developer spróbuje przekazać stringa do parametru typu boolean, pipeline odmówi kompilacji. To silne typowanie zapobiega błędom w runtime i zapewnia, że szablon zachowa się dokładnie tak, jak zaplanował to centralny zespół. Wymuszając ewaluację i type-checking struktury pipeline'u przed rozpoczęciem wykonywania, szablon Extends działa jak granica architektoniczna. Całkowicie oddziela to, co budują developerzy, od tego, jak organizacja to zabezpiecza. To wszystko w tym odcinku. Dzięki za wysłuchanie i buduj dalej!
9

Kierowanie wdrożeniami za pomocą Environments

4m 10s

Przenieś swój pipeline z poziomu zwykłego 'uruchamiania kodu' do zarządzania rzeczywistymi wdrożeniami. Omawiamy typ Deployment Job, Environments oraz strategie wdrażania, takie jak runOnce i Canary.

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. Azure Pipelines, odcinek 9 z 10. Możesz łatwo napisać standardowy job w pipeline, który odpala shell script, żeby zrobić push kodu na serwer. Ale kiedy uderzy krytyczny bug i ktoś zapyta, co dokładnie weszło na produkcję w zeszły wtorek, ten standardowy job da ci tylko logi z konsoli. Żeby mieć prawdziwy ślad audytowy tego, co i gdzie zostało zdeployowane, potrzebujesz Targeting Deployments with Environments. Environment w Azure DevOps to logiczna kolekcja zasobów, na które targetujesz swój deploy. Nazywasz je na przykład production albo staging, i służy ono jako punkt zaczepienia do śledzenia. Zamiast używać standardowego joba w pipeline do pushowania kodu, używasz specjalnego słowa kluczowego, czyli deployment job. Kiedy podepniesz deployment job do Environment, Azure DevOps automatycznie śledzi konkretne commity i work itemy, które są deployowane na ten konkretny target. Dostajesz pełną historię deployów w interfejsie użytkownika bez pisania żadnej dodatkowej logiki logowania. Jest jedna główna różnica w tym, jak zachowują się deployment jobs w porównaniu do standardowych jobów. Standardowy job automatycznie pobiera twoje repozytorium z kodem źródłowym. Deployment job tego nie robi. Domyślnie całkowicie pomija krok checkout. To zaskakuje wielu developerów. Powód jest prosty. Zanim dotrzesz do fazy deployu, powinieneś deployować prekompilowany artefakt albo container image stworzony na wcześniejszym etapie buildu. Zazwyczaj nie potrzebujesz surowego kodu źródłowego na deployment runnerze. Jeśli faktycznie potrzebujesz repozytorium źródłowego, musisz jawnie powiedzieć deployment jobowi, żeby zrobił checkout. Kiedy definiujesz deployment job, nie podajesz płaskiej sekwencji tasków. Opakowujesz te taski w deployment strategy. Najpopularniejsza strategia to run once. Jak sama nazwa wskazuje, po prostu wykonuje ona twoje kroki deployu sekwencyjnie na danym environment. Jeśli potrzebujesz czegoś bardziej złożonego, możesz użyć strategii canary. Canary pozwala ci zdeployować aplikację na mały procent serwerów, monitorować błędy, a potem stopniowo robić roll out nowej wersji na resztę. To ogranicza szkody w przypadku złego release'u. Wewnątrz tych strategii, twoje taski są zorganizowane w lifecycle hooks. To wymusza czystą strukturę. Najpierw masz hook pre-deploy, gdzie możesz zainicjować zasoby albo odpalić migracje bazy danych. Potem pojawia się hook deploy, który pushuje nową wersję twojej aplikacji. Po tym, hook route-traffic zajmuje się przerzuceniem requestów sieciowych na nowo zdeployowaną wersję. Na koniec możesz użyć post-route-traffic, żeby odpalić health checki albo posprzątać stare zasoby. Jeśli coś pójdzie nie tak, są też hooki on-failure i on-success do obsługi rollbacków albo powiadomień. Weźmy scenariusz, w którym używasz strategii run once, żeby spushować container image do namespace'u w Kubernetesie. W swoim pipeline definiujesz deployment job targetujący twoje Environment production. Wewnątrz strategii run once, używasz hooka deploy, żeby zdefiniować task, który bierze twój zbudowany artefakt kontenera i aplikuje deployment manifest na klaster. Nie musisz robić checkoutu repozytorium, ponieważ container image jest już zbudowany i zapisany w twoim registry. Kiedy ten pipeline rusza, taski się wykonują, a Azure DevOps rejestruje tę akcję. Ponieważ targetuje to Environment, możesz otworzyć interfejs, kliknąć na production i zobaczyć dokładnie, który commit wyzwolił build obrazu, który developer go napisał i że z sukcesem dotarł do klastra Kubernetes. Oto kluczowa sprawa. Przejście ze standardowego joba na deployment job nie tylko zmienia to, jak ustrukturyzowany jest twój pipeline. Zmienia twój pipeline ze ślepego skryptu automatyzacji w pełni śledzoną historię deployów. Dzięki za wysłuchanie. Do następnego razu!
10

Bramki enterprise: Approvals i Checks

3m 56s

Załóż bariery ochronne na swoje zautomatyzowane wdrożenia. W tym ostatnim odcinku sprawdzamy, jak skonfigurować Approvals, Branch Control i Exclusive Locks na Twoich Environments, aby chronić produkcję.

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. Azure Pipelines, odcinek 10 z 10. Nigdy nie chcesz, żeby zautomatyzowany pipeline robił pusha potężnej, nieodwracalnej migracji bazy danych na produkcję w piątkowy wieczór. W pełni zautomatyzowany pipeline jest świetny, dopóki nie ztriggeruje się w złym momencie albo bez nadzoru człowieka. Właśnie tutaj Enterprise Gates, a konkretnie Approvals and Checks, rozwiązują ten problem. Zanim przyjrzymy się konkretnym checks, musimy wyjaśnić jedno powszechne nieporozumienie. Approvals and checks nie są definiowane w twoim pliku YAML pipeline'u. Są one konfigurowane w UI Azure DevOps, bezpośrednio na samym zasobie, takim jak Environment czy Service Connection. To rozróżnienie ma ogromne znaczenie. Gdyby te reguły znajdowały się w pliku YAML, deweloper mógłby zedytować plik na feature branchu, usunąć produkcyjne checks i ominąć zabezpieczenia. Umieszczając konfigurację na zasobie, to jego właściciel wymusza te reguły. Dzięki temu twój compliance jest zabezpieczony przed manipulacją. Kod pipeline'u po prostu prosi o użycie zasobu, a zasób decyduje, czy warunki deployu są spełnione. Przełóżmy to na konkretny scenariusz. Masz environment o nazwie Production. Chcesz wymusić bezpieczeństwo release'ów i compliance z ITIL bez utraty automatyzacji. Po pierwsze, chcesz zapobiec deployom w weekendy. Na environment Production w UI, dodajesz check Business Hours. Definiujesz dozwolone okno czasowe, na przykład od poniedziałku do czwartku, od dziewiątej do piątej w twojej lokalnej strefie czasowej. Jeśli pipeline spróbuje zrobić deploy poza tym oknem, zatrzymuje się. Czeka w stanie pending, aż zaczną się godziny pracy. Koniec z migracjami w piątkowe wieczory. Następnie potrzebujesz ludzkiego sanity check. Dodajesz check Manual Approval i przypisujesz go do konkretnej grupy, na przykład zespołu QA. Kiedy pipeline dotrze do stage'a deployu na Production, zatrzymuje się. Do zespołu QA wysyłany jest mail. Przeglądają oni zmiany i jawnie dają approve lub reject dla tego runa w portalu Azure DevOps. Dopiero po zatwierdzeniu pipeline wznawia działanie. Możesz nawet wymusić sekwencję ewaluacji, wymagając, żeby check Business Hours przeszedł pomyślnie, zanim zostanie wysłane powiadomienie o manual approval. Teraz musisz zagwarantować, że eksperymentalny kod się nie prześlizgnie. Wdrażasz Branch Control. Dodajesz check, który mówi, że tylko main branch ma pozwolenie na targetowanie environmentu Production. Jeśli ktoś ztriggeruje pipeline z feature brancha, check automatycznie failuje. Deploy jest blokowany, zanim w ogóle spróbuje się uruchomić. Na koniec zostaje kwestia współbieżnych deployów. Jeśli dwóch deweloperów zmerguje kod w odstępie dziesięciu minut, możesz skończyć z dwoma pipeline'ami, które próbują jednocześnie zaktualizować tę samą infrastrukturę produkcyjną. Check Exclusive Lock zapobiega temu race condition. Zapewnia on, że tylko jeden run pipeline'u może mieć dostęp do environmentu w danym czasie. Drugi pipeline po prostu czeka w kolejce, aż pierwszy się skończy, gwarantując czystą, sekwencyjną historię deployów. Oto kluczowy wniosek. Approvals and checks odbierają władzę nad deployem z kodu pipeline'u i przekazują ją właścicielowi infrastruktury, tworząc bezpieczną, niezmienną granicę wokół twoich krytycznych systemów. Ponieważ to już ostatni odcinek naszej serii o Azure Pipelines, gorąco polecam zajrzeć do oficjalnej dokumentacji Microsoftu i wypróbować te konfiguracje w praktyce. Jeśli chcesz zaproponować tematy do naszej kolejnej serii, wpadnij na DEV STORIES DOT EU. To wszystko w tym odcinku. Dzięki za wysłuchanie i buduj dalej!