Differences

This shows you the differences between two versions of the page.

Link to this comparison view

ss:laboratoare:04 [2025/02/26 00:15]
jan.vaduva
ss:laboratoare:04 [2026/03/23 18:50] (current)
ciprian.popescu0411 [Partea 4: Protejarea branch-ului ''main'']
Line 1: Line 1:
-====== Laborator 4: Implementarea ​testării unitare și a acoperirii codului ​======+====== Laborator 4: Implementarea ​unui pipeline CI/CD pentru un proiect embedded ​====== 
 + 
 +În laboratorul anterior am configurat mediul de lucru și am testat comunicarea între ESP32-CAM și clientul Python. În acest laborator vom automatiza procesul de verificare a codului folosind un pipeline **CI/CD (Continuous Integration / Continuous Delivery)** cu **GitHub Actions**.
  
 ===== Obiective ===== ===== Obiective =====
-  * Implementarea testării unitare pentru funcționalitățile aplicației dezvoltate în laboratoarele anterioare 
-  * Măsurarea și analiza acoperirii codului pentru îmbunătățirea calității software 
-  * Integrarea testelor unitare în pipeline-ul CI/CD 
  
-===== Cerințe tehnologice ​===== +  - Înțelegerea conceptelor de CI/CD și a avantajelor lor în proiecte embedded. 
-  * **Limbaj șframework ​de testare**: PyTest ​(Python) / Jest (JavaScript) / JUnit (Java+  - Configurarea unui repository GitHub pentru proiect. 
-  * **Măsurarea acoperirii codului**: Coverage.pyIstanbulJaCoCo +  - Crearea unui workflow GitHub Actions care: 
-  ​* **CI/CD Pipeline**: GitHub ​Actions/​GitLab ​CI/​CD/​Jenkins ​pentru ​rularea testelor automat +    * Compilează firmware-ul ESP32 automat la fiecare push. 
-  * **Raportare șanaliză**: Codecov/SonarQube ​pentru ​interpretarea metricilor de acoperire+    * Verifică codul Python cu linting și analiză de securitate. 
 +    * Rulează analiza statică pe codul C++ al firmware-ului. 
 +  - Salvarea artifactului ''​firmware.bin''​ pentru deployment. 
 + 
 +===== De ce CI/CD pentru embedded? ​===== 
 + 
 +Într-un proiect clasic de software, CI/CD este standard. Dar și în embedded este esențial:​ 
 + 
 +  * **Preveniț"it compiles on my machine"​** — compilarea se face într-un mediu curat, reproductibil. 
 +  * **Detectare timpurie** — o eroare ​de compilare sau un warning critic este prins automat, înainte de upload pe dispozitiv. 
 +  ​* **Artefacte de release** — fișierul ''​firmware.bin''​ este generat automat și poate fi distribuit fără ca cineva să aibă PlatformIO instalat. 
 + 
 +===== Partea 1Pregătirea repository-ului de GitHub ===== 
 + 
 +==== 1.1 Inițializare Git ==== 
 + 
 +Dacă proiectul nu este deja într-un repository git: 
 + 
 +<code bash> 
 +cd /​path/​to/​proiect 
 +git init 
 +</​code>​ 
 + 
 +==== 1.2 Crearea fișierului ''​.gitignore''​ ==== 
 + 
 +Asigurați-vă că fișierul ''​.gitignore''​ generat de PlatformIO exclude fișierele generate și mediile virtuale: 
 + 
 +<​code>​ 
 +# PlatformIO 
 +.pio/ 
 + 
 +# Python 
 +.venv/ 
 +__pycache__/​ 
 +*.pyc 
 + 
 +# IDE 
 +.vscode/ 
 +.idea/ 
 + 
 +# OS 
 +.DS_Store 
 +Thumbs.db 
 +</​code>​ 
 + 
 +==== 1.3 Push pe GitHub ==== 
 + 
 +Creați un repository nou pe GitHub ​(fără README), apoi: 
 + 
 +<code bash> 
 +git add . 
 +git commit -m "​Initial commit"​ 
 +git branch -M main 
 +git remote add origin https://​github.com/​UTILIZATOR/​NUMELE-REPO.git 
 +git push -u origin main 
 +</​code>​ 
 + 
 +<​note>​ 
 +Înlocuiți ''​UTILIZATOR''​ cu username-ul vostru GitHub și ''​NUMELE-REPO''​ cu numele repository-ului creat. 
 +</​note>​ 
 + 
 +===== Partea 2: Crearea workflow-ului CI ===== 
 + 
 +Workflow-urile GitHub Actions sunt definite ca fișiere YAML în directorul ''​.github/​workflows/''​. 
 + 
 +==== 2.1 Structura fișierului ==== 
 + 
 +Creați fișierul ''​.github/​workflows/​ci.yml'':​ 
 + 
 +<file yaml ci.yml>​ 
 +name: ESP32-CAM CI Pipeline 
 + 
 +# Declanșare la push sau pull request pe branch-ul main 
 +on: 
 +  push: 
 +    branches: [ "​main"​ ] 
 +  pull_request:​ 
 +    branches: [ "​main"​ ] 
 + 
 +jobs: 
 +  # ============================================= 
 +  # Job 1: Compilarea firmware-ului ESP32 
 +  # ============================================= 
 +  build-firmware:​ 
 +    name: Build ESP32 Firmware 
 +    runs-on: ubuntu-latest 
 + 
 +    steps: 
 +      - name: Checkout code 
 +        uses: actions/​checkout@v4 
 + 
 +      - name: Set up Python 
 +        uses: actions/​setup-python@v5 
 +        with: 
 +          python-version:​ '​3.12'​ 
 + 
 +      - name: Install PlatformIO 
 +        run: pip install platformio 
 + 
 +      - name: Build Firmware (ESP32-CAM AI-Thinker) 
 +        run: pio run -e esp32cam 
 + 
 +      # Salvăm firmware.bin ca artifact descărcabil 
 +      - name: Upload Firmware Artifact 
 +        uses: actions/upload-artifact@v4 
 +        with: 
 +          name: firmware-esp32cam 
 +          path: .pio/​build/​esp32cam/​firmware.bin 
 + 
 +  # ============================================= 
 +  # Job 2: Analiza statică C++ (Firmware) 
 +  # ============================================= 
 +  analyze-firmware:​ 
 +    name: Static Analysis (C++) 
 +    runs-on: ubuntu-latest 
 + 
 +    steps: 
 +      - name: Checkout code 
 +        uses: actions/checkout@v4 
 + 
 +      - name: Install Cppcheck 
 +        run: sudo apt-get install -y cppcheck 
 + 
 +      - name: Run Cppcheck 
 +        run: | 
 +          cppcheck --enable=all \ 
 +                   ​--inconclusive \ 
 +                   ​--std=c++11 \ 
 +                   -I include/ \ 
 +                   ​--suppress=missingIncludeSystem \ 
 +                   ​--suppress=missingInclude \ 
 +                   ​--suppress=unusedFunction \ 
 +                   ​--suppress=cstyleCast \ 
 +                   ​--error-exitcode=1 \ 
 +                   ​src/​ 
 + 
 +  # ============================================= 
 +  # Job 3: Verificarea codului Python ​(Receiver
 +  ​# ============================================= 
 +  check-python:​ 
 +    name: Python Lint & Security 
 +    runs-on: ubuntu-latest 
 + 
 +    steps: 
 +      - name: Checkout code 
 +        uses: actions/​checkout@v4 
 + 
 +      - name: Set up Python 
 +        uses: actions/​setup-python@v5 
 +        with: 
 +          python-version:​ '​3.12'​ 
 + 
 +      - name: Install dependencies 
 +        run: | 
 +          pip install pylint bandit 
 +          # opencv-python-headless se folosește în CI (fără display) 
 +          pip install paho-mqtt opencv-python-headless numpy 
 + 
 +      - name: Lint with Pylint 
 +        # || true = soft-fail, pipeline-ul nu eșuează pe warning-uri pylint 
 +        run: pylint --disable=C0114,​C0115,​C0116,​C0103 receiver.py || true 
 + 
 +      - name: Security scan with Bandit 
 +        run: bandit receiver.py -ll 
 +</​file>​ 
 + 
 +==== 2.2 Explicarea workflow-ului ==== 
 + 
 +Acest workflow definește ​**3 job-uri independente** care rulează în paralel: 
 + 
 +^ Job ^ Ce face ^ Când eșuează ^ 
 +| ''​build-firmware''​ | Compilează codul ESP32 cu PlatformIO | Erori de compilare (sintaxălinkare) | 
 +| ''​analyze-firmware''​ | Rulează ''​cppcheck''​ pe codul C++ | Buffer overflowsmemory leaks, variabile neinițializate | 
 +| ''​check-python''​ | Rulează ''​pylint''​ + ''​bandit''​ pe receiver | Probleme de stil, parole hardcodate, funcții nesigure | 
 + 
 +<code text> 
 +  ​push/PR 
 +    │ 
 +    ├──► build-firmware ──► firmware.bin (artifact) 
 +    │ 
 +    ├──► analyze-firmware ──► raport cppcheck 
 +    │ 
 +    └──► check-python ──► raport pylint + bandit 
 +</​code>​ 
 + 
 +===== Partea 3: Testarea pipeline-ului ===== 
 + 
 +==== 3.1 Commit și push ==== 
 + 
 +<code bash> 
 +git add .github/​workflows/​ci.yml 
 +git commit -m "​Add ​CI pipeline"​ 
 +git push 
 +</code> 
 + 
 +==== 3.2 Verificare pe GitHub ==== 
 + 
 +  - Deschideți repository-ul pe GitHub. 
 +  - Navigați la tab-ul ​**Actions**. 
 +  - Ar trebui să vedeți workflow-ul ''​ESP32-CAM ​CI Pipeline''​ rulând. 
 +  - Faceți clic pe el pentru ​a vedea detaliile fiecărui job. 
 + 
 +==== 3.3 Descărcarea firmware-ului ==== 
 + 
 +Dacă build-ul reușește:​ 
 + 
 +  ​- Deschideți run-ul din Actions. 
 +  - La secțiunea ​**Artifacts**, vețvedea ''​firmware-esp32cam''​. 
 +  - Descărcați-l — conține ''​firmware.bin''​ gata de upload pe dispozitiv. 
 + 
 +<note tip> 
 +După descărcare,​ puteți flash-ui direct pe ESP32-CAM folosind ''​esptool''​ **fără a avea PlatformIO instalat**: 
 + 
 +<code bash> 
 +pip install esptool 
 +esptool.py --chip esp32 --port ​/dev/ttyUSB0 --baud 460800 write_flash 0x10000 firmware.bin 
 +</​code>​ 
 + 
 +Pe Windows, înlocuiți ''/​dev/​ttyUSB0''​ cu portul COM corespunzător (ex: ''​COM3''​). 
 + 
 +Acest lucru este util pentru ​distribuirea firmware-ului către colegi sau pentru deployment pe dispozitive fără a recompila codul sursă. 
 +</​note>​ 
 + 
 +===== Partea 4: Protejarea branch-ului ''​main''​ =====
  
-===== Funcționalități =====+Pentru a preveni merge-ul codului care nu trece CI-ul:
  
-==== 1Scrierea testelor unitare ==== +  - Pe GitHub: **Settings → Rules → Rulesets → New ruleset → New branch ruleset**
-  * Crearea unui set de teste unitare pentru componentele principale ale aplicației +  ​- La **Target branches** adăugați branch-ul ''​main''​. 
-  * Utilizarea mocking/​stubbing pentru izolarea dependențelor +  ​- Activați ​**Require status checks to pass** și adăugați cele 3 job-uri: ''​Build ESP32 Firmware'',​ ''​Static Analysis (C++)'',​ ''​Python Lint & Security''​. 
-  ​* Testarea funcțiilor critice de procesare a imaginilor, autentificare șinteracțiune cu baza de date+  ​- Salvați ruleset-ul.
  
-==== 2Măsurarea acoperirii codului ==== +<note important>​ 
-  ​Configurarea unui instrument de măsurare a acoperirii codului +Interfața GitHub se poate schimbaPe unele repository-uri mai vechi, opțiunea se găsește la **Settings → Branches → Add rule**. 
-  ​Generarea rapoartelor de acoperire pentru identificarea zonelor neacoperite de teste +</​note>​
-  ​Stabilirea unui prag minim de acoperire necesar pentru livrarea codului+
  
-==== 3. Integrarea testelor în pipeline-ul ​CI/CD ==== +De acum, nimeni nu poate face merge pe ''​main''​ dacă pipeline-ul ​eșuează.
-  * Configurarea rulării automate a testelor la fiecare commit/pull request +
-  * Impunerea unui prag minim de acoperire a codului pentru aprobarea unui build +
-  * Generarea ​și publicarea rapoartelor de testare și acoperire+
  
-===== Evaluare ​===== +===== Exerciții ​=====
-  * Implementarea testelor unitare pentru funcționalități cheie (40%)   +
-  * Măsurarea și raportarea acoperirii codului (30%)   +
-  * Integrarea testării și a metricilor de acoperire în pipeline-ul CI/CD (30%)  ​+
  
-===== Resurse suplimentare ===== +  - **Provocați un eșec**: Introduceți intenționat o eroare de compilare în ''​main.cpp''​ (exștergeți un '';''​),​ faceți push pe un branch separat și creați un Pull RequestObservați cum pipeline-ul blochează merge-ul.
-  ​[https://​docs.pytest.org/​en/​latest/​ PyTest Documentation] / [https://​jestjs.io Jest Documentation] / [https://​junit.org JUnit Documentation] ​  +
-  ​[https://​coverage.readthedocs.io Coverage.py] / [https://​istanbul.js.org Istanbul Code Coverage] / [https://​www.jacoco.org JaCoCo] ​  +
-  ​[https://​docs.sonarqube.org/latest/ SonarQube Documentation] / [https://about.codecov.io Codecov]  ​+
  
 +  - **Adăugați un job de test**: Creați un job nou în workflow care rulează un test simplu Python — de exemplu, verificați că ''​receiver.py''​ poate fi parsat fără erori de sintaxă:
  
 +<code yaml>
 +- name: Smoke test
 +  run: python -m py_compile receiver.py
 +</​code>​
  
 +  - **Release automat**: Adăugați un pas care creează un GitHub Release cu ''​firmware.bin''​ atașat, doar când se face push pe un tag (ex: ''​v1.0''​). Hint: folosiți ''​if:​ startsWith(github.ref,​ '​refs/​tags/'​)''​ și action-ul ''​softprops/​action-gh-release''​.
ss/laboratoare/04.1740521747.txt.gz · Last modified: 2025/02/26 00:15 by jan.vaduva
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0