Uruchamianie migracji bazy w Azure DevOps

Wprowadzenie

Już kiedyś opisywałem na tym blogu, że jednym z większych problemów, które widzę w projektach moich kursantów, są migracje bazy danych. Kilka miesięcy temu opisywałem trzy różne podejścia: migrację w Entity Framework, Fluent Migratora oraz DbUp. Podejścia te, jak sądzę, pokrywają większość przypadków, które możesz mieć w swojej aplikacji.

Kolejnym problemem związanym z migracjami jest ich uruchamianie. O ile w jakimś projekcie jest już użyty jakiś mechanizm (na ogół są to migracje z Entity Framework), to pojawia się problem z jego uruchomieniem. Na ogół niestety migracje wykonują się przy starcie aplikacji, z użyciem tego samego connection stringa, na którym działa później aplikacja. To niestety później, w przypadku wystąpienia podatności SQL Injection w aplikacji, może prowadzić do tragicznych skutków. Użyty użytkownik musi mieć podwyższone uprawnienia, aby mógł wykonać migracje i zmienić strukturę bazy danych.

W tym wpisie pokażę Ci, jak można wykonać migrację bazy danych w trakcie wdrażania aplikacji (mówimy o aplikacjach webowych). Dorzucę tutaj również możliwość tworzenia migawek bazy danych, aby można było później na danej instancji aplikacji wykonywać automatyczne testy Postmana.

Migrator

We wspomnianych wyżej wpisach utworzyłem dedykowaną aplikację konsolową do wykonywania migracji baz danych. W tym wpisie rozbuduję trochę migratora z wpisu o migracjach w Entity Framework. Jeśli nie czytałeś tego wpisu, to najlepiej, abyś zrobił to przed przeczytaniem dalszej części.

Rozbudowa migratora będzie polegać na dodaniu możliwości tworzenia migawek bazy danych, aby można było je tworzyć po zmigrowaniu bazy danych do nowego schematu. Tutaj podobnie, jeśli nie czytałeś wpisu o wykorzystaniu Sql Server Snapsthops do resetowania danych w testach, zapraszam do przeczytania.

Migrator w przypadku wykonywania migawki będzie działał w następujący sposób: cofnie stan bazy na podstawie migawki, usunie migawkę, wykona migrację bazy, utworzy nową migawkę. W pozostałych sytuacjach wykona tylko samą migrację bazy.

W tym celu rozbudowałem DatabaseRestoreService o możliwość tworzenia oraz usuwania migawek. Dodatkowo usługa loguje operacje z użyciem nLoga:

W Migratorze rozszerzyłem klasę Options poprzez dodanie dwóch nowych właściwości. CreateSnapshot służy do przekazania informacji, czy podczas migracji wykonywane będą operacje na migawkach. Natomiast SnapshotPath posłuży do przekazania ścieżki, gdzie ma zostać zapisany plik migawki:

Oczywiście tutaj można by dodać więcej parametrów. Na przykład parametr do przekazania nazwy migawki, zamiast budowania jej w określony sposób w DatabaseRestoreService.

Po wprowadzeniu nowych opcji zmieniła się również klasa Program Migratora:

Tak jak wspomniałem wyżej, w metodzie Migrate sprawdzamy wartość właściwości CreateSnapshot. Gdy jest na true, przywracamy bazę do stanu z migawki i migawkę usuwamy. Na końcu po wykonaniu migracji ponownie sprawdzamy CreateSnapshot i tworzymy nową migawkę, gdy właściwość ma wartość true.

Uruchomienie tak przygotowanego migratora wygląda w ten sposób:

Darmowy kurs Visual Studio

Pracując z setkami programistów, zauważyłem, że większość osób nie pracuje efektywnie w Visual Studio. W skrajnych przypadkach korzystali z kopiowania z wykorzystaniem menu Edit. Wiem, że to dziwne, ale naprawdę niektórzy tak pracują. Dlatego postanowiłem stworzyć kurs Visual Studio – aby pomóc koleżankom i kolegom w efektywniejszej pracy.

