Czy dobrą praktyką jest przechowywanie numerów wersji oprogramowania w VCS?

22

Wersja produktu, na przykład v1.0.0.100, reprezentuje nie tylko unikalną wersję produkcyjną oprogramowania, ale pomaga zidentyfikować zestawy funkcji i etapy poprawek dla tego produktu. Obecnie widzę dwa sposoby utrzymania ostatecznej wersji pakietu / kompilacji / binarnej produktu:

  1. Kontrola wersji. Plik gdzieś przechowuje numer wersji. Serwer kompilacji Continuous Integration (CI) będzie miał skrypt do zbudowania oprogramowania, które korzysta z tego sprawdzonego numeru wersji w celu zastosowania go do wszystkich potrzebnych obszarów oprogramowania (pliki binarne, pakiety instalatora, strony pomocy, dokumentacja itp.).

  2. Parametry środowiska i / lub kompilacji. Są one utrzymywane poza kontrolą wersji (tzn. Nie są powiązane z migawką / znacznikiem / gałęzią). Skrypty kompilacji dystrybuują i używają liczby w ten sam sposób, jednak po prostu uzyskują wartość w inny sposób (jest ona dostarczana do skryptu kompilacji, zamiast skryptu wiedzieć, skąd wziąć go względem drzewa źródłowego).

Problem z pierwszym podejściem polega na tym, że może to komplikować połączenia między głównymi gałęziami. Jeśli nadal utrzymujesz 2 równoległe wydania tego samego oprogramowania, rozwiążesz konflikty podczas łączenia dwóch głównych linii, jeśli wersja uległa zmianie na obu od ostatniego scalenia.

Problem z drugim podejściem polega na pojednaniu. Kiedy wrócisz do wydania 1 rok temu, będziesz polegać wyłącznie na informacjach na tagu, aby zidentyfikować numer wydania.

W obu przypadkach mogą istnieć pewne aspekty numeru wersji, które nie są znane przed kompilacją CI. Na przykład kompilacja CI może programowo wstawić czwarty komponent, który tak naprawdę jest numerem kompilacji automatycznej (np. 140 kompilacja w gałęzi). Może to być także numer wersji w VCS.

Jak najlepiej nadążyć za numerem wersji oprogramowania? Czy „znane” części powinny być zawsze utrzymywane w VCS? A jeśli tak, to czy konflikty w głównych oddziałach są problemem?

Obecnie utrzymujemy nasz numer wersji za pomocą parametrów określonych i utrzymywanych w planie kompilacji CI (Atlassian Bamboo). Przed połączeniem z naszym masteroddziałem musimy zachować ostrożność, aby numery wersji były odpowiednio ustawione przed rozpoczęciem kompilacji CI . Jeśli chodzi o przepływ pracy Gitflow, uważam, że jeśli numer wersji byłby śledzony w kontroli źródła, moglibyśmy zagwarantować, że jest on poprawnie skonfigurowany, gdy tworzymy releaseoddział w przygotowaniu wydania. W tym oddziale QA przeprowadziłoby końcowe testy integracji / dymu / regresji, a po podpisaniu masternastąpi połączenie, które sygnalizuje zobowiązanie do wydania.

void.pointer
źródło
3
Czy konflikt scalania między dwiema wersjami pliku, w version.txtktórym jedna wersja zawiera jedną linię, 1.0.7a drugą 1.2.0jest tak trudny do rozwiązania? Jeśli jest to jedyny konflikt polegający na połączeniu dwóch rozdzielonych gałęzi, uważam się za bardzo szczęśliwy. Jak często to występuje? Jeśli tak się stanie, czy nie jest dobrze, że musisz zastanowić się, jaki numer wersji powinna mieć scalona wersja? (Przepraszamy za niejednoznaczne użycie słowa „wersja”.)
5gon12eder,
1
@ 5gon12eder Trudności lub odczucia związane z samym połączeniem są nieistotne. To tylko negatywny aspekt całego rozwiązania.
void.pointer

Odpowiedzi:

28

Osobiście wybieram opcję 3: zachowaj informacje o wersji w metadanych VCS , w szczególności w tagach.

Git sprawia, że ​​jest to bardzo łatwe, ponieważ istnieje polecenie git describe, które może jednoznacznie opisać zatwierdzenie na podstawie znacznika. Oto jak to działa:

  • Jeśli bieżący zatwierdzenie jest oznaczony, wypisz nazwę znacznika.
  • W przeciwnym razie, historia chodzić kierunku do tyłu, aż znajdziesz tag i wtedy wyjście opis w następującym formacie: <tag>-<number of commits since the tag>-g<abbreviated commit hash>.
  • Jeśli w drzewie roboczym występują niezatwierdzone zmiany, dołącz -dirty.

