13 KiB
Analyse: Ubuntu-26.04-Build-Skripte
Analysierte Dateien
| Datei | Rolle |
|---|---|
jenkins-ci-rme/jenkins_builder_ubuntu26.sh |
Bash-Einstiegspunkt (Jenkins/Container) |
rpmbuild/make_rpm_ubuntu26.py |
Python-Builder, erzeugt das DEB-Paket |
Kontext: Beide Skripte sind die Ubuntu/DEB-Variante der ursprünglichen openSUSE/RPM-Pipeline
(jenkins_builder.sh + make_rpm.py) im Zuge der Qt6-Migration. Zielplattform ist Ubuntu 26.04
mit Qt 6.10.2 (via aqtinstall in /opt/Qt). Laut jenkins-ci-rme/README-ubuntu-docker.md ist die
Ubuntu-Infrastruktur „für zukünftige Ubuntu-Unterstützung vorbereitet" — sie ist also noch nicht
in die aktive Pipeline eingebunden (das jenkins-ci-rme/Jenkinsfile ruft weiterhin
jenkins/jenkins_builder.sh auf, nicht die _ubuntu26-Variante).
1. jenkins_builder_ubuntu26.sh
1.1 Zweck
Baut ein LTS-DEB-Paket für ein Projekt-Flavor (qatar | ahtc | guez) auf Ubuntu 26.04.
Es validiert die Umgebung, legt eine saubere Quell-Kopie an und delegiert die eigentliche
Paket-Erzeugung an make_rpm_ubuntu26.py.
1.2 Ablauf (Zeile für Zeile)
set -eo pipefail— strikte Fehlerbehandlung: Abbruch bei jedem Fehler, bei nicht-Null-Exit-Code und bei Fehlern in Pipelines. Gutes Fundament.- Umgebungs-Validierung via
: "${VAR:?...}"fürPROJECT,OS_VERSION,LTS_VERSION,GUEZ_MODE,WORKSPACE,PROJECT_BASE_DIR. Fehlt eine Variable, bricht das Skript sofort mit klarem Fehler ab.BUILD_NUMBER/BUILD_TAGsind optional. HOME=/home/builder+mkdir -p— setzt das Home-Verzeichnis (Kommentar: „running as root in container").- Quell-Staging:
rm -rf "${PROJECT_BASE_DIR}"und anschließendetar-Pipe (tar -cf - -C WORKSPACE . | tar -xf - -C PROJECT_BASE_DIR) kopiert den Workspace als saubere Kopie. Ausgeschlossen:./rpms,./.git,./build,./deb_build_tmp. VERSION_DATE=$(date +%Y-%m-%d)wird exportiert.- Aufruf des Python-Builder aus
${WORKSPACE}/rpmbuild:python3 make_rpm_ubuntu26.py -c LTS \ --project_name "${PROJECT}" \ --version "${LTS_VERSION}" \ --output_dir "${WORKSPACE}/rpms/${PROJECT}/${OS_VERSION}/" \ --cmake_build_flags "-DUSE_IPO=ON -DUSE_UNITY_BUILD=ON -DGUEZ_MODE=${GUEZ_MODE} \ -DBUILD_WLS=ON -DPostgreSQL_TYPE_INCLUDE_DIR=/usr/include/postgresql/" \ --build_number "${BUILD_NUMBER:-1}" ls -lhRdes Output-Verzeichnisses zur Bestätigung.
1.3 Stärken
- Strikte, frühzeitige Validierung aller Pflicht-Variablen.
pipefailmacht dietar-Pipe fehlersicher.- Output ist pro
Projekt/OS-Versionisoliert → parallele OS-Builds kollidieren nicht. - Saubere Quell-Kopie ohne
.git/build/rpms. python3stattpython(robuster als im Original).
1.4 Befunde / Probleme
| # | Schwere | Befund |
|---|---|---|
| S1 | Hoch | PROJECT_BASE_DIR wird nie verwendet. Die tar-Staging-Kopie nach PROJECT_BASE_DIR ist toter Code: make_rpm_ubuntu26.py berechnet source_dir selbst als Elternverzeichnis von rpmbuild/ (also WORKSPACE), nicht PROJECT_BASE_DIR. Die teure Kopie wird verworfen. |
| S2 | Mittel | VERSION_DATE wird exportiert, aber nirgends (auch nicht im Python-Skript) gelesen. |
| S3 | Mittel | BUILD_TAG wird im Header als „Required" dokumentiert, aber weder validiert noch an den Builder übergeben. |
| S4 | Mittel | HOME=/home/builder + Kommentar „running as root" widerspricht dem Dockerfile, das USER ctc mit Home /shd/CTC/TOOLS setzt. Inkonsistenz zwischen Skript und Image. |
| S5 | Niedrig | rm -rf "${PROJECT_BASE_DIR}" ist durch die :?-Prüfung abgesichert, aber ein rm -rf auf einer Umgebungsvariable bleibt ein Risiko, falls die Validierung je entfernt wird. |
2. make_rpm_ubuntu26.py
2.1 Zweck
Erzeugt ein DEB-Paket für Ubuntu 26.04, indem es eine debian/-Verzeichnisstruktur
(control, changelog, rules, source/format, compat) generiert und debuild ausführt.
Migriert von make_rpm.py (RPM).
2.2 Struktur & Funktionen
| Funktion | Zweck |
|---|---|
verbose() / debug() / info() / warning() / error() / die() |
Logging, gesteuert durch EMERGE_VERBOSE |
system(cmdstring, file) |
Shell-Ausführung via subprocess.Popen (stdout-Capture) |
get_os_name() |
Liest PRETTY_NAME aus /etc/os-release |
remove_directory(dest_dir) |
shutil.rmtree |
copy_src_dir_to_dest_dir(...) |
Rekursive Quell-Kopie mit optionalen Permissions |
create_debian_control(...) |
Generiert debian/control |
create_debian_changelog(...) |
Generiert debian/changelog |
create_debian_rules(...) |
Generiert debian/rules (chmod +x) |
build_deb(...) |
Orchestrierung: Temp-Dir, Quell-Kopie, debian/, debuild, Move, Cleanup |
main() |
argparse, bestimmt source_dir, ruft build_deb auf |
2.3 Ablauf build_deb()
output_diranlegen.deb_build_tmpuntersource_diranlegen (vorher entfernen).- Quelle nach
deb_build_tmp/legatus-<projekt>-<version>kopieren. debian/mitcontrol,changelog,rules,source/format(3.0 (quilt)),compat(13) befüllen.os.chdir(pkg_dir),DEB_BUILD_OPTIONSsetzen,debuild -us -uc -bausführen.- Erzeugte Artefakte (
.deb,.dsc,.changes,.buildinfo) nachoutput_dirverschieben. - Cleanup:
chdirzurück,deb_build_tmpentfernen.
2.4 Stärken
- Klare, modulare Struktur mit getrennten
create_debian_*-Helfern. - Konsistentes Logging mit
die()bei Fehlern. debuild -us -uc -b(unsigned, binary-only) — passend für CI ohne Signatur.- Sauberes Cleanup des Temp-Build-Verzeichnisses.
subprocess.runmit Return-Code-Check fürdebuild.
2.5 Befunde / Probleme
Kritisch (Build würde fehlschlagen / falsches Ergebnis)
| # | Schwere | Befund |
|---|---|---|
| P1 | Kritisch | debuild/debhelper/dpkg-dev sind im Dockerfile nicht installiert. Das Image installiert rpm, aber kein debhelper, debuild oder dpkg-dev. Der Aufruf debuild -us -uc -b schlägt mit „command not found" fehl. |
| P2 | Kritisch | CMake-Flags werden nie in den Build übergeben. --cmake_build_flags landet ausschließlich im Description-Text von debian/control. Die generierte debian/rules hardcodet nur -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr. Damit greifen USE_IPO, USE_UNITY_BUILD, GUEZ_MODE, BUILD_WLS, PostgreSQL_TYPE_INCLUDE_DIR nicht — das Paket wird mit falschen Build-Optionen gebaut. |
| P3 | Kritisch | Kein CMakeLists.txt im Quell-Root. source_dir ist der Repo-Root (Eltern von rpmbuild/), dort liegt aber kein CMakeLists.txt (das echte Projekt-Root ist qt-migration-legatus/qt6-after/qt6-migrated-legatus/). dh --buildsystem=cmake würde im konfigurierten Build-Verzeichnis scheitern. |
| P4 | Kritisch | DEB_BUILD_OPTIONS="parallel=$(nproc)" — es findet keine Shell-Expansion statt; debhelper erwartet eine Zahl (parallel=N). Der wörtliche String $(nproc) ist ungültig und führt zu einem Fehler bzw. wird ignoriert. |
Mittel
| # | Schwere | Befund |
|---|---|---|
| P5 | Mittel | --config wird verlangt, aber weder validiert noch genutzt. Es wird keine Config-Datei gelesen; der Wert wird nur geloggt. Im Original (make_rpm.py) hatte -c eine Bedeutung. |
| P6 | Mittel | Changelog-Timestamp inkonsistent: datetime.now() (lokale Zeit) mit hartkodiertem +0000. Ist die Container-TZ nicht UTC, ist der Zeitstempel falsch. |
| P7 | Mittel | Build-Depends in control passt nicht zum Image: qt6-base-dev/libgeographic-dev werden gelistet, das Image nutzt aber Qt aus /opt/Qt (aqtinstall) und libgeographiclib-dev. Misstreibend (bei -b-Build nicht für Dependency-Resolution relevant, aber irreführend). |
| P8 | Mittel | project_name wird nicht validiert (gegen `qatar |
| P9 | Mittel | Vollständige Repo-Kopie (inkl. external/ mit ArcGIS-SDK & RTI Connext, jenkins/, rpmbuild/) nach deb_build_tmp — sehr langsam und speicherintensiv. |
Niedrig / Code-Qualität
| # | Schwere | Befund |
|---|---|---|
| P10 | Niedrig | Unbenutzte Imports: configparser, getpass, re, pathlib.Path. |
| P11 | Niedrig | Unbenutzte Funktionen: system(), get_os_name(), warning(). |
| P12 | Niedrig | „emerge"-Namensreste aus dem RPM-Skript: EMERGE_VERBOSE, Fehlermeldung „emerge fatal error". |
| P13 | Niedrig | Dateiname make_rpm_ubuntu26.py baut ein DEB, kein RPM — irreführend. |
| P14 | Niedrig | debian/compat-Datei ist deprecated (debhelper ≥ 12); 13 ist überflüssig. |
| P15 | Niedrig | control-Description-Fortsetzungszeilen mit 3 statt 1 Leerzeichen eingerückt; fehlt Standards-Version/Homepage (Lintian-Warnungen). |
| P16 | Niedrig | copy_src_dir_to_dest_dir: os.path.isfile(tmpdir) prüft einen Verzeichnis-Pfad (Restcode); die perm-Logik prüft os.path.isdir(f) auf eine gerade kopierte Datei (immer False). |
| P17 | Niedrig | os.makedirs(tmpdir) ohne exist_ok nach exists-Check (Race, gering). |
| P18 | Niedrig | override_dh_auto_install: dh_auto_install ist ein no-op-Override (ohne Effekt). |
| P19 | Niedrig | .dsc/.changes werden zum Move geprüft, entstehen bei -b aber nicht (harmlos). |
| P20 | Niedrig | os.chdir(pkg_dir) ändert den Prozess-CWD; bei debuild-Fehler wird er nicht wiederhergestellt (Prozess beendet sich aber ohnehin). |
3. Zusammenspiel der beiden Skripte
Jenkins/Container
└─ jenkins_builder_ubuntu26.sh
├─ validiert ENV (PROJECT, OS_VERSION, LTS_VERSION, GUEZ_MODE, WORKSPACE, PROJECT_BASE_DIR)
├─ tar-Staging → PROJECT_BASE_DIR (⚠ toter Code, s. S1)
└─ python3 make_rpm_ubuntu26.py
├─ source_dir = Eltern(rpmbuild/) = WORKSPACE (⚠ ≠ PROJECT_BASE_DIR)
├─ kopiert WORKSPACE → deb_build_tmp/legatus-<proj>-<ver>
├─ generiert debian/{control,changelog,rules,source/format,compat}
├─ debuild -us -uc -b (⚠ debuild fehlt im Image, s. P1)
└─ .deb → WORKSPACE/rpms/<proj>/<os>/
Kernproblem des Zusammenspiels: Das Shell-Skript investiert in eine Staging-Kopie nach
PROJECT_BASE_DIR, die der Python-Builder ignoriert (P3/S1). Gleichzeitig erreicht der
Python-Builder die CMake-Flags nicht (P2) und baut aus einem Root ohne CMakeLists.txt (P3).
Die Pipeline ist daher in ihrem aktuellen Zustand nicht funktionsfähig.
4. Zusammenfassung der Befunde (nach Schwere)
| Schwere | Anzahl | IDs |
|---|---|---|
| 🔴 Kritisch | 4 | P1, P2, P3, P4 |
| 🟠 Hoch | 1 | S1 |
| 🟡 Mittel | 7 | S2, S3, S4, P5, P6, P7, P8, P9 |
| ⚪ Niedrig | 11 | P10–P20 |
Hinweis: S2–S4 sind im Shell-Skript als „Mittel" eingestuft; P5–P9 im Python-Skript.
5. Empfehlungen (Priorität)
- P1:
debhelper,dpkg-dev(bietetdebuild) in das Dockerfile aufnehmen (apt-get install -y debhelper dpkg-dev). - P2:
--cmake_build_flagsin die generiertedebian/ruleseinbetten, z. B.(Flags sicher als Make-Variablen/Zeile injizieren).override_dh_auto_configure: dh_auto_configure -- -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr <FLAGS> - P3:
source_dirauf das echte CMake-Projekt-Root zeigen lassen (Parameter--source_diroderPROJECT_BASE_DIRtatsächlich nutzen) — und damit S1 auflösen, indem das Shell-SkriptPROJECT_BASE_DIRan den Builder übergibt. - P4:
DEB_BUILD_OPTIONS="parallel=$(nproc)"durch eine echte Zahl ersetzen, z. B.env["DEB_BUILD_OPTIONS"] = f"parallel={os.cpu_count()}". - S1/S2/S3: Toten Code entfernen (
PROJECT_BASE_DIR-Staging,VERSION_DATE,BUILD_TAG-Doku) oder die Variablen tatsächlich nutzen. - P5:
--configvalidieren (z. B.choices=["LTS"]) oder entfernen. - P6: Changelog-Timestamp mit
datetime.now(timezone.utc)erzeugen. - P7:
Build-Dependsan das tatsächliche Image anpassen (Qt aus/opt/Qt,libgeographiclib-dev). - P9: Quell-Kopie auf das eigentliche Projekt-Root beschränken (statt ganzes Repo
inkl.
external/). - P10–P20: Code-Qualität aufräumen (unbenutzte Imports/Funktionen, „emerge"-Reste,
Dateiname,
compat-Datei,control-Formatierung,copy_src_dir_to_dest_dir-Logik).
Erstellt am 2026-10-08. Analyse basiert auf jenkins-ci-rme/jenkins_builder_ubuntu26.sh,
rpmbuild/make_rpm_ubuntu26.py sowie Kontext aus jenkins-ci-rme/Jenkinsfile,
jenkins-ci-rme/Dockerfile-ubuntu26-qt6.dockerfile, jenkins-ci-rme/jenkins_builder.sh
(Original) und der Repository-Struktur.