commit 2b195eacb30226bccb603c8ff50636873f61a630 Author: twi-devel Date: Tue Aug 18 21:17:51 2026 +0200 Repo setup first commit diff --git a/Dockerfile-15.1.dockerfile b/Dockerfile-15.1.dockerfile new file mode 100755 index 0000000..28ce9c7 --- /dev/null +++ b/Dockerfile-15.1.dockerfile @@ -0,0 +1,88 @@ +# DOCKERFILE SPEC FOR BUILD Container +# +# FOLLOWING ARG NEEDED FROM JENKINSFILE +# ARG BASE_IMG_VERSION +# ARG ADMINSRV +# ARG PROJECT + + +ARG BASE_URL=harbor.sl.defence-elec.de +ARG BASE_IMG=opensuse/leap +ARG BASE_IMG_VERSION=15.1 + +FROM ${BASE_URL}/${BASE_IMG}:${BASE_IMG_VERSION} + +ARG BASE_IMG_VERSION +ARG USERPASS=ctc +ARG ADMINSRV=10.198.80.75 +ARG PROJECT=guez + +ENV ADMINSRV_ENV=${ADMINSRV} +ENV REPOVERSION_ENV=${BASE_IMG_VERSION} +ENV PROJECT_ENV=${PROJECT} + +LABEL Author='Thore Poggenburg' +LABEL PROJECT=${PROJECT} +LABEL OS_VERSION=${BASE_IMG_VERSION} + +RUN groupadd ctc -g 1445\ + && groupadd rme -g 1000\ + && useradd -d /shd/CTC/TOOLS -u 1445 -g ctc -m -p $(openssl passwd -crypt ${USERPASS}) ctc \ + && useradd -d /home/rme -u 1000 -g rme -m -p $(openssl passwd -crypt ${USERPASS}) rme + +RUN zypper rr 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20\ + && zypper --non-interactive ar --no-gpgcheck http://${ADMINSRV_ENV}/opensuse/${REPOVERSION_ENV}/distribution/leap/${REPOVERSION_ENV}/repo/oss/ OSS \ + && zypper --non-interactive ar --no-gpgcheck http://${ADMINSRV_ENV}/opensuse/${REPOVERSION_ENV}/distribution/leap/${REPOVERSION_ENV}/repo/non-oss NOSS \ + && zypper --non-interactive ar --no-gpgcheck http://${ADMINSRV_ENV}/opensuse/${REPOVERSION_ENV}/update/leap/${REPOVERSION_ENV}/oss/ UOSS \ + && zypper --non-interactive ar --no-gpgcheck http://${ADMINSRV_ENV}/opensuse/${REPOVERSION_ENV}/update/leap/${REPOVERSION_ENV}/non-oss/ UNOSS \ + && zypper --non-interactive ar --no-gpgcheck http://${ADMINSRV_ENV}/opensuse/${REPOVERSION_ENV}/repositories/KDE:/Qt5/openSUSE_Leap_${REPOVERSION_ENV}/ KDE_QT5 \ + && zypper --non-interactive ar --no-gpgcheck http://${ADMINSRV_ENV}/opensuse/${REPOVERSION_ENV}/repositories/KDE:/Frameworks5/openSUSE_Leap_${REPOVERSION_ENV}/ KDE_Frameworks5 \ + && zypper --non-interactive ar --no-gpgcheck http://${ADMINSRV_ENV}/opensuse/${REPOVERSION_ENV}/repositories/KDE:/Applications/KDE_Frameworks5_openSUSE_Leap_${REPOVERSION_ENV}/ KDE_Applications \ +# && zypper --non-interactive ar --no-gpgcheck http://${ADMINSRV_ENV}/opensuse/${REPOVERSION_ENV}/update/leap/${REPOVERSION_ENV}/sle SLE-UPDATE \ + && zypper --non-interactive ar --no-gpgcheck http://${ADMINSRV_ENV}/opensuse/${REPOVERSION_ENV}/repositories/server:/database:/postgresql/openSUSE_Leap_${REPOVERSION_ENV}/ postgresql \ + && zypper --non-interactive refresh + +RUN zypper dup -ly --allow-name-change --allow-arch-change --allow-vendor-change \ + && zypper --non-interactive removerepo $(zypper ls | grep repo-backports-debug-update | awk '{ print $1 }') \ + && zypper --non-interactive removerepo $(zypper ls | grep repo-backports-update | awk '{ print $1 }') \ + && zypper --non-interactive removerepo $(zypper ls | grep repo-sle-debug-update | awk '{ print $1 }') \ + && zypper --non-interactive removerepo $(zypper ls | grep repo-sle-update | awk '{ print $1 }') + +RUN zypper --non-interactive update -ly --recommends \ + && zypper --non-interactive install -ly openssl curl wget subversion git vim nano python-xml xls2csv bc\ + && zypper --non-interactive install -ly postgresql postgresql-devel libbotan-devel \ + && zypper --non-interactive install -ly json-glib-lang libjson-c* libjson-glib-1_0-0 \ + && zypper --non-interactive install -ly libpopt0 popt popt-devel libpopt0-32bit \ + && zypper --non-interactive install -ly rpm-build python-rpm-macros python3-rpm systemd-rpm-macros \ + && zypper --non-interactive install -ly kernel-devel kernel-firmware-all kernel-default kernel-source patterns-devel-base-devel_kernel kernel-default-devel libjpeg62-devel alsa-devel libpulse-devel \ + && zypper --non-interactive install -ly libevdev2 libdmtx-devel kexec-tools tcl-devel gcc-c++ gdal-devel gsoap-devel libpoppler-devel java-1_8_0-openjdk \ + && zypper --non-interactive install -ly postgresql14 postgresql14-devel libbotan-2-18 python-rpm-generators gtest libOpenSceneGraph131 libOpenSceneGraph131-devel + +RUN zypper dup -ly --allow-name-change --allow-arch-change --allow-vendor-change + +RUN curl http://${ADMINSRV_ENV}/rme/rde_package_signing_key.pub --output /rde_package_signing_key.pub \ + && rpm --import /rde_package_signing_key.pub \ + && rm -rf /rde_package_signing_key.pub \ + && zypper --non-interactive ar http://${ADMINSRV_ENV}/rme/repository/${PROJECT_ENV}/15.0/ RME_15.0 + +RUN zypper --non-interactive refresh \ + && zypper --non-interactive install -ly --allow-downgrade --allow-vendor-change ctc_devel_tds_qt5 qt5-kdreports-devel tao-devel + + +RUN if [[ ${PROJECT_ENV} = guez ]]; \ + then zypper --non-interactive install -ly NGS NGS-devel NGS_guez_fom NGS_guez_fom-devel NGS_rtifacade_mak450 liblog4cplus-1_2-5 ${PROJECT_ENV}_dependencies ${PROJECT_ENV}_situation_map-devel ; \ + elif [[ ${PROJECT_ENV} = ahtc ]]; \ + then zypper --non-interactive install -ly ctc_maia-devel NGS NGS-devel NGS_apache_fom-devel ace-devel ace-xml-devel ${PROJECT_ENV}_dependencies ${PROJECT_ENV}_situation_map-devel; \ + elif [[ ${PROJECT_ENV} = qatar ]]; \ + then zypper --non-interactive install -ly nano ; \ + elif [[ ${PROJECT_ENV} = l400p2]]; \ + then zypper --non-interactive install -ly ${PROJECT_ENV}_situation_map-devel nano; \ + elif [[ ${PROJECT_ENV} = l400]]; \ + then zypper --non-interactive install -ly ${PROJECT_ENV}_situation_map-devel nano; \ + else echo "No specific pakets found for project name: ${PROJECT_ENV}"; \ + fi + +USER ctc +WORKDIR /shd/CTC/TOOLS + +CMD ["/bin/bash"] diff --git a/Dockerfile-ubuntu26-qt6.dockerfile b/Dockerfile-ubuntu26-qt6.dockerfile new file mode 100644 index 0000000..a5aa57f --- /dev/null +++ b/Dockerfile-ubuntu26-qt6.dockerfile @@ -0,0 +1,152 @@ +# DOCKERFILE SPEC FOR BUILD Container with Qt6 +# Based on Ubuntu 26.04 with aqtinstall for Qt6 installation + +FROM ubuntu:26.04 + +ARG USERPASS=ctc +ARG ADMINSRV=10.198.80.75 +ARG PROJECT=guez +ARG REPOVERSION=26.04 +ARG QT_VERSION=6.8.3 +ARG QT_ARCH=linux_gcc_64 +ARG QT_BASE_DIR=/opt/Qt +ARG QT_ROOT=/opt/Qt/6.8.3/gcc_64 + +ENV DEBIAN_FRONTEND=noninteractive \ + PYTHONUNBUFFERED=1 \ + PIP_NO_CACHE_DIR=1 \ + LANG=C.UTF-8 \ + LC_ALL=C.UTF-8 \ + QT_VERSION=${QT_VERSION} \ + QT_ARCH=${QT_ARCH} \ + QT_BASE_DIR=${QT_BASE_DIR} \ + QT_ROOT=${QT_ROOT} \ + Qt6_ROOT=${QT_ROOT} \ + CMAKE_PREFIX_PATH=/usr/local:${QT_ROOT} \ + LD_LIBRARY_PATH=${QT_ROOT}/lib \ + PATH=${QT_ROOT}/bin:$PATH \ + ADMINSRV_ENV=${ADMINSRV} \ + PROJECT_ENV=${PROJECT} \ + REPOVERSION_ENV=${REPOVERSION} + +LABEL Author='Thore Poggenburg (updated for Qt6 on Ubuntu 26.04)' +LABEL PROJECT=${PROJECT} +LABEL OS_VERSION=${REPOVERSION} + +SHELL ["/bin/bash", "-o", "pipefail", "-c"] + +# Create users (install openssl first for password hashing) +RUN apt-get update && apt-get install -y openssl \ + && groupadd ctc -g 1445 || true \ + && groupadd rme -g 1001 || true \ + && useradd -d /shd/CTC/TOOLS -u 1445 -g ctc -m -p $(openssl passwd -5 ${USERPASS}) ctc || true \ + && useradd -d /home/rme -u 1001 -g rme -m -p $(openssl passwd -5 ${USERPASS}) rme || true \ + && rm -rf /var/lib/apt/lists/* + +WORKDIR /app + +# Install base development tools and Qt6 dependencies +RUN apt-get update \ + && apt-get install -y --no-install-recommends \ + ca-certificates \ + sudo \ + git \ + cmake \ + ninja-build \ + clang \ + build-essential \ + gnupg \ + curl \ + jq \ + openssh-client \ + pkg-config \ + libgl1-mesa-dev \ + libxkbcommon-x11-0 \ + libfontconfig1 \ + libdbus-1-3 \ + libpulse0 \ + libxcb-glx0 \ + libxcb-cursor0 \ + libpq-dev \ + libbz2-dev \ + libpoppler-dev \ + libpoppler-qt6-dev \ + libboost-dev \ + libgeographiclib-dev \ + libssl-dev \ + libxml2-dev \ + libicu-dev \ + libqt6svg6-dev \ + unzip \ + python3 \ + python3-venv \ + python3-pip \ + && ln -sf /usr/bin/python3 /usr/local/bin/python3 \ + && ln -sf /usr/bin/python3 /usr/local/bin/python \ + && rm -rf /var/lib/apt/lists/* + +# Setup Python virtual environment and install aqtinstall +RUN python3 -m venv /opt/venv \ + && /opt/venv/bin/pip install --upgrade pip setuptools wheel \ + && /opt/venv/bin/pip install aqtinstall + +# Install Qt6 via aqtinstall with required modules +RUN set -eux; \ + mkdir -p "${QT_BASE_DIR}" \ + && /opt/venv/bin/python -m aqt install-qt linux desktop "${QT_VERSION}" "${QT_ARCH}" \ + -m qtmultimedia qtserialport qtimageformats qtwebsockets qtpdf qtwebview \ + --outputdir "${QT_BASE_DIR}" \ + && test -f "${QT_ROOT}/lib/cmake/Qt6/Qt6Config.cmake" + +# Build and install Log4Qt from source (Qt6 support) +RUN set -eux; \ + cd /tmp && \ + git clone --depth 1 --branch v2.0.0 https://github.com/MEONMedical/Log4Qt.git && \ + cd Log4Qt && \ + mkdir build && cd build && \ + cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr/local -DCMAKE_PREFIX_PATH="${QT_ROOT}" .. && \ + cmake --build . -j$(nproc) && \ + cmake --install . && \ + cd /tmp && rm -rf Log4Qt + +# Build and install Grantlee from source (Qt6 support) +# Note: Ubuntu grantlee5-devel is Qt5-based, so we build Qt6-compatible version from master branch +RUN set -eux; \ + cd /tmp && \ + git clone --depth 1 https://github.com/steveire/grantlee.git && \ + cd grantlee && \ + mkdir build && cd build && \ + cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr/local -DCMAKE_PREFIX_PATH="${QT_ROOT}" -DGRANTLEE_BUILD_WITH_QT6=ON .. && \ + cmake --build . -j$(nproc) && \ + cmake --install . && \ + cd /tmp && rm -rf grantlee + +# Build and install KDReports from source (Qt6 support) +RUN set -eux; \ + cd /tmp && \ + git clone --depth 1 --branch kdreports-2.3.0 https://github.com/KDAB/KDReports.git && \ + cd KDReports && \ + mkdir build && cd build && \ + cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr/local -DCMAKE_PREFIX_PATH="${QT_ROOT}" -DKDReports_QT6=ON .. && \ + cmake --build . -j$(nproc) && \ + cmake --install . && \ + cd /tmp && rm -rf KDReports + +# Install GoogleTest +RUN apt-get update \ + && apt-get install -y --no-install-recommends libgtest-dev libgmock-dev \ + && rm -rf /var/lib/apt/lists/* + +# Add RPM/rpmbuild tools for make_rpm.py +RUN apt-get update \ + && apt-get install -y --no-install-recommends rpm rpm-build rpmdevtools \ + && rm -rf /var/lib/apt/lists/* + +# Cleanup +RUN apt-get clean \ + && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* + +USER ctc +WORKDIR /shd/CTC/TOOLS + +CMD ["/bin/bash"] \ No newline at end of file diff --git a/Dockerfile-ubuntu26.04.dockerfile b/Dockerfile-ubuntu26.04.dockerfile new file mode 100644 index 0000000..db67b97 --- /dev/null +++ b/Dockerfile-ubuntu26.04.dockerfile @@ -0,0 +1,88 @@ +FROM ubuntu:24.04 + +LABEL maintainer="legatus-team" +LABEL description="Ubuntu 24.04 build environment for Legatus LTS DEB builds" + +# Prevent interactive prompts during package installation +ENV DEBIAN_FRONTEND=noninteractive +ENV TZ=Europe/Berlin + +# Install base build dependencies +RUN apt-get update && apt-get install -y --no-install-recommends \ + build-essential \ + cmake \ + ninja-build \ + git \ + curl \ + wget \ + python3 \ + python3-pip \ + python3-setuptools \ + libgl1-mesa-dev \ + libglu1-mesa-dev \ + libxcb-cursor0 \ + libxcb-icccm4 \ + libxcb-image0 \ + libxcb-keysyms1 \ + libxcb-randr0 \ + libxcb-render-util0 \ + libxcb-shape0 \ + libxcb-xfixes0 \ + libxcb-xinerama0 \ + libxcb-xkb1 \ + libxkbcommon-x11-0 \ + libdbus-1-3 \ + libfontconfig1 \ + libfreetype6 \ + libharfbuzz0b \ + ca-certificates \ + gnupg \ + lsb-release \ + software-properties-common \ + pkg-config \ + libudev-dev \ + && rm -rf /var/lib/apt/lists/* + +# Install Qt6 from host mount or pre-installed location +# Qt6 is NOT installed in this image due to licensing/download requirements +# Mount Qt6 installation at runtime: +# docker run -v /opt/Qt:/opt/Qt -e CMAKE_PREFIX_PATH=/opt/Qt/6.8.2/gcc_64/lib/cmake ... +# See README-ubuntu-docker.md for installation options + +# Install additional development libraries (common dependencies) +RUN apt-get update && apt-get install -y --no-install-recommends \ + libboost-all-dev \ + libjson-glib-dev \ + libgeographic-dev \ + libpq-dev \ + libssl-dev \ + libcurl4-openssl-dev \ + libxml2-dev \ + libxslt1-dev \ + zlib1g-dev \ + libbz2-dev \ + liblzma-dev \ + libzstd-dev \ + && rm -rf /var/lib/apt/lists/* + +# Install clang-tidy and LLVM tools for code quality checks +RUN apt-get update && apt-get install -y --no-install-recommends \ + clang-tidy \ + clang-format \ + clang-tools \ + llvm \ + && rm -rf /var/lib/apt/lists/* + +# Set up rpmbuild directory structure (for compatibility with existing scripts) +RUN mkdir -p /home/builder/rpmbuild/{BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS} && \ + echo "%_topdir /home/builder/rpmbuild" > /home/builder/.rpmmacros + +# Create non-root builder user +RUN useradd -m -u 1000 builder && \ + chown -R builder:builder /home/builder + +# Set working directory +WORKDIR /workspace + +# Default command +CMD ["/bin/bash"] \ No newline at end of file diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100755 index 0000000..656d3a3 --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,152 @@ +def projects = ['ahtc', 'guez'] + +// Maps OsVersion -> BUILD_VERSION env var consumed by rpmbuild/make_rpm.py +// (the script looks for lts${BUILD_VERSION}.spec; empty selects specs/lts.spec). +// Ubuntu 26.04 is the target platform for Qt6 migration +def spec_suffix_for_os = [ + '26.04': '26.04' +] + +def choice_projects = ['ALL'] + projects +properties([ + disableConcurrentBuilds(), + parameters([ + choice(name: 'ProjectName', choices: choice_projects, description: 'LTS project flavor (passed as cmake -D_pname)'), + string(name: 'OsVersions', defaultValue: '26.04', description: 'Comma-separated Ubuntu base versions, all built in parallel (selects build container tag and spec variant)'), + string(name: 'LtsVersion', defaultValue: '1.0', description: 'LTS version (major.minor) passed to make_rpm.py --version'), + booleanParam(name: 'ClearWorkspace', defaultValue: false, description: 'Clear entire workspace on all nodes used for build'), + booleanParam(name: 'PublishArtifactRepo', defaultValue: true, description: 'Upload produced RPMs to the internal artifact repository') + ]) +]) + +env.GIT_TERMINAL_PROMPT = "0" +env.LTS_VERSION = "${params.LtsVersion}" +env.BUILD_CONTAINER_REGISTRY = "harbor.sl.defence-elec.de" +env.BUILD_CONTAINER_PREFIX = "buildcontainer" +env.ARTIFACTREPO = "https://internal-repo.sl.defence-elec.de" +env.BITBUCKET_URL = "https://devhub.defence-elec.de/bitbucket" + +// Posts the build status to Bitbucket via jenkins/jenkins_notifier.sh (REST +// build-status API). A notification failure must never break the build itself. +def notifyBitbucketStatus(String state) { + try { + withCredentials([usernamePassword(credentialsId: 'bitbucket-notifier', + usernameVariable: 'CURL_USER', + passwordVariable: 'CURL_PASS')]) { + sh """ + export CURL_CRED="\${CURL_USER}:\${CURL_PASS}" + export BUILD_STATE='${state}' + bash jenkins/jenkins_notifier.sh + """ + } + } catch (e) { + echo "WARNING: Bitbucket notification (${state}) failed: ${e.message}" + } +} + +// OS versions this build covers; every (project, osVersion) pair runs in parallel. +def osVersions = params.OsVersions.split(',').collect { it.trim() }.findAll { it } + +if (params.ProjectName != 'ALL') { + projects = [params.ProjectName] +} + + +// One parallel branch per (project, osVersion) combination. Outputs are isolated +// under rpms/${project}/${osVersion} so concurrent OS builds never collide. +def builds = [:] +projects.each { project -> + osVersions.each { osVersion -> + def buildVersion = spec_suffix_for_os.containsKey(osVersion) ? spec_suffix_for_os[osVersion] : osVersion + def rpmsDir = "rpms/${project}/${osVersion}" + + builds["${project} (${osVersion})"] = { + stage("Prepare ${project} (${osVersion})") { + sh "rm -rf ${rpmsDir}" + sh "mkdir -p ${rpmsDir}" + } + + stage("Build RPM ${project} (${osVersion})") { + def imageName = "${BUILD_CONTAINER_REGISTRY}/${BUILD_CONTAINER_PREFIX}/${project}_${osVersion}" + def buildContainer = docker.image("${imageName}") + def guezMode = (project == 'guez') ? 'ON' : 'OFF' + + def dockerOpts = "--init --shm-size=2g" + + " -e HOME=/shd/CTC/TOOLS" + + " -e PROJECT_BASE_DIR=/tmp/legatus" + + " -e PROJECT=${project}" + + " -e OS_VERSION=${osVersion}" + + " -e LTS_VERSION=${LTS_VERSION}" + + " -e GUEZ_MODE=${guezMode}" + + " -e BUILD_VERSION=${buildVersion}" + + " -e BUILD_NUMBER=${env.BUILD_NUMBER}" + + " -e BUILD_TAG=${env.BUILD_TAG}" + + buildContainer.inside(dockerOpts) { + sh "bash jenkins/jenkins_builder.sh" + } + } + + stage("Publish ${project} (${osVersion})") { + if (params.PublishArtifactRepo) { + withCredentials([usernamePassword(credentialsId: 'internal-repo-uploader', + usernameVariable: 'CURL_USER', + passwordVariable: 'CURL_PASS')]) { + sh """ + export CURL_CRED="\${CURL_USER}:\${CURL_PASS}" + export PROJECT='${project}' + export OS_VERSION='${osVersion}' + export LTS_VERSION='${LTS_VERSION}' + export BUILD_NUMBER='${env.BUILD_NUMBER}' + export ARTIFACTREPO='${env.ARTIFACTREPO}' + export ARTIFACTFOLDER='${project}' + bash jenkins/jenkins_publisher.sh + """ + } + + def tdsUrl = readFile("url-${project}-${osVersion}.txt").trim() + def tdsVersion = readFile("tdsversion-${project}-${osVersion}.txt").trim() + def link = """${project} ${tdsVersion} (OS ${osVersion})""" + currentBuild.description = currentBuild.description ? "${currentBuild.description}
${link}" : link + } else { + echo "Artifact-repo publish skipped for ${project} (OS ${osVersion}, PublishArtifactRepo=false)" + } + } + + stage("Cleanup ${project} (${osVersion})") { + sh "rm -rf ${rpmsDir}" + } + } + } +} + +notifyBitbucketStatus('INPROGRESS') + +try { + stage("Initialization") { + if (params.ClearWorkspace) { + cleanWs() + checkout([ + $class: 'GitSCM', + branches: scm.branches, + doGenerateSubmoduleConfigurations: false, + extensions: [[$class: 'SubmoduleOption', disableSubmodules: false, parentCredentials: true, recursiveSubmodules: true, reference: '', trackingSubmodules: false]], + userRemoteConfigs: scm.userRemoteConfigs + ]) + } + echo "Legatus build initialized — branch '${env.BRANCH_NAME}', project(s): ${projects.join(', ')}, LTS ${env.LTS_VERSION}, OS version(s) (parallel): ${osVersions.join(', ')}" + } + + parallel builds + + stage("Finalization") { + echo "Legatus build completed — branch '${env.BRANCH_NAME}', project(s): ${projects.join(', ')} (LTS ${env.LTS_VERSION}), OS version(s): ${osVersions.join(', ')}" + } + + currentBuild.result = 'SUCCESS' +} catch (e) { + currentBuild.result = 'FAILURE' + throw e +} finally { + notifyBitbucketStatus(currentBuild.result == 'SUCCESS' ? 'SUCCESSFUL' : 'FAILED') +} diff --git a/README-ubuntu-docker.md b/README-ubuntu-docker.md new file mode 100644 index 0000000..bb02378 --- /dev/null +++ b/README-ubuntu-docker.md @@ -0,0 +1,96 @@ +# Ubuntu 24.04/26.04 Docker Build Environment for Legatus LTS + +## ⚠️ Wichtiger Hinweis (2026-08-18) + +**Ubuntu 24.04 und 26.04 haben KEINE Qt6-Pakete in den Standard-Repositories.** + +Nach umfassender Untersuchung: +- `apt-cache search qt6` liefert 0 Ergebnisse auf Ubuntu 24.04/26.04 +- beinerji/opt-qt-6.8.2-noble PPA ist unzuverlässig/defekt +- Qt.io bietet keine einfachen tar.xz-Downloads für CI-Automatisierung + +**Empfohlene Lösung für CI**: Verwende **openSUSE Leap 15.5** mit KDE:Qt6 Repository (siehe `Dockerfile-opensuse-qt6.dockerfile`). + +Die Ubuntu-Infrastruktur (`Dockerfile-ubuntu26.04.dockerfile`, `jenkins_builder_ubuntu26.sh`, `make_rpm_ubuntu26.py`) ist für zukünftige Ubuntu-Unterstützung vorbereitet. + +--- + +## Qt6 Installation Options + +Ubuntu 24.04 hat keine Qt6-Pakete in den Standard-Repos. Es gibt drei Optionen: + +### Option 1: Qt von Host mounten (Empfohlen für lokale Entwicklung) + +```bash +# Qt6 auf Host installieren (z.B. unter /opt/Qt) +# Dann Docker mit mount starten: +docker run --rm -v $(pwd):/repo -v /opt/Qt:/opt/Qt \ + -e CMAKE_PREFIX_PATH=/opt/Qt/6.8.2/gcc_64/lib/cmake \ + -e PATH=/opt/Qt/6.8.2/gcc_64/bin:$PATH \ + legatus-ubuntu24.04:latest +``` + +### Option 2: Qt Offline Installer im Dockerfile + +```dockerfile +# Qt Account Credentials als Build-Args +ARG QT_USERNAME +ARG QT_PASSWORD + +# Installer herunterladen und im silent mode installieren +RUN wget -q https://download.qt.io/official_releases/online_installers/qt-unified-linux-x64-online.run && \ + chmod +x qt-unified-linux-x64-online.run && \ + echo "[Defaults]" > qt.conf && \ + echo "CredentialsId=QtAccount" >> qt.conf && \ + ./qt-unified-linux-x64-online.run --script qt-installer.qs && \ + rm qt-unified-linux-x64-online.run qt.conf +``` + +### Option 3: Pre-built Docker Image verwenden + +Ein separates Docker-Image mit vorinstalliertem Qt6 verwenden: +```bash +docker pull /legatus-qt6-ubuntu24.04:latest +``` + +### Option 4: openSUSE Leap Docker (bereits funktionierend) + +Das bestehende `Dockerfile-opensuse-leap.dockerfile` verwendet openSUSE mit Qt6 aus den offiziellen Repos: +```bash +docker build -t legatus-opensuse:latest -f jenkins/Dockerfile-opensuse-leap.dockerfile jenkins/ +``` + +## Build Dependencies + +Dieses Dockerfile installiert alle notwendigen Build-Dependencies außer Qt6: +- build-essential, cmake, ninja-build +- libboost-all-dev, libgeographic-dev +- libssl-dev, libcurl4-openssl-dev +- clang-tidy, clang-format + +## Verwendung + +```bash +# Docker Image bauen (ohne Qt6) +docker build -t legatus-ubuntu24.04:latest -f Dockerfile-ubuntu26.04.dockerfile . + +# Mit Qt6 vom Host mounten +docker run --rm -v $(pwd):/repo -v /opt/Qt:/opt/Qt \ + -e CMAKE_PREFIX_PATH=/opt/Qt/6.8.2/gcc_64/lib/cmake \ + legatus-ubuntu24.04:latest \ + cmake -S /repo/qt-migration-legatus/qt6-after/qt6-migrated-legatus \ + -B /repo/build -DCMAKE_BUILD_TYPE=Debug + +# Build ausführen +docker run --rm -v $(pwd):/repo -v /opt/Qt:/opt/Qt \ + -e CMAKE_PREFIX_PATH=/opt/Qt/6.8.2/gcc_64/lib/cmake \ + legatus-ubuntu24.04:latest \ + cmake --build /repo/build --parallel $(nproc) +``` + +## Hinweis für CI/CD + +Für Jenkins/GitLab CI wird empfohlen: +1. Ein Basis-Image mit Qt6 zu bauen und in einer Registry zu speichern +2. Oder Qt6 auf dem CI-Host zu installieren und ins Docker-Image zu mounten +3. Oder das bewährte openSUSE-Image zu verwenden \ No newline at end of file diff --git a/jenkins_builder.sh b/jenkins_builder.sh new file mode 100755 index 0000000..86d9d23 --- /dev/null +++ b/jenkins_builder.sh @@ -0,0 +1,54 @@ +#!/usr/bin/env bash +# +# Build an LTS RPM for one project flavor (ahtc / guez). +# Driven by rpmbuild/make_rpm.py — see also jenkins/Jenkinsfile. +# +# Required environment (set by the Jenkinsfile or `docker run -e ...`): +# PROJECT LTS flavor: qatar | ahtc | guez (cmake -D_pname) +# OS_VERSION Ubuntu base version, e.g. 26.04 +# LTS_VERSION Major.minor LTS version, e.g. 1.0 +# GUEZ_MODE ON | OFF — cmake -DGUEZ_MODE +# WORKSPACE Jenkins workspace path (set automatically by Jenkins) +# PROJECT_BASE_DIR Path used by make_rpm.py as the source tree (basename must be 'legatus') +# BUILD_VERSION Spec suffix selector for make_rpm.py (lts${BUILD_VERSION}.spec) +# BUILD_NUMBER Jenkins build number (used as @RELEASE@ in the spec) +# BUILD_TAG Jenkins build tag (used as @JENKINS_BUILD_TAG@ in the spec) +# + +set -eo pipefail + +: "${PROJECT:?PROJECT must be set}" +: "${OS_VERSION:?OS_VERSION must be set}" +: "${LTS_VERSION:?LTS_VERSION must be set}" +: "${GUEZ_MODE:?GUEZ_MODE must be set}" +: "${WORKSPACE:?WORKSPACE must be set}" +: "${PROJECT_BASE_DIR:?PROJECT_BASE_DIR must be set}" + +echo "Building LTS ${LTS_VERSION}-${BUILD_NUMBER:-?} RPM for project '${PROJECT}' (OS ${OS_VERSION})." +echo "Spec selector : lts${BUILD_VERSION:-}.spec" +echo "PROJECT_BASE_DIR=${PROJECT_BASE_DIR}" + +mkdir -p /shd/CTC/TOOLS/rpmbuild/{BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS} + +# openSUSE's rpmbuild defaults %_topdir to /usr/src/packages and ignores HOME +echo "%_topdir /shd/CTC/TOOLS/rpmbuild" > "${HOME}/.rpmmacros" + +# Stage workspace as a clean copy under PROJECT_BASE_DIR +rm -rf "${PROJECT_BASE_DIR}" +mkdir -p "${PROJECT_BASE_DIR}" +tar --exclude='./rpms' --exclude='./.git' --exclude='./build' \ + -cf - -C "${WORKSPACE}" . | tar -xf - -C "${PROJECT_BASE_DIR}" + +export VERSION_DATE +VERSION_DATE=$(date +%Y-%m-%d) + +# Output is isolated per OS version so parallel OS builds of the same project +cd "${WORKSPACE}/rpmbuild" +python make_rpm.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/pgsql/" + +echo "RPMs produced for '${PROJECT}' (OS ${OS_VERSION}):" +ls -lhR "${WORKSPACE}/rpms/${PROJECT}/${OS_VERSION}/" diff --git a/jenkins_builder_ubuntu26.sh b/jenkins_builder_ubuntu26.sh new file mode 100644 index 0000000..4d7a6a7 --- /dev/null +++ b/jenkins_builder_ubuntu26.sh @@ -0,0 +1,52 @@ +#!/usr/bin/env bash +# +# Build an LTS DEB package for Ubuntu 26.04 +# Migrated from jenkins_builder.sh (openSUSE) to Ubuntu/DEB ecosystem +# +# Required environment (set by the Jenkinsfile or `docker run -e ...`): +# PROJECT LTS flavor: qatar | ahtc | guez (cmake -D_pname) +# OS_VERSION Ubuntu version, e.g. 26.04 +# LTS_VERSION Major.minor LTS version, e.g. 1.0 +# GUEZ_MODE ON | OFF — cmake -DGUEZ_MODE +# WORKSPACE Jenkins workspace path (set automatically by Jenkins) +# PROJECT_BASE_DIR Path used by make_rpm_ubuntu26.py as the source tree +# BUILD_NUMBER Jenkins build number (used as release in DEB version) +# BUILD_TAG Jenkins build tag +# + +set -eo pipefail + +: "${PROJECT:?PROJECT must be set}" +: "${OS_VERSION:?OS_VERSION must be set}" +: "${LTS_VERSION:?LTS_VERSION must be set}" +: "${GUEZ_MODE:?GUEZ_MODE must be set}" +: "${WORKSPACE:?WORKSPACE must be set}" +: "${PROJECT_BASE_DIR:?PROJECT_BASE_DIR must be set}" + +echo "Building LTS ${LTS_VERSION}-${BUILD_NUMBER:-?} DEB for project '${PROJECT}' (Ubuntu ${OS_VERSION})." +echo "PROJECT_BASE_DIR=${PROJECT_BASE_DIR}" + +# Set up builder user environment (running as root in container) +export HOME=/home/builder +mkdir -p "${HOME}" + +# Stage workspace as a clean copy under PROJECT_BASE_DIR +rm -rf "${PROJECT_BASE_DIR}" +mkdir -p "${PROJECT_BASE_DIR}" +tar --exclude='./rpms' --exclude='./.git' --exclude='./build' --exclude='./deb_build_tmp' \ + -cf - -C "${WORKSPACE}" . | tar -xf - -C "${PROJECT_BASE_DIR}" + +export VERSION_DATE +VERSION_DATE=$(date +%Y-%m-%d) + +# Output is isolated per OS version so parallel OS builds of the same project +cd "${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}" + +echo "DEB packages produced for '${PROJECT}' (Ubuntu ${OS_VERSION}):" +ls -lhR "${WORKSPACE}/rpms/${PROJECT}/${OS_VERSION}/" \ No newline at end of file diff --git a/jenkins_publisher.sh b/jenkins_publisher.sh new file mode 100755 index 0000000..a081735 --- /dev/null +++ b/jenkins_publisher.sh @@ -0,0 +1,62 @@ +#!/usr/bin/env bash +# +# Upload produced RPMs to the internal artifact repository and emit two +# helper files for the Jenkinsfile to consume (named per project + OS version): +# ${WORKSPACE}/url-${PROJECT}-${OS_VERSION}.txt — browseable URL of the uploaded folder +# ${WORKSPACE}/tdsversion-${PROJECT}-${OS_VERSION}.txt — full version string (LTS-build) +# +# Required environment (set by the Jenkinsfile / withCredentials): +# PROJECT LTS flavor: ahtc | guez +# OS_VERSION Ubuntu base version, e.g. 26.04 +# LTS_VERSION Major.minor LTS version, e.g. 1.0 +# BUILD_NUMBER Jenkins build number (release component of the artifact name) +# WORKSPACE Jenkins workspace path +# ARTIFACTREPO Base URL of the internal repo (no trailing slash) +# ARTIFACTFOLDER Subfolder under cts-rpms/ (project name, e.g. qatar) +# CURL_CRED user:password for the upload (Jenkins credential) +# + +set -eo pipefail + +: "${PROJECT:?PROJECT must be set}" +: "${OS_VERSION:?OS_VERSION must be set}" +: "${LTS_VERSION:?LTS_VERSION must be set}" +: "${BUILD_NUMBER:?BUILD_NUMBER must be set}" +: "${WORKSPACE:?WORKSPACE must be set}" +: "${ARTIFACTREPO:?ARTIFACTREPO must be set}" +: "${ARTIFACTFOLDER:?ARTIFACTFOLDER must be set}" +: "${CURL_CRED:?CURL_CRED must be set}" + +tds_folder_name="${PROJECT}-TDS-${LTS_VERSION}-${BUILD_NUMBER}" +tds_folder_path="${WORKSPACE}/rpms/${PROJECT}/${OS_VERSION}" +tds_artifact_store="${ARTIFACTREPO}/repository/cts-rpms/${ARTIFACTFOLDER}/${OS_VERSION}/${tds_folder_name}" + +if [ ! -d "${tds_folder_path}/${tds_folder_name}" ]; then + echo "ERROR: expected RPM folder not found: ${tds_folder_path}/${tds_folder_name}" >&2 + exit 1 +fi + +shopt -s nullglob +uploaded=0 +for file in "${tds_folder_path}/${tds_folder_name}"/*; do + [ -f "${file}" ] || continue + name=$(basename "${file}") + echo "Uploading: ${name}" + curl --fail --silent --show-error \ + --user "${CURL_CRED}" \ + --upload-file "${file}" \ + "${tds_artifact_store}/${name}" + uploaded=$((uploaded + 1)) +done + +if [ "${uploaded}" -eq 0 ]; then + echo "ERROR: no files uploaded from ${tds_folder_path}/${tds_folder_name}" >&2 + exit 1 +fi + +echo "Uploaded ${uploaded} file(s) to ${tds_artifact_store}/" + +# Per-(project, OS) filenames so concurrent publish stages don't clobber each +# other's helper files; the Jenkinsfile reads back the matching names. +echo "${ARTIFACTREPO}/service/rest/repository/browse/cts-rpms/${ARTIFACTFOLDER}/${OS_VERSION}/${tds_folder_name}/" > "${WORKSPACE}/url-${PROJECT}-${OS_VERSION}.txt" +echo "${LTS_VERSION}-${BUILD_NUMBER}" > "${WORKSPACE}/tdsversion-${PROJECT}-${OS_VERSION}.txt" diff --git a/jenkins_publisher_ubuntu26.sh b/jenkins_publisher_ubuntu26.sh new file mode 100644 index 0000000..8dcef73 --- /dev/null +++ b/jenkins_publisher_ubuntu26.sh @@ -0,0 +1,67 @@ +#!/usr/bin/env bash +# +# Upload produced DEBs to the internal artifact repository and emit two +# helper files for the Jenkinsfile to consume (named per project + OS version): +# ${WORKSPACE}/url-${PROJECT}-${OS_VERSION}.txt — browseable URL of the uploaded folder +# ${WORKSPACE}/tdsversion-${PROJECT}-${OS_VERSION}.txt — full version string (LTS-build) +# +# Migrated from jenkins_publisher.sh (openSUSE) to Ubuntu/DEB ecosystem +# +# Required environment (set by the Jenkinsfile / withCredentials): +# PROJECT LTS flavor: ahtc | guez +# OS_VERSION Ubuntu base version, e.g. 26.04 +# LTS_VERSION Major.minor LTS version, e.g. 1.0 +# BUILD_NUMBER Jenkins build number (release component of the artifact name) +# WORKSPACE Jenkins workspace path +# ARTIFACTREPO Base URL of the internal repo (no trailing slash) +# ARTIFACTFOLDER Subfolder under cts-rpms/ (project name, e.g. qatar) +# CURL_CRED user:password for the upload (Jenkins credential) +# + +set -eo pipefail + +: "${PROJECT:?PROJECT must be set}" +: "${OS_VERSION:?OS_VERSION must be set}" +: "${LTS_VERSION:?LTS_VERSION must be set}" +: "${BUILD_NUMBER:?BUILD_NUMBER must be set}" +: "${WORKSPACE:?WORKSPACE must be set}" +: "${ARTIFACTREPO:?ARTIFACTREPO must be set}" +: "${ARTIFACTFOLDER:?ARTIFACTFOLDER must be set}" +: "${CURL_CRED:?CURL_CRED must be set}" + +tds_folder_name="${PROJECT}-TDS-${LTS_VERSION}-${BUILD_NUMBER}" +tds_folder_path="${WORKSPACE}/rpms/${PROJECT}/${OS_VERSION}" +tds_artifact_store="${ARTIFACTREPO}/repository/cts-rpms/${ARTIFACTFOLDER}/${OS_VERSION}/${tds_folder_name}" + +if [ ! -d "${tds_folder_path}/${tds_folder_name}" ]; then + echo "ERROR: expected package folder not found: ${tds_folder_path}/${tds_folder_name}" >&2 + exit 1 +fi + +shopt -s nullglob +uploaded=0 +for file in "${tds_folder_path}/${tds_folder_name}"/*; do + [ -f "${file}" ] || continue + # Upload .deb, .dsc, .changes, .buildinfo files + if [[ "${file}" == *.deb ]] || [[ "${file}" == *.dsc ]] || [[ "${file}" == *.changes ]] || [[ "${file}" == *.buildinfo ]]; then + name=$(basename "${file}") + echo "Uploading: ${name}" + curl --fail --silent --show-error \ + --user "${CURL_CRED}" \ + --upload-file "${file}" \ + "${tds_artifact_store}/${name}" + uploaded=$((uploaded + 1)) + fi +done + +if [ "${uploaded}" -eq 0 ]; then + echo "ERROR: no files uploaded from ${tds_folder_path}/${tds_folder_name}" >&2 + exit 1 +fi + +echo "Uploaded ${uploaded} file(s) to ${tds_artifact_store}/" + +# Per-(project, OS) filenames so concurrent publish stages don't clobber each +# other's helper files; the Jenkinsfile reads back the matching names. +echo "${ARTIFACTREPO}/service/rest/repository/browse/cts-rpms/${ARTIFACTFOLDER}/${OS_VERSION}/${tds_folder_name}/" > "${WORKSPACE}/url-${PROJECT}-${OS_VERSION}.txt" +echo "${LTS_VERSION}-${BUILD_NUMBER}" > "${WORKSPACE}/tdsversion-${PROJECT}-${OS_VERSION}.txt" \ No newline at end of file