Przygotowałem 20 lekcji e-mail, w których pokażę Ci, w jaki sposób pracować efektywniej i szybciej w Visual Studio. Poznasz dodatki, bez których nie wyobrażam sobie pracy w tym IDE.

Po więcej informacji zapraszam na dedykowaną stronę kursu: Darmowy Kurs Visual Studio.

Quiz C#

Ostatnio przygotowałem również quiz C#, w którym możesz sprawdzić swoją wiedzę. Podejmiesz wyzwanie?

Uruchomienie migracji w Azure DevOps

Mając już przygotowanego migratora, możemy uruchomić migrację podczas wdrażania aplikacji. W tym wpisie rozbuduję definicję build oraz release z wpisu o Sql Server Snapsthops do resetowania danych w testach.

W definicji build dodałem kopiowanie plików „*.exe|*.dll|*.pdb|*.config” do folderu bin w artefaktach, aby później pliki te (w tym i migrator) były dostępne podczas wykonywania wdrożenia aplikacji. Sam krok wygląda tak:

Cały plik definicji builda znajdziesz na githubie: https://github.com/danielplawgo/WebApiTests/blob/migration/azure-pipelines.yml.

W definicji release na początku dodałem dwie nowe zmienne (MigrationConnectionString oraz SnapshotPath), które później wykorzystam podczas wywoływania migratora:

azure devops run migration variables

W zmiennej MigrationConnectionString  znajduje się connection string do bazy, który zostanie wykorzystany podczas migracji bazy danych do nowej wersji. Tak jak wspomniałem wcześniej, tutaj używamy użytkownika, który ma zwiększone uprawnienia i może zmieniać schemat bazy. Natomiast zmienna SnapshotPath zawiera ścieżkę do pliku migawki.

Do listy zadań dodałem na samej górze wywołanie komendy wiersza poleceń:

azure devops run migration cmd task

W konfiguracji taska poza zmianą nazwy ustawiłem dwie rzeczy:

  • Working Directory (w sekcji Advanced) – wybrałem folder, w którym znajduje się skompilowany migrator – są to właśnie te pliki kopiowane przez dodany do buildu aplikacji task. Ustawienie tego folderu w ten sposób powoduje, że w Script mogę już wywoływać bezpośrednio migrator
  • Script – wywołanie samego migratora z przekazaniem odpowiednich parametrów. Parametry są pobierane ze zmiennych z użyciem składni: $(nazwa zmiennej)

Dokładną zawartością Script jest:

Tak skonfigurowany task spowoduje, że przed wdrożeniem nowej wersji aplikacji zostanie wykonana migracja bazy danych oraz snapshot na potrzeby testów WebApi z Postmana.

Przykładowy log wykonania tego nowego taska:

Przykład

Kod wykorzystany w tym wpisie znajdziesz na githubie. Rozbudowałem wcześniejszy przykład i wszystkie dodatkowe zmiany znajdują się w branch migration – https://github.com/danielplawgo/WebApiTests/tree/migration. W przykładzie poza zmianą connection stringa w Web.config w projekcie WebApi należy jeszcze zmienić connection stringa we właściwościach projektu migratora w zakładce Debug, w której ustawia się parametry przekazywane w wierszu poleceń podczas uruchamiania aplikacji z poziomu Visual Studio.

Podsumowanie

Mam nadzieję, że udało mi się pokazać Ci, że wykonywanie migracji bazy danych z użyciem innego użytkownika podczas wdrażania jej nie musi być czymś skomplikowanym. Gorąco Ci polecam, abyś nie wykonywał migracji podczas startu aplikacji, bo niestety zawsze niesie to za sobą jakieś dodatkowe ryzyko.

A może u Ciebie w projekcie ten problem rozwiązaliście w inny sposób? Z chęcią dowiem się, jak to jest u Was. Zostaw komentarz pod wpisem!

1 thought on “Uruchamianie migracji bazy w Azure DevOps

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *