=== Git === Git Workflow ============ Abbiamo deciso di adottare un modello "ibrido" fra git flow e feature (topic) branches. Nello specifico, si lavora per topic branches con la possibilità, per progetti più grandi e strutturati, di avere stratificazione delle topic branches con alcune long-lived topic branches grosse divise a loro volta in subtopic branches. On top del lavoro in branch, deve essere utilizzata una nomenclatura del versioning che permetta agli sviluppatori di risalire in maniera puntuale sia alla tipologia di commit che viene identificata da quella determinata versione del software, sia al livello di qualità del software che si sta prendendo in esame. Per fare un esempio banale, ci si aspetta che qualsiasi versione di software che vada in produzione sia ALMENO 1.0.0. Consultare il paragrafo **Versioning** per maggiori dettagli. Distinguiamo quindi 3 tipologie principali di branches: 1. **Main branches** (vita lunga): spesso sarà solo master, sono branches di integrazione che devono essere sempre buildabili e senza pezzi incompleti, deployabili. Su queste branch in genere ogni commit equivale ad una release (= tag). Non si committa mai direttamente ma solo tramite merge requests. Possono essere più di una nel caso di diverse "edizioni" o versioni che devono vivere ed evolversi in parallelo. 2. **Release branches** (vita media o corta): nonostante il nome, queste non devono essere necessariamente collegate alle release, ma sono da intendere come grandi branch che raccolgono varie topic branches in un "pacchetto" di nuovi sviluppi. Sono quindi un intermedio fra topic branches e main branches che possono risultare utili in progetti più grandi e/o a cui collaborano tante persone, ma non sono obbligatorie. Dovrebbero quindi corrispondere, a grandi linee, ai tasks su odoo una volta che verranno introdotti i sub-tasks. 3. **Topic branches**: le tipiche topic/feature branches standard in tanti git workflow [#]_, una per ogni modifica indipendente. .. highlights:: “The idea is to give a clear, highly-focused purpose to each branch.” .. [#] https://www.atlassian.com/git/tutorials/comparing-workflows/gitflow-workflow In generale ogni branch dovrebbe essere atomica e dunque indipendente dalle modifiche fatte su altri branch, cioè non dovrebbe mai essere necessario mergiare downstream (cioè da branch più generale a una più specifica), spesso la necessità di far ciò implica una suddivisione in branches sbagliata. Si fanno i merge dunque solo upstream (es. Topic -> Release -> Main) Nel caso (da evitare) che sia necessario pullare modifiche fatte su altre branch: * Se alla branch ci lavori solo tu e non è stata mai presa da altri, è possibile e consigliato fare rebase per avere una history più pulita * Se la branch è condivisa, e **assolutamente in tutti i casi in cui qualcuno sta usando la branch**, usare sempre e solo merge ed, in generale, nessuna operazione git che riscrive la storia (rebase, --ammend, filter-branch), rompendo il repository per gli altri. Alcuni possibili esempi pratici: Windtalk * Main branches: ``business``, ``consumer`` * Release branch: ``video-attachments`` * Subtopic branches: ``video-compression``, ``video-editing``, ``video-message``, ``recording-effects`` Buddies * Main branches: ``TIM``, ``Kena``, ``Liam`` * Topic branch: ``liam-gate``. piccola e ci lavora 1 persona quindi no bisogno per release branches. Buddies * Main branches: ``TIM``, ``Kena``, ``Liam`` * Release branche: ``redis-queue`` * Subtopic: ``put-stuff-in-queue``, ``take-stuff-from-queue`` Commits ======= Frequenza di commit ------------------- Creare commit più piccoli possibili che contengano un'unità di lavoro definita e separata dal resto. NON tenersi in pancia giorni di modifiche e poi fare un mega commit che riguarda più modifiche. I commit piccoli e atomici rendono possibile fare revert, cherry-pick ed altre operazioni intaccando il meno possibile il codice. Messaggi di commit ------------------ Riferimento: https://chris.beams.io/posts/git-commit/ .. highlights:: 1. Separate subject from body with a blank line 2. Limit the subject line to 50 characters 3. Capitalize the subject line 4. Do not end the subject line with a period 5. Use the imperative mood in the subject line 6. Wrap the body at 72 characters 7. Use the body to explain what and why vs. how Limit 50 caratteri bypassabile raramente Non iniziare il summary con -, in generale no punteggiatura iniziale e finale nel summary NON MISCHIARE LE LINGUE DEI MESSAGGI DI COMMIT! Preferire inglese per nuovi progetti (e sicuramente per progetti a cui lavorano persone che non sanno l'italiano), ma se un progetto ha tutti i commit in italiano non introdurne di nuovi in inglese. Cercare di scrivere i commit più chiari (e corretti) possibile, se ci si rende conto di un errore in un commit appena (< 30 secondi) fatto e pushato, si può sistemare con git commit --amend e push --force. Lasciare sempre la summary standard generata da git per MERGE, REVERT etc. Se si vuole aggiungere qualcosa (che non sarebbe male), farlo nel body del messaggio di commit. Varie ===== Nomi branches ------------- I nomi delle branches devono essere: * Esplicativi (NO ``feature1``, ``bugfix``, ``better-version``) * Preferibilmente tutto minuscolo con trattini per separare le parole * In inglese Esempi di buoni nomi: `fix-bug-incorrect-invoice-address`, `new-homepage-layout`, `main-view-scroll-performance-improvements` Esempi di brutti nomi: `bugfix-3`, `newDevelopments`, `improvements`, `sostituzioneRobaPerMessaggi` Versioning ---------- Il versioning in WebMonks deve seguire la nomenclatura indicata sotto: questo per garantire un metodo strutturato e organizzato, e uguale per tutti, in modo che chiunque si occupi del codice al posto nostro abbia la certezza di tutte le informazioni che gli servono per capire da dove partire e dove committare le modifiche effettuate. Risulta quindi fondamentale il **taggare** le commit effettuate. Il tag si effettua con il comando: .. code-block:: sh git tag "vx.y.z-nomebranch-lifecycleID" Notare la "v" all'inizio del tag. - Il **nomebranch** identifica il branch su cui stiamo lavorando. Abbiamo visto che **non** si lavora direttamente sul branch master, ma si crea **sempre** una nuova branch con il comando .. code-block:: sh git checkout -b nomebranch Quando si tagga il lavoro svolto, bisogna sempre inserire il nome del branch nella versione. Per **lifecycleID** si identifica in quale software release life cycle ci troviamo, associato ad un numero intero progressivo che identifica lo step su cui stiamo lavorando. Nomi validi possono essere, ad esempio: - alpha1 - beta3 Generalmente si considera come codice **alpha** tutto ciò che non è pronto nemmeno per effettuare testing: quando la vostra è applicazione è appena nata, un versioning corretto potrebbe essere: - v0.1.0-videobranch-alpha1 Questo versioning identifica un nuovo software che non è ancora pronto ad andare in produzione (essendo la Major version == 0), che si sta sviluppando la prima Minor version (1), e il codice è ancora di qualità alpha. Infine, che il tag appartiene a del codice che si trova nel branch **videobranch**. Generalmente, utilizzando il versioning spiegato qui sotto, potrebbe non essere necessario incrementare mai l'identificativo **alpha**, in quanto si sta parlando ancora di software non ancora *freezzato* (vedi sotto). Per quanto riguarda il versioning vero e proprio, x.y.z identificano, rispettivamente: - Major version: un incremento di major version identifica uno o più restyle completi dell'applicazione, una serie di breaking changes che rappresentano un nuovo ciclo di vita del software, e che lo rendono eventualmente anche incompatibile con quello precedente. Consideriamo come Major version 1 la versione *minima* per andare in produzione. - Minor version: un incremento di minor version identifica solitamente delle aggiunte di nuove funzionalità, il restyle di vecchie funzioni che mantengono, tuttavia, la compatibilità all'indietro, ma anche la correzione di bug che inficiavano il corretto funzionamento dell'applicazione. All'aumentare della Major version, occorre reimpostare la Minor version corrispondente a zero. Se state sviluppando software e siete alla v0.8.9, se ad un certo punto di accorgete che potete andare in produzione, dovendo quindi andare su una Major 1, reimpostate la versione su v1.0.0 (ed effettuate il merge su master se necessario). - Minor minor version: un incremento di minor-minor version è facoltativo ma è consigliato per avere la massima affidabilità sul versioning. Identifica modifiche minime sul codice, ma anche uno o più step che concorrono alla creazione della prossima minor version. Potreste aver bisogno di aggiornare la minor minor version anche otto, o nove volte, prima di poter incrementare la minor. Quando il codice raggiunge un certo livello di maturità, tutte le feature sono state implementate, e i bug "pesanti" siano stati tutti indirizzati e corretti, si può chiamare un **code freeze** e passare il codice alla sua prima versione **beta**. Da questo momento in poi, l'incremento di versione deve essere soltanto sull'identificativo **beta**. Ad esempio, mettiamo il caso di aver passato il nostro software in versione v0.6.4-alpha1 in beta. Lo tagghiamo il v0.6.4-beta1 e lo deployamo su preproduzione (se possiamo, altrimenti chiediamo ad un sysadmin). Da questo punto in poi cominciano i **test di integrazione**, oppure la **quality assurance** e viene controllato che il software sia perfettamente funzionante: in questa fase, se risultano delle modifiche, si incrementa l'identificativo beta ad ogni modifica. Si presuppone che a questo punto **non** vengano introdotte nuove funzionalità: siamo in code freeze e quindi testiamo, con il cliente o i sistemisti, che il nostro software funzioni correttamente, seguendo la nostra test-list end-to-end, o facendo degli unit test. Se trovassimo un bug di qualche tipo, a questo punto potremmo fare le nostre fix, e incrementare il beta a **beta2**, poi **beta3** e così via, facendo ogni volta dei nuovi tag. Quando il nostro codice è pronto per la produzione, creiamo il tag di produzione seguendo questa semplice logica: - Se il nostro versioning è già in una Major 1, lasciamo tutta la numerazione così com'è, togliamo solo il tag beta, e mergiamo su master, **rimuovendo la vecchia branch se possibile**. Ad esempio: v1.4.3-videobranch-beta8 diventa v1.4.3, mergiato su master (e il branch videobranch viene rimosso) Le branch dovrebbero essere quindi temporanee ed avere un ciclo di vita pari agli sviluppi che stiamo facendo. **A meno di rare eccezioni, su produzione verranno pullati e deployati SOLO tag NON BETA e SOLO su branch master** - Se il nostro versioning è in versione v0.x, potete passare alla v1.0.0, rimuovendo il tag beta. Ad esempio: v0.8.22-modifichechat-beta8 diventa v1.0.0, mergiato su master (e il branch modifichechat viene rimosso) Pulire le branch ---------------- Le branch inutilizzate da più di tre mesi verranno archiviate e poi, allo scadere dei sei mesi di inutilizzo, cancellate senza preavviso. Nel caso in cui una branch debba essere longterm, identificatelo nel nome del branch stesso per fare capire quali branch debbano essere mantenuti e quali no, usando il nome **lts** o **longterm**. Ad esempio: videobranch-lts. Push force ---------- * solo per rebase di topic branches non usate da nessun altro e ammend per errori nei commit appena pushati. Cosa committare --------------- Non committare mai, assolutamente: * File di configurazione veri, solo esempi con chiavi finte o esplicative, utilizzando, come nomenclatura, il nome "target" aggiungendo "sample": ad esempio, ecosystem.config.js.sample. Nel caso in cui il deploy sia "pacchettizzato" (es. webpack con Vue.js, o dei WAR java autocontenenti), è permesso committare le configurazioni in quanto il pacchetto diventa autocontenuto. Farlo, comunque, solo se strettamente necessario. * Dipendenze: queste vanno gestite con dependnce manager del framework/linguaggio o, in caso di dipendenze in-house custom, sottomoduli git. * File compilati o altro output del processo di build o esecuzione Committare sempre: * ``.gitignore`` (può essere generato da https://gitignore.io) * README * config linter se usato (e.s. eslintrc, pylintrc) Preferibilmente: * .editorconfig (https://editorconfig.org) per convenzione condivise su newlines, indentazione Cosa taggare ------------ Il *tag* è uno strumento che permette di identificare, in qualsiasi momento, una data versione di codice che reputiamo una milestone nello sviluppo, un punto fermo, o comunque una situazione in cui le modifiche sono più o meno definitive. E' ovvio che può capitare di dover interrompere il lavoro prima che le modifiche siano state terminate, e si debba pusharlo su git per non rischiare di perderlo: in questo caso, **non taggare** il software, specificando nel messaggio di commit che si tratta di una versione intermedia.