Tak więc, jeśli robisz kompilację wydania i masz zaznaczone zatwierdzenie 1.2.3, wyświetli się 1.2.3. Jeśli obecnie pracujesz nad wersją 1.2.4 i dokonałeś 4 zatwierdzeń od wersji 1.2.3 i masz niezatwierdzone zmiany w drzewie, zostanie ono wypisane 1.2.3-4-gdeadbee-dirty.

Gwarantuje to, że jest unikalny i monotoniczny, a także czytelny dla człowieka, a zatem może być używany bezpośrednio jako ciąg wersji. Jedyne, co musisz zapewnić, to odpowiednia konwencja nazewnictwa tagów.

Jörg W Mittag
źródło
Naprawdę podoba mi się ten pomysł, ale wydaje się to trudne do zarządzania w JIRA + Bamboo. Bamboo działa tylko na gałęziach, a nie na tagach, więc przed wygenerowaniem kompilacji musisz upewnić się, że tag został wypchnięty. Jest to podatne na błędy.
void.pointer
1
git describedziała również z gałęziami: „ --all - Zamiast używać tylko tagów z adnotacjami, użyj dowolnego odwołania znalezionego w refs/przestrzeni nazw. Ta opcja umożliwia dopasowanie dowolnej znanej gałęzi, gałęzi zdalnego śledzenia lub lekkiego tagu”. Nie jestem jednak pewien, jak to działa z Bamboo. (Będzie to oczywiście wymagało ostrożnego nazywania gałęzi, tak jak normalny tryb z tagami.)
Jörg W Mittag
1
Znam ludzi, którzy robią całkowicie automatyczne wydania Gita. Ciąg wersji jest budowany przez git describe, dziennik zmian jest generowany na podstawie git shortlog(cóż, właściwie ze skryptu, który analizuje dane wyjściowe git log --pretty=tformat:<some custom format string>), a informacje o wersji są generowane z opisu znacznika i git notesdołączane do ważnych zatwierdzeń kamienia milowego.
Jörg W Mittag
Chodzi mi o to, że tag musiałby zostać utworzony przed wydaniem, aby zatwierdzenia były odpowiednio wersjonowane z numerem podstawowym. Jest to sprzeczne z zasadą tagowania podczas lub w momencie wydania. Bamboo pobiera kompilacje automatycznie na podstawie commits do master(od develop, pamiętaj, że używam gitflow). Co się stanie, jeśli ktoś prześle scalenie masterbez tagu? Nie użyje odpowiedniej wersji (w rzeczywistości użyłby wersji z ostatniego wydania)
void.pointer
Jeśli używasz takiego schematu, tagowanie jest zwalniające. Ach, rozumiem, o co ci chodzi, tak myślę. Więc obecnie twój serwer CI jest sterownikiem wydania, a przy tej zmianie SCM jest sterownikiem wydania, ale czy chcesz, aby tak pozostało?
Jörg W Mittag
8

Tak. Dobrą praktyką jest przechowywanie większości numerów wersji w vcs. Jeśli weźmiemy pod uwagę semantyczną wersję semver.org, gdzie mamy major.minor.patch.build, pierwsze trzy muszą znajdować się w vcs. Ostatnim może być liczba rosnąca z serwera kompilacji używana do cofania określonego zatwierdzenia, z którego wykonany jest plik binarny.

Aby to ułatwić w .NET, stworzyliśmy małą exe linii cmd, która jest zaangażowana w git. W przypadku zdarzenia przed kompilacją wybiera numer kompilacji oznaczony przez teamcity podczas kompilacji. To narzędzie linii cmd automatycznie generuje klasę z jedną stałą zawierającą numer kompilacji. Reszta numeru wersji: major.minor.patch jest zwykłą stałą w innym pliku. Te dwa udostępnione pliki są dołączone do każdego zestawu w rozwiązaniu jako łącze (alt + shift-drag).

To podejście jest na tyle potężne, że możemy zbudować teamcity i przetestować nasz kod. Naciśnij lazur i niech Kudu zbuduje go ponownie, ale z numerem kompilacji teamcity jako wersją dll.

Esben Skov Pedersen
źródło