This is an old revision of the document!


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

  1. Înțelegerea conceptelor de CI/CD și a avantajelor lor în proiecte embedded.
  2. Configurarea unui repository GitHub pentru proiect.
  3. Crearea unui workflow GitHub Actions care:
    • Compilează firmware-ul ESP32 automat la fiecare push.
    • Verifică codul Python cu linting și analiză de securitate.
    • Rulează analiza statică pe codul C++ al firmware-ului.
  4. 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ți “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 1: Pregătirea repository-ului de GitHub

1.1 Inițializare Git

Dacă proiectul nu este deja într-un repository git:

cd /path/to/proiect
git init

1.2 Crearea fișierului ''.gitignore''

Asigurați-vă că fișierul .gitignore generat de PlatformIO exclude fișierele generate și mediile virtuale:

# PlatformIO
.pio/

# Python
.venv/
__pycache__/
*.pyc

# IDE
.vscode/
.idea/

# OS
.DS_Store
Thumbs.db

1.3 Push pe GitHub

Creați un repository nou pe GitHub (fără README), apoi:

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

Înlocuiți UTILIZATOR cu username-ul vostru GitHub și NUMELE-REPO cu numele repository-ului creat.

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:

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

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 overflows, memory leaks, variabile neinițializate
check-python Rulează pylint + bandit pe receiver Probleme de stil, parole hardcodate, funcții nesigure
  push/PR
    │
    ├──► build-firmware ──► firmware.bin (artifact)
    │
    ├──► analyze-firmware ──► raport cppcheck
    │
    └──► check-python ──► raport pylint + bandit

Partea 3: Testarea pipeline-ului

3.1 Commit și push

git add .github/workflows/ci.yml
git commit -m "Add CI pipeline"
git push

3.2 Verificare pe GitHub

  1. Deschideți repository-ul pe GitHub.
  2. Navigați la tab-ul Actions.
  3. Ar trebui să vedeți workflow-ul ESP32-CAM CI Pipeline rulând.
  4. Faceți clic pe el pentru a vedea detaliile fiecărui job.

3.3 Descărcarea firmware-ului

Dacă build-ul reușește:

  1. Deschideți run-ul din Actions.
  2. La secțiunea Artifacts, veți vedea firmware-esp32cam.
  3. Descărcați-l — conține firmware.bin gata de upload pe dispozitiv.

După descărcare, puteți flash-ui direct pe ESP32-CAM folosind esptool fără a avea PlatformIO instalat:

pip install esptool
esptool.py --chip esp32 --port /dev/ttyUSB0 --baud 460800 write_flash 0x10000 firmware.bin

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ă.

Partea 4: Protejarea branch-ului ''main''

Pentru a preveni merge-ul codului care nu trece CI-ul:

  1. Pe GitHub: Settings → Rules → Rulesets → New ruleset → New branch ruleset.
  2. La Target branches adăugați branch-ul main.
  3. Activați Require status checks to pass și adăugați cele 3 job-uri: Build ESP32 Firmware, Static Analysis (C++), Python Lint & Security.
  4. Salvați ruleset-ul.

Interfața GitHub se poate schimba. Pe unele repository-uri mai vechi, opțiunea se găsește la Settings → Branches → Add rule.

De acum, nimeni nu poate face merge pe main dacă pipeline-ul eșuează.

Exerciții

  1. 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 Request. Observați cum pipeline-ul blochează merge-ul.
  1. 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ă:
- name: Smoke test
  run: python -m py_compile receiver.py
  1. 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.1774284625.txt.gz · Last modified: 2026/03/23 18:50 by ciprian.popescu0411
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