Open Source Development Course Continuous Integration and Delivery Vojtech Trefný vtref nyOredhat. com 26. 3. 2020 # twitter.com/vojtechtrefny O github.com/vojtechtrefny Nj/ gitlab.com/vtrefny Pipeline CI/CD Pipeline • Steps that need to be performed to test and deliver new version of the software. • Defines what needs to be done: when, how and in what order. • Steps can vary for every project. • Multiple pipelines or steps can run in parallel. prepare- cloud-image-Start environment koji-build compose nvr-verify package-tests End •—o-o-©-©-@—• 1/28 Na obrázku je ukázka testovací pipeline z Fedora Cl. Je zde vidět postup pro otestování nového buildu RPM balíčku, který se (v případě úspěšného projetí testů) dostane do Fedory. Podroběji si tento proces popíšeme v části demo, kde jsou i podrobnější poznámky. CI/CD Pipeline 1. Testing environment Preparation of the environment to run the tests: deploying containers, starting VMs... 2. Static Analysis Finding defects by analyzing the code without running it. 3. Codestyle Checking for violations of the language or project style guides. 4. Build Building the project from source. 5. Tests Running project test suite or test suites. 6. Packaging and Deployment Building source archives, packages or container images. 2/28 Výše popsané kroky jsou jen příkladem Cl pipeline. V různých projektech se mohou jednotlivé kroky lišit, některé chybět a naopak přibýt některé jiné, záleží podle typu projektu a použitého programovacího jazyka. Jednotlivé kroky nemusí být prováděny v daném pořadí a celá pipeline nemusí být lineární -kroky, které se dají paralelizovat se obvykle paralelizují pro urychlení celé operace - například testy a statická analýza mohou běžet souběžně zcela bez problémů. Část „CD", tedy deployment nebo delivery, je často samostatná a nemusí vždy proběhnout - u pull requestů se často pouští jen testy a balíčky/image se řeší pouze při vydání. Testing Environment Testing Environment 1. Preparation of VMs/containers to run the tests Configuration Matrix xS6_64 i636 arm 64 f_30 a© aid • f_31 • f_r^whide • • centos_7 • debian 1 0 ad debian t a J • rhel_8 a j 9 0 We might want to run tests in different environments on multiple different distributions or architectures. 2. Installation of the test dependencies Test dependencies are usually not covered by the project dependencies. 3. Getting the code Clone the PR or get the latest code from the master branch. 3/28 Na obrázku je příklad testovací matice jednoho z našich projektů. Pro co nejlepší pokrytí testy se snažíme testovat na různých distribucích i architekturách. Každá kombinace představuje jeden virtuální stroj, na kterém běží testy. Většina projektů si vystačí se spouštěním testů v kontejnerech nebo jinýh jednodušších prostředích, ale někdy je vhodné testovat na co nejširší škále systémů. Takové testy pak mohou pomoci odhalit problémy se závislostmi (chybějící knihovny nebo staré verze knihoven na „stabilních", tedy starších, distribucích a v případě různých architektur je takto možné odhalit například chyby při ukládání dat s nesprávnou endianitou. Rozsáhlejší testovací matice jsou časté také u webových projektů, kdy se testuje na mnoha různých webových prohlížečích. Static Analysis Static Analysis • Tools that can identify potential bugs by analyzing the code without running it. • Can detect problems not covered by the test suite - corner cases, error paths etc. • Coverity (C/C++, Java, Python, Go... )x • Cppcheck (C/C++)2 • Pylint (Python)3 • RuboCop (Ruby)4 1 https://scan.coverity.com 2 http://cppcheck.sourceforge.net/ 3 https://www.pylint.org 4 https://docs.rubocop.org 4/28 Coverity Error: USE_AFTER_FREE (CWE-825) : libblockdev-2.13/src/plugins/lvm-dbus.c:1163: freed_arg: "g_free" frees "output". libblockdev-2.13/src/plugins/lvm-dbus.c:1165: pass_freed_arg: Passing freed pointer "output" as an argument to "g_set_error". # 11631 g_free (output); # 11641 if (ret == 0) { # 1165 I-> g_set_error (error, BD_LVM_ERR0R, BD_LVM_ERROR_PARSE, # 11661 "Failed to parse number from output: J\°/0s # 11671 output); j ii 5/28 Ukázka výstupu nástroje coverity na Céčkovém zdrojáku. Statická analýza zde odhalila chybu, která by jinak vedla k pádu programu. Paměť uvolněná na řádce 1163 se používá na řádce 1165. Protože se jedná o chybový stav dané funkce je možné, že tento stav není pokrytý jednotkovými testy, které by tak tento problém neodhalily. Code Style Code style and style guides • Coding conventions - naming, code lay-out, comment style... • Language specific (PEP 85), project specific (Linux kernel coding style6) or library/toolkit specific (GTK coding style7). • Automatic checks using specific tools (pycodestyle) or (partially) by the static analysis tools. 5 https://www.python.org/dev/peps/pep-0008/ https://www.kernel.org/doc/html/v5.3/process/coding-style.html ^https://developer.gnome.org/programming-guidelines/stable/c-coding-style.html.en 6/28 Pokud budete (nejen v rámci tohoto předmětu) přispívat do nějakého open source projektu, vždy si napřed zjistěte, jestli má nějaký code style. I pokud nemá žádný formalizovaný, pokuste se dodržovat styl, jakým je kód napsaný. Nedodržení zavedených stylů případného reviewera vašeho pull requestu minimální rozladí, v některých případech bude takový příspěvek automaticky zamítnut bez ohledu na to, zda je jinak přínosný či ne. Code style and style guides I 11 1 Beautiful is better than ugly. Explicit is better than implicit. Simple is better than complex. Complex is better than complicated. Flat is better than nested. Readability counts. Tim Peters The Zen of Python 7/28 Linux kernel coding style https://www.kernel.org/doc/html/v4.10/process/coding-style.html Don't put multiple statements on a single line unless you have something to hide: tf (condition) do this; dosomethingeverytime; The preferred form for allocating an array is the following: p = kmalloc_array(n. sizeof(...). ■■■); Do not unnecessarily use braces where a single statement will do. tf (condition) actionQ ; 8/28 Python and PEP8 https: //gist.github.com/vojtechtrefny/435737417be003873a7f94aa7d53c4d2 vtrefny : bash — Konsole <2i File Edit View Bookmarks Settings Help Fny@aida py:ll:6: py:ll:80 . py:15:1: . py:21:22 .py:24:41 ,py:30:54 py:31:6: py:34:l: py:34:l: Fny@aida -]$ pycodestyle-3 style.py E211 whitespace before '( ' : E501 line too long (85 > 79 characters) I E303 too many blank lines (3) : E701 multiple statements on one line (colon) : E703 statement ends with a semicolon : E502 the backslash is redundant between brackets E128 continuation line under-indented for visual indent W293 blank line contains whitespace W391 blank line at end of file -]$ I 9/28 Python and PEP8 pepSspeaks commented on 18 Feb Hello @vojtechtrefny! Thanks for updating this PR. We checked the lines you've touched for PEP 8 issues, and found: • In the file capr_builder/copr_builder . py : Line 31:54: E261 at least two spaces before inline comment 10/28 Ačkoli je PEP8 standard, ne všechny Python projekty jej používají, u některých může být zaveden jiný code style. I projekty, které PEP8 dodržují nemusí striktně vyžadovat dodržování všech jeho pravidel. Například omezení na 79 znaků na řádek je velice kontroverzní a mnohé projekty si stanovují vlastní omezení. Na orbázcích výše je výstup kontroly pomocí programu pycodestyle a kontrola pull requestů na GitHubu pomocí aplikace pep8speaks, kterou je možné u open source projektů zapnout zdarma. Documentation style • Documentation might be checked in the same way code is. • Similar style documents and tools for checking documentations exist (for example PEP 2578and pydocstyle9for Python). • In some cases wrong or missing documentation (docstrings in the code) can lead to a broken build or missing features. https://www.python.org/dev/peps/pep-0257/ http://www.pydocstyle.org 11/28 Build Build • Building the project, a preparation to run the test suite. • Depends on language - mostly no-op for interpreted languages, more complicated for compiled ones. • Build in the CI environment can detect issues with dependencies. • Builds on different architectures can help detect issues related to endianness or data types sizes. 12/28 GNU Autotools • Helps creating portable source packages. • Two steps: • configure (scans the build environment) • make (compiles the source) • Complicated for developers, easy for users. • Takes care of dependency checking, dynamic linking, installation destinations etc. 13/28 GNU Autotools I saw a book entitled "Die GNU Autotools"and I thought "My feelings exactly". Turns out the book was in German. Tim Martin10 10https://twitter.com/timmartin2/status/23365017839599616 Image source: https://developer.gnome.org/anjuta-build-tutorial/stable/create-autotools.html.en 14/28 Složitost jednotlivých build systémů se liší podle použitého jazyka a frameworku. Nejsložitější je nejspíše u kompilovaných jazyků. Jako příklad (částečně odstrašující) může posloužit rodina nástrojů GNU Autotools, na kterou narazíte především u projektů napsaných v jazyce C. Kromě samotné kompilace daného projektu mají Autotools na starosti především zjištění informací o systému, kontrolu závislostí a jejich správné přilinkování k danému projektu. Cílem Autotools je aby pro uživatele bylo snadné daný projekt/program nainstalovat a obvykle díky tomu stačí obecné ./configure && make && make install, ale za cenu velké složitosti pro programátory, kteří musíš Autotools často bojovat a díky tomu se netěší zrovna velké oblíbenosti. Velkou složitostí se ale vyznačují všechny pokročilé build systémy a pokud budete přispívat do některého linuxového nebo GNU projektu, tak na Autotools stoprocentně narazíte. Tests Tests • Running tests that are part of the project. • New tests should be part of every change to the codebase. • New features require new unit and integration tests. • Bug fixes should come with a regression test. • For some project (like libraries) running test suites of their users might be an option. 15/28 Coverage • Code coverage (or Test coverage) represents how much of the code is covered by the test suite. • Usually percentual value that shows how many lines of the code were "visited" by the test. • Generally a check that all functions and branches are covered by the suite. • Used as a measure of the test suite "quality". 16/28 Coverage 1 def div{a, b)fl 2 if b == 0: 3 raise ValueError 4 else: 5 return a / b 6 7 assert div(2f ) == $ coverage3 report -m Name Stmts Miss Cover Missing div.py 5 1 80°/0 3 Resulting coverage is 80 %, because 1 of 5 statements is not covered. 17/28 Coverage je občas vnímáno jako jediná správná míra kvality testů a mnoho projektů se hodí za 100% coverage, ale občas se přitom zapomíná, že plné pokrytí neznamená, že testy jsou skutečně kvalitní. Na obrázku je nadsazená ukázka testu, který pokrývá 80 % kódu, ale kdyby daná funkce vracela vždy 1, tak je pokrytí stejné, ale test neodhalí, že funkce ve skutečnosti vůbec nefunguje. Na druhou stranu je vhodné coverage sledovat a ujistit se, že testy pokrývají skutečně všechny stavy, do kterých se daná funkce může dostat. Coverage • Automated coverage tests might be part of the CI. • Decrease in coverage can be viewed as a reason to reject contribution to the project. coveralls commented on 17 Oct 2018 • edited » +(gj ... coverage 90% Coverage increased (+0.04%) to 89.725% when pulling aa7b2c5 on svmhdvn:svmhdvn/spellcheck into f4ebdce on PyCQA:mas1er. 18/28 Obecně, pokud budete přispívat do nějaké projektu, součástí vašeho příspěvku by měly vždy být testy Obvzlášť, pokud přidáváte nějakou novou funkcionalitu. Pokud projekt sleduje cov-erage svých testů a po přidání vašich změn coverage klesne, může to být důvod k zamítnutí navrhovaných změn. Delivery and Deployment Packaging and publishing • Delivery - releasing new changes quickly and regularly (daily, weekly...). • Deployment - delivery with automated push to production, without human interaction. • Usually after merging the changes, not for the PRs. • Building packages, container images, ISO images... • Built packages can be used for further testing (manually by the Quality Assurance or in another CI infrastructure) or directly pushed to production or included in testing/nightly builds of the project. 19/28 „CD" část celého CI/CD procesu hodně záleží na daném projektu a jeho výstupech. Pokud projekt jen poskytuje knihovnu nebo GUI aplikaci, výstupem může být prostě tarball se zdrojovými kódy nebo balíček pro určitou distribuci a poslední krok už se řeší zcela jinde (například v distribuci jako samostatný CI/CD proces). Projekt může ale také nabízet nightly buildy, tedy každodenní buildy s nejnovějšími změnami a pak je třeba řešit, jak tyto buildy uživatelům zpřístupnit. Způsoby opět záleží na okolnostech - Python projekty mohou nabízet daily buildy v PyPI, Fedora má Copr repozitáře, Ubuntu PPA atp. Proces se může napříkla lišit i v rámci jednoho projektu - například u Fedory je možné do aktuálně vyvíjené verze (rawhide) publikovat nové verze balíčků okamžitě prakticky bez omezení, u stabilních distribucí musí projít ještě dalším testování a jsou umisťovány do speciálního repozitáře a teprve po 14 dnech se dostanou ke všem uživatelům. V některých případech (u projektů zaměřených na vysokou stabilitu) může být tento postup i částečně manuální a nová verze musí projít manuálním testováním a schválením. CI Tools Demo Travis CI • Probably most popular CI service nowadays. • Can be integrated in your projects on GitHub. • Free for opensource projects. • Configured using .travis.yml file in the project • https://travis-ci.org 20/28 Travis CI All checks have passed 1 successful check Hide all checks e Travis CI - Pull Request Successful in 44s — Build Passed This branch has no conflicts with the base branch Merging can be performed automatically. Details Merge pull request or view command line instructions. 21/28 Travis Cl y vojtechtrefny / copr-builder < lam Current Branches Build History Pull Requests v" Pull Request £41 Add a first simple testfor topr_builder Parsing of config files is covered. ■■ Commit ef796cc c tj #41: Add a first símpletestfor copr_builder i71 i; Branch master Ji, Vojtech Trefny $ 0 Python Moreoptions ; H #25 passed O Restart build (Tf Ran for44 sec .-.| 3 days ago 22/28 Travis je oblíbený především díky velmi snadné integraci u projektů hostnovaných na GitHubu nebo GitLabu. Na GitHubu lze Travis přidat do projektu v Marketplace téměř bezpracné. Samotné spouštění testů se pak nastavuje pomocí YAML souboru umístěného v daném re-pozitáři. Ukázka spouštění testů u velice jednoduchého Python projektu: https: //github. com/vojtechtrefny/copr-builder/blob/master/.travis .yml - projekt má vlastní Makefile, který umožňuje spouštění testů a stačí tedy říct Travisu, jaké závislosti je třeba doinstalovat a jakými příkazy testy pustit a na jaké branchi (branchích). Automation system, not a "true" CI/CD tool. Can automatically run given tasks on a node or set of nodes. Tasks can be started on time basis or triggered by an external event (like new commit or PR on GitHub). https://j enkins.io/ • Complex CI system with task to deliver an "Always Ready Operating System". • Packages are tested after every change and "gated" if the CI pipeline fails. • The goal is to prevent breaking the distribution. CI will stop the broken package before it can affect the distribution. Fedora CI prepare- cloud-image-Start environment koji-build compose nvr-verify package-tests End •-o-©-©-©-©-• package-tests - 5m 19s [/j i ✓ > Currently checking if package tests exist — Print Message Deleting old packages Cloninghttps://src.fedoraproject.org/rpms/vim/into the f30 branch 3s •y > rpm -q standard-test-roles — Checking if standard-test-roles are installed Getting list of tags 2s ✓ > Print Message Print Message CI Notifier 5s •y > Print Message CI Notifier 5s ✓ > Creating directory /workDir/workspace/fedora-f30-build-pipeline/package-tests /tmp/package-testsh - Shell Script 4m 33s ✓ > logs/ — Verify if file exists in workspace