reset jenkins file
This commit is contained in:
1 parent
37bd700564
commit
26f702b7a4
7 files changed
-1612
No files matched your search
@@ -1,153 +0,0 @@
|
|||||||
// Release pipeline for the Qt6-migrated legatus validation-scope branch
|
|
||||||
// (story/release-validation-scope): TetraIF, Z, Lts/Common (+
|
|
||||||
// Lts/Proxies/TrainingAreaBase) -> 5 release DEB packages.
|
|
||||||
//
|
|
||||||
// Workspace layout (checked out by Jenkins, outer pipeline repo):
|
|
||||||
// <WORKSPACE>/
|
|
||||||
// external/
|
|
||||||
// qt-migration-legatus/qt6-after/qt6-migrated-legatus/ <- LEGATUS_ROOT
|
|
||||||
// Dockerfile (prebuilt build image recipe)
|
|
||||||
// new_docker_build.sh (local build driver)
|
|
||||||
// rpmbuild/make_rpm_ubuntu26.py (in-tree packaging)
|
|
||||||
// jenkins-ci-rme/ (this pipeline)
|
|
||||||
//
|
|
||||||
// The build container image is the prebuilt image built from the in-tree
|
|
||||||
// Dockerfile; it is built on the agent when not present (RebuildImage
|
|
||||||
// forces a fresh build).
|
|
||||||
|
|
||||||
def project = 'guez'
|
|
||||||
def legatusRoot = 'qt-migration-legatus/qt6-after/qt6-migrated-legatus'
|
|
||||||
def imageName = 'legatus-qt6:1.0'
|
|
||||||
|
|
||||||
properties([
|
|
||||||
disableConcurrentBuilds(),
|
|
||||||
parameters([
|
|
||||||
string(name: 'OsVersions', defaultValue: '26.04', description: 'Comma-separated Ubuntu base versions, all built in parallel'),
|
|
||||||
string(name: 'LtsVersion', defaultValue: '1.0', description: 'LTS version (major.minor) passed to make_rpm_ubuntu26.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 DEBs to the internal artifact repository'),
|
|
||||||
booleanParam(name: 'RebuildImage', defaultValue: false, description: 'Rebuild the prebuilt build image from the in-tree Dockerfile (default: reuse when present)'),
|
|
||||||
booleanParam(name: 'RunCoverage', defaultValue: true, description: 'Build the release scope with -O0 --coverage, run ctest, collect the lcov report and archive it')
|
|
||||||
])
|
|
||||||
])
|
|
||||||
|
|
||||||
env.GIT_TERMINAL_PROMPT = '0'
|
|
||||||
env.LTS_VERSION = "${params.LtsVersion}"
|
|
||||||
env.ARTIFACTREPO = 'https://internal-repo.sl.defence-elec.de'
|
|
||||||
|
|
||||||
// OS versions this build covers; every build is isolated under
|
|
||||||
// rpms/${project}/${osVersion} so concurrent OS builds never collide.
|
|
||||||
def osVersions = params.OsVersions.split(',').collect { it.trim() }.findAll { it }
|
|
||||||
|
|
||||||
def builds = [:]
|
|
||||||
osVersions.each { osVersion ->
|
|
||||||
def rpmsDir = "rpms/${project}/${osVersion}"
|
|
||||||
|
|
||||||
builds["${project} (${osVersion})"] = {
|
|
||||||
stage("Prepare ${project} (${osVersion})") {
|
|
||||||
sh "rm -rf ${rpmsDir}"
|
|
||||||
sh "mkdir -p ${rpmsDir}"
|
|
||||||
}
|
|
||||||
|
|
||||||
stage("Prepare build image ${project} (${osVersion})") {
|
|
||||||
if (params.RebuildImage) {
|
|
||||||
sh "docker rmi ${imageName} || true"
|
|
||||||
}
|
|
||||||
// The in-tree driver owns the Dockerfile build args (APT_PACKAGES,
|
|
||||||
// QT_VERSION, ...) - single source of truth.
|
|
||||||
sh """
|
|
||||||
if docker image inspect ${imageName} >/dev/null 2>&1; then
|
|
||||||
echo "Reusing existing prebuilt image ${imageName}"
|
|
||||||
else
|
|
||||||
echo "Building prebuilt image ${imageName} from the in-tree Dockerfile..."
|
|
||||||
cd ${legatusRoot} && bash ./new_docker_build.sh --build-prebuilt-image --docker-image ${imageName}
|
|
||||||
fi
|
|
||||||
"""
|
|
||||||
}
|
|
||||||
|
|
||||||
stage("Build DEB ${project} (${osVersion})") {
|
|
||||||
def buildContainer = docker.image("${imageName}")
|
|
||||||
def guezMode = (project == 'guez') ? 'ON' : 'OFF'
|
|
||||||
|
|
||||||
def dockerOpts = "--init --shm-size=2g" +
|
|
||||||
" -v ${WORKSPACE}:/workspace" +
|
|
||||||
" -e WORKSPACE=/workspace" +
|
|
||||||
" -e PROJECT_BASE_DIR=/workspace" +
|
|
||||||
" -e PROJECT=${project}" +
|
|
||||||
" -e OS_VERSION=${osVersion}" +
|
|
||||||
" -e LTS_VERSION=${LTS_VERSION}" +
|
|
||||||
" -e GUEZ_MODE=${guezMode}" +
|
|
||||||
" -e BUILD_NUMBER=${env.BUILD_NUMBER}" +
|
|
||||||
" -e BUILD_TAG=${env.BUILD_TAG}"
|
|
||||||
|
|
||||||
buildContainer.inside(dockerOpts) {
|
|
||||||
sh "bash /workspace/${legatusRoot}/jenkins-ci-rme/jenkins_builder_ubuntu26.sh"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
stage("Coverage ${project} (${osVersion})") {
|
|
||||||
if (!params.RunCoverage) {
|
|
||||||
echo "Coverage skipped for ${project} (OS ${osVersion}, RunCoverage=false)"
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// The driver (run on the agent, same pattern as the image-build
|
|
||||||
// stage) builds the scope with -O0 --coverage, runs ctest and
|
|
||||||
// collects the lcov report into the workspace mount.
|
|
||||||
sh "cd ${legatusRoot} && bash ./new_docker_build.sh --docker-image ${imageName} --run-coverage --coverage-output-dir ${WORKSPACE}/coverage/${project}/${osVersion}"
|
|
||||||
archiveArtifacts artifacts: "coverage/${project}/${osVersion}/**", allowEmptyArchive: true
|
|
||||||
}
|
|
||||||
|
|
||||||
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 ${legatusRoot}/jenkins-ci-rme/jenkins_publisher_ubuntu26.sh
|
|
||||||
"""
|
|
||||||
}
|
|
||||||
|
|
||||||
def tdsUrl = readFile("url-${project}-${osVersion}.txt").trim()
|
|
||||||
def tdsVersion = readFile("tdsversion-${project}-${osVersion}.txt").trim()
|
|
||||||
def link = """<a href="${tdsUrl}" target="_blank">${project} ${tdsVersion} (OS ${osVersion})</a>"""
|
|
||||||
currentBuild.description = currentBuild.description ? "${currentBuild.description}<br/>${link}" : link
|
|
||||||
} else {
|
|
||||||
echo "Artifact-repo publish skipped for ${project} (OS ${osVersion}, PublishArtifactRepo=false)"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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 Qt6 release build initialized — branch '${env.BRANCH_NAME}', project: ${project}, LTS ${env.LTS_VERSION}, OS version(s): ${osVersions.join(', ')}"
|
|
||||||
}
|
|
||||||
|
|
||||||
parallel builds
|
|
||||||
|
|
||||||
stage("Finalization") {
|
|
||||||
echo "Legatus Qt6 release build completed — project: ${project} (LTS ${env.LTS_VERSION}), OS version(s): ${osVersions.join(', ')}"
|
|
||||||
}
|
|
||||||
|
|
||||||
currentBuild.result = 'SUCCESS'
|
|
||||||
} catch (e) {
|
|
||||||
currentBuild.result = 'FAILURE'
|
|
||||||
throw e
|
|
||||||
}
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
# jenkins-ci-rme — release pipeline for the Qt6 validation-scope branch
|
|
||||||
|
|
||||||
In-tree copy of the Jenkins CI flow, adapted so the release pipeline depends
|
|
||||||
only on files inside this source tree:
|
|
||||||
|
|
||||||
| File | Purpose |
|
|
||||||
|---|---|
|
|
||||||
| `Jenkinsfile` | Jenkins pipeline: prepare the prebuilt image (in-tree `Dockerfile`), run the builder inside the container, publish the DEBs to the artifact repo |
|
|
||||||
| `jenkins_builder_ubuntu26.sh` | Runs **inside** the build container: stages the workspace, runs the in-tree `rpmbuild/make_rpm_ubuntu26.py`, copies the DEBs to the packages-out mount |
|
|
||||||
| `jenkins_publisher_ubuntu26.sh` | Runs on the Jenkins agent: uploads the DEBs from `${WORKSPACE}/rpms/${PROJECT}/${OS_VERSION}/` to the internal artifact repository |
|
|
||||||
| `release-16-10-2026.sh` | Local driver: the same flow without Jenkins, through the in-tree `new_docker_build.sh` |
|
|
||||||
|
|
||||||
## Not included (superseded)
|
|
||||||
|
|
||||||
- `jenkins_builder.sh` / `jenkins_publisher.sh` — openSUSE/RPM flow, not used
|
|
||||||
by this branch (DEB/Ubuntu 26.04 only)
|
|
||||||
- `Dockerfile-15.1` / `Dockerfile-ubuntu26.04` / `Dockerfile-ubuntu26-qt6` —
|
|
||||||
old image recipes; the prebuilt build image is built from the in-tree
|
|
||||||
`Dockerfile` (one level up)
|
|
||||||
- `jenkins_notifier.sh` — Bitbucket build-status notification, not part of
|
|
||||||
this project
|
|
||||||
|
|
||||||
## Adaptations vs. the outer-repo copy
|
|
||||||
|
|
||||||
- Packaging uses the **in-tree** `rpmbuild/make_rpm_ubuntu26.py`
|
|
||||||
(was `${WORKSPACE}/rpmbuild` from the outer repo)
|
|
||||||
- The prebuilt build image is built from the **in-tree** `Dockerfile` via
|
|
||||||
`new_docker_build.sh --build-prebuilt-image` (was a pre-pulled harbor
|
|
||||||
image) — build args stay in `new_docker_build.sh` (single source of truth)
|
|
||||||
- `MIGRATE_PIPELINE_ROOT` is no longer needed: `new_docker_build.sh`
|
|
||||||
derives it from its own location
|
|
||||||
- DEB output path: `${WORKSPACE}/rpms/${PROJECT}/${OS_VERSION}/` (Jenkins
|
|
||||||
convention); the packages-out copy is skipped when that directory is the
|
|
||||||
make_rpm output dir (same device:inode guard as in `new_docker_build.sh`)
|
|
||||||
- Publisher uploads `${WORKSPACE}/rpms/${PROJECT}/${OS_VERSION}/` directly —
|
|
||||||
`make_rpm_ubuntu26.py` writes the DEBs there without a TDS subfolder
|
|
||||||
- The post-publish Cleanup stage was dropped: the DEBs are kept under
|
|
||||||
`${WORKSPACE}/rpms/...` (the documented output location)
|
|
||||||
|
|
||||||
## Local run
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd qt6-migrated-legatus
|
|
||||||
bash ./jenkins-ci-rme/release-16-10-2026.sh
|
|
||||||
# DEBs: <pipeline-root>/rpms/guez/26.04/
|
|
||||||
```
|
|
||||||
|
|
||||||
## Jenkins setup
|
|
||||||
|
|
||||||
The job SCM must be the outer pipeline repository (the Jenkinsfile lives in
|
|
||||||
the `qt-migration-legatus` submodule; point the job's script path at
|
|
||||||
`qt-migration-legatus/qt6-after/qt6-migrated-legatus/jenkins-ci-rme/Jenkinsfile`).
|
|
||||||
Required Jenkins credential: `internal-repo-uploader` (username/password for
|
|
||||||
the artifact repository).
|
|
||||||
@@ -1,84 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
#
|
|
||||||
# Build the LTS DEB packages for the Qt6-migrated legatus release
|
|
||||||
# (validation scope: TetraIF, Z, Lts/Common + Lts/Proxies/TrainingAreaBase)
|
|
||||||
# for Ubuntu 26.04.
|
|
||||||
#
|
|
||||||
# Runs inside the prebuilt build container (built from the in-tree
|
|
||||||
# Dockerfile) with the pipeline workspace mounted at /workspace.
|
|
||||||
# Packaging is done by the IN-TREE rpmbuild copy
|
|
||||||
# (qt-migration-legatus/qt6-after/qt6-migrated-legatus/rpmbuild/), so the
|
|
||||||
# release flow needs no files outside the source tree.
|
|
||||||
#
|
|
||||||
# Required environment (set by the Jenkinsfile or `docker run -e ...`):
|
|
||||||
# PROJECT LTS flavor: guez
|
|
||||||
# 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 Container workspace path (/workspace)
|
|
||||||
# PROJECT_BASE_DIR Staging root inside the container (/workspace)
|
|
||||||
# BUILD_NUMBER Build number (used as release in the DEB version)
|
|
||||||
# BUILD_TAG Build tag
|
|
||||||
#
|
|
||||||
# IMPORTANT: Source files under git management must NEVER be deleted.
|
|
||||||
# Only the temporary staging directory (deb_stage) is removed.
|
|
||||||
|
|
||||||
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}"
|
|
||||||
|
|
||||||
# Stage workspace as a clean copy under PROJECT_BASE_DIR/deb_stage.
|
|
||||||
STAGE_DIR="${PROJECT_BASE_DIR}/deb_stage"
|
|
||||||
rm -rf "${STAGE_DIR}"
|
|
||||||
mkdir -p "${STAGE_DIR}"
|
|
||||||
tar --exclude='./rpms' --exclude='./.git' --exclude='./build' \
|
|
||||||
--exclude='./deb_build_tmp' --exclude='./deb_stage' --exclude='./packages-out' \
|
|
||||||
-cf - -C "${WORKSPACE}" . | tar -xf - -C "${STAGE_DIR}"
|
|
||||||
|
|
||||||
export VERSION_DATE
|
|
||||||
VERSION_DATE=$(date +%Y-%m-%d)
|
|
||||||
|
|
||||||
# Real CMake project root inside the staged tree (the in-tree source)
|
|
||||||
SOURCE_DIR="${STAGE_DIR}/qt-migration-legatus/qt6-after/qt6-migrated-legatus"
|
|
||||||
if [ ! -f "${SOURCE_DIR}/CMakeLists.txt" ] || [ ! -f "${SOURCE_DIR}/rpmbuild/make_rpm_ubuntu26.py" ]; then
|
|
||||||
echo "ERROR: staged source incomplete under ${SOURCE_DIR} (CMakeLists.txt or rpmbuild/make_rpm_ubuntu26.py missing)" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Output is isolated per OS version so parallel OS builds of the same
|
|
||||||
# project never collide
|
|
||||||
cd "${SOURCE_DIR}/rpmbuild"
|
|
||||||
python3 make_rpm_ubuntu26.py -c LTS \
|
|
||||||
--project_name "${PROJECT}" \
|
|
||||||
--version "${LTS_VERSION}" \
|
|
||||||
--output_dir "${WORKSPACE}/rpms/${PROJECT}/${OS_VERSION}/" \
|
|
||||||
--source_dir "${SOURCE_DIR}" \
|
|
||||||
--cmake_build_flags "-DUSE_IPO=ON -DUSE_UNITY_BUILD=ON -DGUEZ_MODE=${GUEZ_MODE} -DBUILD_WLS=ON -DPostgreSQL_TYPE_INCLUDE_DIR=/usr/include/postgresql/ -DRELEASE_BUILD=ON" \
|
|
||||||
--build_number "${BUILD_NUMBER:-1}" \
|
|
||||||
--release_scope
|
|
||||||
|
|
||||||
PACKAGE_OUT_DIR=/workspace/packages-out
|
|
||||||
mkdir -p "${PACKAGE_OUT_DIR}"
|
|
||||||
shopt -s nullglob
|
|
||||||
for deb in "${WORKSPACE}/rpms/${PROJECT}/${OS_VERSION}/"*.deb; do
|
|
||||||
base="$(basename "${deb}")"
|
|
||||||
if [[ -e "${PACKAGE_OUT_DIR}/${base}" ]] &&
|
|
||||||
[[ "$(stat -c '%d:%i' "${deb}")" == "$(stat -c '%d:%i' "${PACKAGE_OUT_DIR}/${base}")" ]]; then
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
cp -f "${deb}" "${PACKAGE_OUT_DIR}/"
|
|
||||||
done
|
|
||||||
shopt -u nullglob
|
|
||||||
|
|
||||||
echo "DEB packages produced for '${PROJECT}' (Ubuntu ${OS_VERSION}):"
|
|
||||||
ls -lhR "${WORKSPACE}/rpms/${PROJECT}/${OS_VERSION}/"
|
|
||||||
echo "DEB packages copied to ${PACKAGE_OUT_DIR}:"
|
|
||||||
ls -lh "${PACKAGE_OUT_DIR}/"
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
#
|
|
||||||
# Upload the 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)
|
|
||||||
#
|
|
||||||
# Adapted for the in-tree flow: make_rpm_ubuntu26.py writes the DEBs
|
|
||||||
# directly under ${WORKSPACE}/rpms/${PROJECT}/${OS_VERSION}/ (no TDS
|
|
||||||
# subfolder), so that directory is uploaded as-is.
|
|
||||||
#
|
|
||||||
# Required environment (set by the Jenkinsfile / withCredentials):
|
|
||||||
# PROJECT LTS flavor: guez
|
|
||||||
# OS_VERSION Ubuntu base version, e.g. 26.04
|
|
||||||
# LTS_VERSION Major.minor LTS version, e.g. 1.0
|
|
||||||
# BUILD_NUMBER 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. guez)
|
|
||||||
# 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}" ]; then
|
|
||||||
echo "ERROR: expected package folder not found: ${tds_folder_path}" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
shopt -s nullglob
|
|
||||||
uploaded=0
|
|
||||||
for file in "${tds_folder_path}"/*; 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
|
|
||||||
shopt -u nullglob
|
|
||||||
|
|
||||||
if [ "${uploaded}" -eq 0 ]; then
|
|
||||||
echo "ERROR: no files uploaded from ${tds_folder_path}" >&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"
|
|
||||||
@@ -1,77 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
#
|
|
||||||
# Local release pipeline for the Qt6-migrated legatus validation scope
|
|
||||||
# (TetraIF, Z, Lts/Common + Lts/Proxies/TrainingAreaBase).
|
|
||||||
#
|
|
||||||
# Runs the in-tree new_docker_build.sh:
|
|
||||||
# - builds the prebuilt Docker image from the in-tree Dockerfile when the
|
|
||||||
# image is not present yet
|
|
||||||
# - builds the release scope, runs ctest and produces the release DEB
|
|
||||||
# packages with the in-tree rpmbuild script
|
|
||||||
# - collects the lcov code-coverage report (--run-coverage; set
|
|
||||||
# DRYRUN_COVERAGE=OFF to skip)
|
|
||||||
#
|
|
||||||
# The DEB packages land in ${WORKSPACE}/rpms/${PROJECT}/${OS_VERSION}/
|
|
||||||
# (Jenkins-style layout; locally WORKSPACE is the pipeline root).
|
|
||||||
#
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
||||||
LEGATUS_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
|
|
||||||
PIPELINE_ROOT="$(cd "${LEGATUS_ROOT}/../../.." && pwd)"
|
|
||||||
|
|
||||||
# Release build configuration (Jenkins-style variables)
|
|
||||||
export WORKSPACE="${PIPELINE_ROOT}"
|
|
||||||
export PROJECT="${PROJECT:-guez}"
|
|
||||||
export OS_VERSION="${OS_VERSION:-26.04}"
|
|
||||||
export LTS_VERSION="${LTS_VERSION:-1.0}"
|
|
||||||
export GUEZ_MODE="${GUEZ_MODE:-ON}"
|
|
||||||
export BUILD_NUMBER="${BUILD_NUMBER:-$(date +%Y%m%d-%H%M%S)}"
|
|
||||||
export BUILD_TAG="${BUILD_TAG:-release-qt6-first}"
|
|
||||||
|
|
||||||
DOCKER_IMAGE="${DOCKER_IMAGE:-legatus-qt6:1.0}"
|
|
||||||
|
|
||||||
log_info() {
|
|
||||||
printf 'INFO: %s\n' "$*"
|
|
||||||
}
|
|
||||||
|
|
||||||
log_info "=== Qt6 Release Pipeline ==="
|
|
||||||
log_info "Pipeline root: ${PIPELINE_ROOT}"
|
|
||||||
log_info "Legatus root: ${LEGATUS_ROOT}"
|
|
||||||
log_info "Docker image: ${DOCKER_IMAGE}"
|
|
||||||
log_info "Build number: ${BUILD_NUMBER}"
|
|
||||||
log_info "Build tag: ${BUILD_TAG}"
|
|
||||||
log_info "Package output: ${WORKSPACE}/rpms/${PROJECT}/${OS_VERSION}/"
|
|
||||||
|
|
||||||
cd "${LEGATUS_ROOT}"
|
|
||||||
|
|
||||||
# Build the prebuilt image from the in-tree Dockerfile when not present yet
|
|
||||||
# (--build-prebuilt-image builds the image and exits)
|
|
||||||
if ! docker image inspect "${DOCKER_IMAGE}" >/dev/null 2>&1; then
|
|
||||||
log_info "Prebuilt image not found - building it from the in-tree Dockerfile..."
|
|
||||||
bash ./new_docker_build.sh --build-prebuilt-image --docker-image "${DOCKER_IMAGE}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Release scope build + ctest + DEB production (in-tree rpmbuild)
|
|
||||||
bash ./new_docker_build.sh \
|
|
||||||
--docker-image "${DOCKER_IMAGE}" \
|
|
||||||
--run-jenkins-builder \
|
|
||||||
--package-output-dir "${WORKSPACE}/rpms/${PROJECT}/${OS_VERSION}/" \
|
|
||||||
--project "${PROJECT}" \
|
|
||||||
--lts-version "${LTS_VERSION}" \
|
|
||||||
--build-number "${BUILD_NUMBER}" \
|
|
||||||
--build-tag "${BUILD_TAG}"
|
|
||||||
|
|
||||||
# Code coverage (lcov) - mirrors the Jenkins Coverage stage. Set
|
|
||||||
# DRYRUN_COVERAGE=OFF for a fast local DEB-only run.
|
|
||||||
DRYRUN_COVERAGE="${DRYRUN_COVERAGE:-ON}"
|
|
||||||
if [[ "${DRYRUN_COVERAGE}" == "ON" ]]; then
|
|
||||||
bash ./new_docker_build.sh \
|
|
||||||
--docker-image "${DOCKER_IMAGE}" \
|
|
||||||
--run-coverage \
|
|
||||||
--coverage-output-dir "${WORKSPACE}/coverage/${PROJECT}/${OS_VERSION}"
|
|
||||||
else
|
|
||||||
log_info "Coverage skipped (DRYRUN_COVERAGE=OFF)"
|
|
||||||
fi
|
|
||||||
|
|
||||||
log_info "=== Release Pipeline Complete ==="
|
|
||||||
@@ -1,647 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
|
||||||
# Build helper for the release validation-scope branch of qt-migrated-legatus
|
|
||||||
#
|
|
||||||
# Builds only the release scope (TetraIF, Z/src, Lts/Common +
|
|
||||||
# Lts/Proxies/TrainingAreaBase) inside the prebuilt Docker image and
|
|
||||||
# optionally runs the Jenkins builder to produce the release DEB packages.
|
|
||||||
#
|
|
||||||
# - Resolves MIGRATE_PIPELINE_ROOT (exported variable, .envrc, or derived
|
|
||||||
# from the script location) for the workspace and external mounts
|
|
||||||
# - Uses a prebuilt Docker image with all build dependencies installed
|
|
||||||
# (build it from ./Dockerfile via --build-prebuilt-image)
|
|
||||||
# - Optional deletion of the prebuilt Docker image via --delete-prebuilt-image
|
|
||||||
# - Optional DEB package production via the in-tree rpmbuild/
|
|
||||||
# make_rpm_ubuntu26.py (self-contained - no outer-repo dependencies)
|
|
||||||
# - Uses a temporary container-side script for robust execution
|
|
||||||
# -----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
usage() {
|
|
||||||
cat <<'EOF'
|
|
||||||
Usage: ./new_docker_build.sh [options]
|
|
||||||
|
|
||||||
Builds the release validation scope inside the prebuilt Docker image:
|
|
||||||
RELEASE_BUILD=ON (fixed) - TetraIF, Z, Lts/Common (+ TrainingAreaBase)
|
|
||||||
ctest runs for the release scope test executables (Lts/Common + Z)
|
|
||||||
|
|
||||||
Options:
|
|
||||||
--docker-image IMAGE Docker image name to use/build/delete
|
|
||||||
(default: legatus-qt6:1.0)
|
|
||||||
--build-prebuilt-image Build the prebuilt Docker image (from ./Dockerfile)
|
|
||||||
and exit. To run the build with it, run the script
|
|
||||||
again with --docker-image
|
|
||||||
--delete-prebuilt-image Delete the configured Docker image and exit
|
|
||||||
|
|
||||||
Package production options (RPM/DEB):
|
|
||||||
--run-jenkins-builder Build the release DEB packages inside the container
|
|
||||||
using the in-tree rpmbuild/make_rpm_ubuntu26.py
|
|
||||||
--package-output-dir DIR Directory to mount for package output (default: ./packages-out)
|
|
||||||
--lts-version VERSION LTS version for package (default: 1.0)
|
|
||||||
--project NAME Project name for package (default: guez)
|
|
||||||
--build-number NUM Build number for package (default: 1)
|
|
||||||
--build-tag TAG Build tag for package (default: manual-build)
|
|
||||||
|
|
||||||
Coverage options (lcov):
|
|
||||||
--run-coverage Build the release scope with -O0 --coverage, run ctest
|
|
||||||
and collect an lcov coverage report (mutually
|
|
||||||
exclusive with --run-jenkins-builder)
|
|
||||||
--coverage-output-dir DIR Directory to mount for coverage output
|
|
||||||
(default: ./coverage-out)
|
|
||||||
|
|
||||||
Environment variable overrides:
|
|
||||||
BUILD_PREBUILT_IMAGE=ON|OFF
|
|
||||||
DELETE_PREBUILT_IMAGE=ON|OFF
|
|
||||||
DOCKER_IMAGE=<image-name>
|
|
||||||
RUN_JENKINS_BUILDER=ON|OFF
|
|
||||||
PACKAGE_OUTPUT_DIR=<dir>
|
|
||||||
LTS_VERSION=<version>
|
|
||||||
PROJECT=<name>
|
|
||||||
GUEZ_MODE=ON|OFF
|
|
||||||
BUILD_NUMBER=<num>
|
|
||||||
BUILD_TAG=<tag>
|
|
||||||
RUN_COVERAGE=ON|OFF
|
|
||||||
COVERAGE_OUTPUT_DIR=<dir>
|
|
||||||
|
|
||||||
MIGRATE_PIPELINE_ROOT resolution (highest precedence first):
|
|
||||||
1. exported MIGRATE_PIPELINE_ROOT (e.g. from a Jenkinsfile)
|
|
||||||
2. MIGRATE_PIPELINE_ROOT set by .envrc in this directory
|
|
||||||
3. derived from the script location (three levels up)
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
./new_docker_build.sh --build-prebuilt-image --docker-image legatus-qt6:1.0
|
|
||||||
./new_docker_build.sh --docker-image legatus-qt6:1.0
|
|
||||||
./new_docker_build.sh --delete-prebuilt-image --docker-image legatus-qt6:1.0
|
|
||||||
./new_docker_build.sh --docker-image legatus-qt6:1.0 \
|
|
||||||
--run-jenkins-builder \
|
|
||||||
--package-output-dir "${WORKSPACE}/rpms/${PROJECT}/${OS_VERSION}/"
|
|
||||||
./new_docker_build.sh --docker-image legatus-qt6:1.0 \
|
|
||||||
--run-coverage \
|
|
||||||
--coverage-output-dir "${WORKSPACE}/coverage/${PROJECT}/${OS_VERSION}/"
|
|
||||||
EOF
|
|
||||||
}
|
|
||||||
|
|
||||||
log_info() {
|
|
||||||
printf 'INFO: %s\n' "$*"
|
|
||||||
}
|
|
||||||
|
|
||||||
log_error() {
|
|
||||||
printf 'ERROR: %s\n' "$*" >&2
|
|
||||||
}
|
|
||||||
|
|
||||||
die() {
|
|
||||||
log_error "$*"
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
require_command() {
|
|
||||||
local cmd="$1"
|
|
||||||
command -v "$cmd" >/dev/null 2>&1 || die "Required command not found: ${cmd}"
|
|
||||||
}
|
|
||||||
|
|
||||||
require_file() {
|
|
||||||
local path="$1"
|
|
||||||
local label="$2"
|
|
||||||
[[ -f "$path" ]] || die "${label} not found: ${path}"
|
|
||||||
}
|
|
||||||
|
|
||||||
require_directory() {
|
|
||||||
local path="$1"
|
|
||||||
local label="$2"
|
|
||||||
[[ -d "$path" ]] || die "${label} directory not found: ${path}"
|
|
||||||
}
|
|
||||||
|
|
||||||
require_non_empty() {
|
|
||||||
local value="$1"
|
|
||||||
local name="$2"
|
|
||||||
[[ -n "$value" ]] || die "Required variable ${name} is not set or empty"
|
|
||||||
}
|
|
||||||
|
|
||||||
normalize_on_off() {
|
|
||||||
local value="$1"
|
|
||||||
local name="$2"
|
|
||||||
|
|
||||||
case "${value^^}" in
|
|
||||||
ON|OFF)
|
|
||||||
printf '%s\n' "${value^^}"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
die "Invalid value for ${name}: ${value}. Expected ON or OFF"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
}
|
|
||||||
|
|
||||||
join_by() {
|
|
||||||
local delimiter="$1"
|
|
||||||
shift || true
|
|
||||||
local first=1
|
|
||||||
local arg
|
|
||||||
|
|
||||||
for arg in "$@"; do
|
|
||||||
if [[ $first -eq 1 ]]; then
|
|
||||||
printf '%s' "$arg"
|
|
||||||
first=0
|
|
||||||
else
|
|
||||||
printf '%s%s' "$delimiter" "$arg"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
cleanup_temp_dir() {
|
|
||||||
local dir="${1:-}"
|
|
||||||
if [[ -n "$dir" && -d "$dir" ]]; then
|
|
||||||
rm -rf "$dir"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
delete_prebuilt_image() {
|
|
||||||
local image_name="$1"
|
|
||||||
|
|
||||||
if docker image inspect "$image_name" >/dev/null 2>&1; then
|
|
||||||
log_info "Deleting Docker image: ${image_name}"
|
|
||||||
docker rmi "$image_name"
|
|
||||||
log_info "Docker image deleted successfully: ${image_name}"
|
|
||||||
else
|
|
||||||
log_info "Docker image does not exist, nothing to delete: ${image_name}"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
APT_PACKAGES=(
|
|
||||||
build-essential
|
|
||||||
cmake
|
|
||||||
libboost-dev
|
|
||||||
libboost-all-dev
|
|
||||||
libjson-glib-dev
|
|
||||||
libgeographiclib-dev
|
|
||||||
ninja-build
|
|
||||||
libkf6texttemplate-dev
|
|
||||||
libpoppler-dev
|
|
||||||
libpoppler-qt6-dev
|
|
||||||
libqt6core6
|
|
||||||
libqt6gui6
|
|
||||||
libqt6widgets6
|
|
||||||
libqt6sql6
|
|
||||||
libqt6sql6-psql
|
|
||||||
libqt6test6
|
|
||||||
qt6-base-dev
|
|
||||||
qt6-l10n-tools
|
|
||||||
qt6-serialport-dev
|
|
||||||
qt6-svg-dev
|
|
||||||
qt6-tools-dev-tools
|
|
||||||
qt6-tools-dev
|
|
||||||
qt6-websockets-dev
|
|
||||||
libgtest-dev
|
|
||||||
libpq-dev
|
|
||||||
postgresql-server-dev-all
|
|
||||||
git
|
|
||||||
python3-pip
|
|
||||||
# Code coverage (genhtml ships in the same package)
|
|
||||||
lcov
|
|
||||||
# Packaging tools for RPM/DEB build
|
|
||||||
rpm
|
|
||||||
debhelper
|
|
||||||
dpkg-dev
|
|
||||||
fakeroot
|
|
||||||
devscripts
|
|
||||||
)
|
|
||||||
|
|
||||||
# Release scope targets: TetraIF + Z components + Lts/Common libraries
|
|
||||||
# and the release-scope test executables (Lts/Common + Z)
|
|
||||||
RELEASE_BUILD_TARGETS=(
|
|
||||||
# TetraIF module targets (CoPrtCnv / LogView / PrtCnv)
|
|
||||||
CoPrtCnv
|
|
||||||
LogViewLogger
|
|
||||||
LogView
|
|
||||||
PrtCnvLib
|
|
||||||
PrtCnv
|
|
||||||
# Z module targets
|
|
||||||
NGLLogger
|
|
||||||
nglapplication
|
|
||||||
nglcompression
|
|
||||||
nglcoreapplication
|
|
||||||
ngldb
|
|
||||||
nglguiapplication
|
|
||||||
nglsettings
|
|
||||||
nglsingleapplication
|
|
||||||
nglsinglecoreapplication
|
|
||||||
ngltools
|
|
||||||
ngltranslator
|
|
||||||
nglwidgets
|
|
||||||
qtsingleapplication
|
|
||||||
qtsinglecoreapplication
|
|
||||||
wms_json_ds
|
|
||||||
tcpserver
|
|
||||||
# Lts/Common library targets (for tests)
|
|
||||||
LtsCoordTrans
|
|
||||||
LtsLicence
|
|
||||||
MockCoordTrans
|
|
||||||
# Test executables for release scope modules
|
|
||||||
# Note: grantlee_parser_smoke excluded - requires ktexttemplate_defaulttags plugin (not in release scope)
|
|
||||||
aes_crypt_test
|
|
||||||
ngltools_qt_smoke
|
|
||||||
lts_coord_trans_unit_test
|
|
||||||
test_nglpdfwidget
|
|
||||||
# TetraIF unit tests (TetraIF/unit-test)
|
|
||||||
coprtcnv_unit_test
|
|
||||||
logview_unit_test
|
|
||||||
prtcnv_unit_test
|
|
||||||
)
|
|
||||||
|
|
||||||
APT_PACKAGES_STRING="$(join_by ' ' "${APT_PACKAGES[@]}")"
|
|
||||||
|
|
||||||
build_prebuilt_image() {
|
|
||||||
local image_name="$1"
|
|
||||||
local dockerfile="Dockerfile"
|
|
||||||
|
|
||||||
require_file "${dockerfile}" "Prebuilt-image Dockerfile"
|
|
||||||
|
|
||||||
# The Dockerfile has no COPY/ADD, so an empty build context is fine -
|
|
||||||
# this avoids tarring the source tree into the build context.
|
|
||||||
local tmp_dir
|
|
||||||
tmp_dir="$(mktemp -d)"
|
|
||||||
|
|
||||||
trap 'cleanup_temp_dir "$tmp_dir"' RETURN
|
|
||||||
|
|
||||||
log_info "Building prebuilt Docker image: ${image_name} (Dockerfile: ${dockerfile})"
|
|
||||||
docker build -t "${image_name}" \
|
|
||||||
-f "${dockerfile}" \
|
|
||||||
--build-arg APT_PACKAGES="${APT_PACKAGES_STRING}" \
|
|
||||||
--build-arg QT_VERSION="${QT_VERSION}" \
|
|
||||||
--build-arg QT_ARCH="${QT_ARCH}" \
|
|
||||||
--build-arg QT_BASE_DIR="${QT_BASE_DIR}" \
|
|
||||||
"${tmp_dir}"
|
|
||||||
log_info "Prebuilt Docker image created successfully: ${image_name}"
|
|
||||||
}
|
|
||||||
|
|
||||||
require_command docker
|
|
||||||
|
|
||||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
||||||
MIGRATE_PIPELINE_ROOT_DEFAULT="$(cd "${SCRIPT_DIR}/../../.." && pwd)"
|
|
||||||
PIPELINE_ROOT_EXPORTED="${MIGRATE_PIPELINE_ROOT:-}"
|
|
||||||
|
|
||||||
if [[ -f ".envrc" ]]; then
|
|
||||||
set -a
|
|
||||||
source ".envrc"
|
|
||||||
set +a
|
|
||||||
fi
|
|
||||||
|
|
||||||
# An explicitly exported MIGRATE_PIPELINE_ROOT (Jenkinsfile) wins over .envrc
|
|
||||||
if [[ -n "${PIPELINE_ROOT_EXPORTED}" ]]; then
|
|
||||||
MIGRATE_PIPELINE_ROOT="${PIPELINE_ROOT_EXPORTED}"
|
|
||||||
else
|
|
||||||
MIGRATE_PIPELINE_ROOT="${MIGRATE_PIPELINE_ROOT:-${MIGRATE_PIPELINE_ROOT_DEFAULT}}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Fixed configuration for the release validation-scope branch
|
|
||||||
RELEASE_BUILD=ON
|
|
||||||
RUN_CTEST=ON
|
|
||||||
BUILD_PREBUILT_IMAGE="${BUILD_PREBUILT_IMAGE:-OFF}"
|
|
||||||
DELETE_PREBUILT_IMAGE="${DELETE_PREBUILT_IMAGE:-OFF}"
|
|
||||||
# Jenkins builder options for RPM/DEB package production
|
|
||||||
RUN_JENKINS_BUILDER="${RUN_JENKINS_BUILDER:-OFF}"
|
|
||||||
PACKAGE_OUTPUT_DIR="${PACKAGE_OUTPUT_DIR:-./packages-out}"
|
|
||||||
# Code coverage (lcov)
|
|
||||||
RUN_COVERAGE="${RUN_COVERAGE:-OFF}"
|
|
||||||
COVERAGE_OUTPUT_DIR="${COVERAGE_OUTPUT_DIR:-./coverage-out}"
|
|
||||||
LTS_VERSION="${LTS_VERSION:-1.0}"
|
|
||||||
PROJECT="${PROJECT:-guez}"
|
|
||||||
GUEZ_MODE="${GUEZ_MODE:-ON}"
|
|
||||||
BUILD_NUMBER="${BUILD_NUMBER:-1}"
|
|
||||||
BUILD_TAG="${BUILD_TAG:-manual-build}"
|
|
||||||
export QT_VERSION="${QT_VERSION:-6.10.2}"
|
|
||||||
export QT_ARCH="${QT_ARCH:-linux_gcc_64}"
|
|
||||||
# aqtinstall uses 'linux_gcc_64' but creates directory 'gcc_64'
|
|
||||||
export QT_ARCH_DIR="${QT_ARCH_DIR:-gcc_64}"
|
|
||||||
export QT_BASE_DIR="${QT_BASE_DIR:-/opt/Qt}"
|
|
||||||
|
|
||||||
while [[ $# -gt 0 ]]; do
|
|
||||||
case "$1" in
|
|
||||||
--build-prebuilt-image)
|
|
||||||
BUILD_PREBUILT_IMAGE=ON
|
|
||||||
;;
|
|
||||||
--delete-prebuilt-image)
|
|
||||||
DELETE_PREBUILT_IMAGE=ON
|
|
||||||
;;
|
|
||||||
--docker-image)
|
|
||||||
shift
|
|
||||||
[[ $# -gt 0 ]] || die "--docker-image requires an image name"
|
|
||||||
DOCKER_IMAGE="$1"
|
|
||||||
;;
|
|
||||||
--run-jenkins-builder)
|
|
||||||
RUN_JENKINS_BUILDER=ON
|
|
||||||
;;
|
|
||||||
--package-output-dir)
|
|
||||||
shift
|
|
||||||
[[ $# -gt 0 ]] || die "--package-output-dir requires a directory path"
|
|
||||||
PACKAGE_OUTPUT_DIR="$1"
|
|
||||||
;;
|
|
||||||
--run-coverage)
|
|
||||||
RUN_COVERAGE=ON
|
|
||||||
;;
|
|
||||||
--coverage-output-dir)
|
|
||||||
shift
|
|
||||||
[[ $# -gt 0 ]] || die "--coverage-output-dir requires a directory path"
|
|
||||||
COVERAGE_OUTPUT_DIR="$1"
|
|
||||||
;;
|
|
||||||
--lts-version)
|
|
||||||
shift
|
|
||||||
[[ $# -gt 0 ]] || die "--lts-version requires a version string"
|
|
||||||
LTS_VERSION="$1"
|
|
||||||
;;
|
|
||||||
--project)
|
|
||||||
shift
|
|
||||||
[[ $# -gt 0 ]] || die "--project requires a project name"
|
|
||||||
PROJECT="$1"
|
|
||||||
;;
|
|
||||||
--build-number)
|
|
||||||
shift
|
|
||||||
[[ $# -gt 0 ]] || die "--build-number requires a build number"
|
|
||||||
BUILD_NUMBER="$1"
|
|
||||||
;;
|
|
||||||
--build-tag)
|
|
||||||
shift
|
|
||||||
[[ $# -gt 0 ]] || die "--build-tag requires a build tag"
|
|
||||||
BUILD_TAG="$1"
|
|
||||||
;;
|
|
||||||
-h|--help)
|
|
||||||
usage
|
|
||||||
exit 0
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
usage
|
|
||||||
die "Unknown option: $1"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
shift
|
|
||||||
done
|
|
||||||
|
|
||||||
BUILD_PREBUILT_IMAGE="$(normalize_on_off "$BUILD_PREBUILT_IMAGE" "BUILD_PREBUILT_IMAGE")"
|
|
||||||
DELETE_PREBUILT_IMAGE="$(normalize_on_off "$DELETE_PREBUILT_IMAGE" "DELETE_PREBUILT_IMAGE")"
|
|
||||||
RUN_JENKINS_BUILDER="$(normalize_on_off "$RUN_JENKINS_BUILDER" "RUN_JENKINS_BUILDER")"
|
|
||||||
RUN_COVERAGE="$(normalize_on_off "$RUN_COVERAGE" "RUN_COVERAGE")"
|
|
||||||
|
|
||||||
if [[ "${RUN_COVERAGE}" == "ON" && "${RUN_JENKINS_BUILDER}" == "ON" ]]; then
|
|
||||||
die "--run-coverage is mutually exclusive with --run-jenkins-builder"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Default for the Docker image name
|
|
||||||
DOCKER_IMAGE="${DOCKER_IMAGE:-legatus-qt6:1.0}"
|
|
||||||
|
|
||||||
# Export variables for Docker container
|
|
||||||
export RELEASE_BUILD RUN_CTEST BUILD_PREBUILT_IMAGE DELETE_PREBUILT_IMAGE DOCKER_IMAGE RUN_JENKINS_BUILDER PACKAGE_OUTPUT_DIR RUN_COVERAGE COVERAGE_OUTPUT_DIR LTS_VERSION PROJECT GUEZ_MODE BUILD_NUMBER BUILD_TAG
|
|
||||||
|
|
||||||
require_non_empty "${DOCKER_IMAGE}" "DOCKER_IMAGE"
|
|
||||||
|
|
||||||
if [[ "${DELETE_PREBUILT_IMAGE}" == "ON" ]]; then
|
|
||||||
delete_prebuilt_image "${DOCKER_IMAGE}"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
require_non_empty "${MIGRATE_PIPELINE_ROOT:-}" "MIGRATE_PIPELINE_ROOT"
|
|
||||||
require_directory "${MIGRATE_PIPELINE_ROOT}" "MIGRATE_PIPELINE_ROOT"
|
|
||||||
|
|
||||||
WORKSPACE_ROOT_HOST="${MIGRATE_PIPELINE_ROOT}"
|
|
||||||
PROJECT_DIR_HOST="${WORKSPACE_ROOT_HOST}/qt-migration-legatus/qt6-after/qt6-migrated-legatus"
|
|
||||||
|
|
||||||
require_directory "${PROJECT_DIR_HOST}" "Project directory"
|
|
||||||
|
|
||||||
log_info "RELEASE_BUILD=${RELEASE_BUILD}"
|
|
||||||
log_info "RUN_CTEST=${RUN_CTEST}"
|
|
||||||
log_info "BUILD_PREBUILT_IMAGE=${BUILD_PREBUILT_IMAGE}"
|
|
||||||
log_info "DELETE_PREBUILT_IMAGE=${DELETE_PREBUILT_IMAGE}"
|
|
||||||
log_info "DOCKER_IMAGE=${DOCKER_IMAGE}"
|
|
||||||
log_info "RUN_JENKINS_BUILDER=${RUN_JENKINS_BUILDER}"
|
|
||||||
log_info "PACKAGE_OUTPUT_DIR=${PACKAGE_OUTPUT_DIR}"
|
|
||||||
log_info "RUN_COVERAGE=${RUN_COVERAGE}"
|
|
||||||
log_info "COVERAGE_OUTPUT_DIR=${COVERAGE_OUTPUT_DIR}"
|
|
||||||
log_info "LTS_VERSION=${LTS_VERSION}"
|
|
||||||
log_info "PROJECT=${PROJECT}"
|
|
||||||
log_info "GUEZ_MODE=${GUEZ_MODE}"
|
|
||||||
log_info "BUILD_NUMBER=${BUILD_NUMBER}"
|
|
||||||
log_info "BUILD_TAG=${BUILD_TAG}"
|
|
||||||
log_info "MIGRATE_PIPELINE_ROOT=${MIGRATE_PIPELINE_ROOT}"
|
|
||||||
log_info "PROJECT_DIR_HOST=${PROJECT_DIR_HOST}"
|
|
||||||
|
|
||||||
if [[ "${BUILD_PREBUILT_IMAGE}" == "ON" ]]; then
|
|
||||||
build_prebuilt_image "${DOCKER_IMAGE}"
|
|
||||||
|
|
||||||
log_info "Prebuilt image was built successfully."
|
|
||||||
log_info "To run the build with it, run:"
|
|
||||||
printf ' ./new_docker_build.sh --docker-image %q\n' "${DOCKER_IMAGE}"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
RELEASE_BUILD_TARGETS_STRING="$(join_by ' ' "${RELEASE_BUILD_TARGETS[@]}")"
|
|
||||||
|
|
||||||
HOST_TEMP_DIR="$(mktemp -d)"
|
|
||||||
CONTAINER_SCRIPT_HOST="${HOST_TEMP_DIR}/run-build-inside-container.sh"
|
|
||||||
cleanup_all() {
|
|
||||||
cleanup_temp_dir "${HOST_TEMP_DIR}"
|
|
||||||
}
|
|
||||||
trap cleanup_all EXIT
|
|
||||||
|
|
||||||
cat > "${CONTAINER_SCRIPT_HOST}" <<'EOF'
|
|
||||||
#!/usr/bin/env bash
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
# Fixed configuration for the release validation-scope branch
|
|
||||||
RELEASE_BUILD="${RELEASE_BUILD:-ON}"
|
|
||||||
RUN_CTEST="${RUN_CTEST:-ON}"
|
|
||||||
# Packaging variables
|
|
||||||
RUN_JENKINS_BUILDER="${RUN_JENKINS_BUILDER:-OFF}"
|
|
||||||
RUN_COVERAGE="${RUN_COVERAGE:-OFF}"
|
|
||||||
LTS_VERSION="${LTS_VERSION:-1.0}"
|
|
||||||
PROJECT="${PROJECT:-guez}"
|
|
||||||
GUEZ_MODE="${GUEZ_MODE:-ON}"
|
|
||||||
BUILD_NUMBER="${BUILD_NUMBER:-1}"
|
|
||||||
BUILD_TAG="${BUILD_TAG:-manual-build}"
|
|
||||||
RELEASE_BUILD_TARGETS="${RELEASE_BUILD_TARGETS:-}"
|
|
||||||
QT_VERSION="${QT_VERSION:-6.10.2}"
|
|
||||||
QT_ARCH="${QT_ARCH:-linux_gcc_64}"
|
|
||||||
QT_ARCH_DIR="${QT_ARCH_DIR:-gcc_64}"
|
|
||||||
QT_BASE_DIR="${QT_BASE_DIR:-/opt/Qt}"
|
|
||||||
|
|
||||||
log_info() {
|
|
||||||
printf 'INFO: %s\n' "$*"
|
|
||||||
}
|
|
||||||
|
|
||||||
log_error() {
|
|
||||||
printf 'ERROR: %s\n' "$*" >&2
|
|
||||||
}
|
|
||||||
|
|
||||||
log_info "Using prebuilt Docker image: all build dependencies are baked in"
|
|
||||||
|
|
||||||
export QT_QPA_PLATFORM=offscreen
|
|
||||||
|
|
||||||
cd /workspace/qt-migration-legatus/qt6-after/qt6-migrated-legatus
|
|
||||||
|
|
||||||
rm -rf build4
|
|
||||||
mkdir -p build4
|
|
||||||
cd build4
|
|
||||||
|
|
||||||
COV_CMAKE_ARGS=()
|
|
||||||
if [[ "${RUN_COVERAGE}" == "ON" ]]; then
|
|
||||||
COV_CMAKE_ARGS=(
|
|
||||||
"-DCMAKE_C_FLAGS_RELEASE=-O0 -g --coverage -DNDEBUG -fPIC"
|
|
||||||
"-DCMAKE_CXX_FLAGS_RELEASE=-O0 -g --coverage -DNDEBUG -fPIC"
|
|
||||||
"-DCMAKE_EXE_LINKER_FLAGS=--coverage"
|
|
||||||
"-DCMAKE_SHARED_LINKER_FLAGS=--coverage"
|
|
||||||
)
|
|
||||||
fi
|
|
||||||
cmake .. \
|
|
||||||
-DBUILD_TESTING=ON \
|
|
||||||
-DRELEASE_BUILD="${RELEASE_BUILD}" \
|
|
||||||
-DCMAKE_CXX_STANDARD=17 \
|
|
||||||
-DCMAKE_BUILD_TYPE=Release \
|
|
||||||
-DCMAKE_PREFIX_PATH="${QT_BASE_DIR}/${QT_VERSION}/${QT_ARCH_DIR}:/usr/local" \
|
|
||||||
"${COV_CMAKE_ARGS[@]}"
|
|
||||||
|
|
||||||
read -r -a RELEASE_TARGETS_ARRAY <<< "${RELEASE_BUILD_TARGETS}"
|
|
||||||
|
|
||||||
log_info "Building release scope targets: ${RELEASE_TARGETS_ARRAY[*]}"
|
|
||||||
make -j8 "${RELEASE_TARGETS_ARRAY[@]}" 2>&1 | tee release_build.log
|
|
||||||
|
|
||||||
if [[ "${RUN_CTEST}" == "ON" ]]; then
|
|
||||||
log_info "Running CTest"
|
|
||||||
ctest --test-dir . --output-on-failure || CTEST_RESULT=$?
|
|
||||||
if [[ "${CTEST_RESULT:-0}" -ne 0 ]]; then
|
|
||||||
log_info "CTest completed with failures (exit code: ${CTEST_RESULT})"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
log_info "Skipping CTest"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ "${RUN_COVERAGE}" == "ON" ]]; then
|
|
||||||
log_info "=== Code coverage (lcov) ==="
|
|
||||||
COVOUT=/workspace/coverage-out
|
|
||||||
SRCROOT=/workspace/qt-migration-legatus/qt6-after/qt6-migrated-legatus
|
|
||||||
mkdir -p "${COVOUT}"
|
|
||||||
|
|
||||||
COV_IGNORE=(--ignore-errors mismatch,inconsistent,unused)
|
|
||||||
lcov --capture --directory . --external "${COV_IGNORE[@]}" \
|
|
||||||
--rc branch_coverage=1 \
|
|
||||||
--output-file "${COVOUT}/raw.info"
|
|
||||||
lcov --extract "${COVOUT}/raw.info" \
|
|
||||||
"${SRCROOT}/TetraIF/*" \
|
|
||||||
"${SRCROOT}/Z/src/*" \
|
|
||||||
"${SRCROOT}/Lts/Common/*" \
|
|
||||||
"${SRCROOT}/Lts/Proxies/TrainingAreaBase/*" \
|
|
||||||
"${COV_IGNORE[@]}" \
|
|
||||||
--rc branch_coverage=1 \
|
|
||||||
--output-file "${COVOUT}/scoped.info"
|
|
||||||
lcov --remove "${COVOUT}/scoped.info" \
|
|
||||||
"*/unit-test/*" \
|
|
||||||
"*CommonUnitTestsPlaceholder*" \
|
|
||||||
"*/UnitTests/*" \
|
|
||||||
"*/tests/*" \
|
|
||||||
"*/test_*" \
|
|
||||||
"*_test.cpp" \
|
|
||||||
"*_test.h" \
|
|
||||||
"*_unit_test*" \
|
|
||||||
"${COV_IGNORE[@]}" \
|
|
||||||
--rc branch_coverage=1 \
|
|
||||||
--output-file "${COVOUT}/coverage.info"
|
|
||||||
lcov --summary "${COVOUT}/coverage.info" "${COV_IGNORE[@]}" --rc branch_coverage=1 \
|
|
||||||
> "${COVOUT}/coverage_summary.txt"
|
|
||||||
genhtml "${COVOUT}/coverage.info" \
|
|
||||||
--output-directory "${COVOUT}/html" \
|
|
||||||
"${COV_IGNORE[@]}" \
|
|
||||||
--branch-coverage --legend \
|
|
||||||
--rc branch_coverage=1
|
|
||||||
log_info "Coverage report written to ${COVOUT} (host: ${COVERAGE_OUTPUT_DIR})"
|
|
||||||
cat "${COVOUT}/coverage_summary.txt"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# DEB package production with the in-tree rpmbuild script
|
|
||||||
if [[ "${RUN_JENKINS_BUILDER}" == "ON" ]]; then
|
|
||||||
log_info "=== DEB Package Production (in-tree rpmbuild) ==="
|
|
||||||
|
|
||||||
OS_VERSION=$(cat /etc/os-release | grep "^VERSION_ID=" | cut -d'"' -f2)
|
|
||||||
STAGE_DIR=/workspace/deb_stage
|
|
||||||
STAGED_SOURCE_DIR="${STAGE_DIR}/qt-migration-legatus/qt6-after/qt6-migrated-legatus"
|
|
||||||
|
|
||||||
log_info "Staging workspace to ${STAGE_DIR}"
|
|
||||||
rm -rf "${STAGE_DIR}"
|
|
||||||
mkdir -p "${STAGE_DIR}"
|
|
||||||
tar --exclude='./rpms' --exclude='./.git' --exclude='./build' \
|
|
||||||
--exclude='./deb_build_tmp' --exclude='./deb_stage' --exclude='./packages-out' \
|
|
||||||
-cf - -C /workspace . | tar -xf - -C "${STAGE_DIR}"
|
|
||||||
|
|
||||||
if [[ ! -f "${STAGED_SOURCE_DIR}/CMakeLists.txt" || ! -f "${STAGED_SOURCE_DIR}/rpmbuild/make_rpm_ubuntu26.py" ]]; then
|
|
||||||
log_error "Staged source incomplete under ${STAGED_SOURCE_DIR} (CMakeLists.txt or rpmbuild/make_rpm_ubuntu26.py missing)"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
log_info "Running ${STAGED_SOURCE_DIR}/rpmbuild/make_rpm_ubuntu26.py with:"
|
|
||||||
log_info " PROJECT=${PROJECT}"
|
|
||||||
log_info " OS_VERSION=${OS_VERSION}"
|
|
||||||
log_info " LTS_VERSION=${LTS_VERSION}"
|
|
||||||
log_info " GUEZ_MODE=${GUEZ_MODE}"
|
|
||||||
log_info " BUILD_NUMBER=${BUILD_NUMBER}"
|
|
||||||
log_info " BUILD_TAG=${BUILD_TAG}"
|
|
||||||
|
|
||||||
cd "${STAGED_SOURCE_DIR}/rpmbuild"
|
|
||||||
if python3 make_rpm_ubuntu26.py -c LTS \
|
|
||||||
--project_name "${PROJECT}" \
|
|
||||||
--version "${LTS_VERSION}" \
|
|
||||||
--output_dir "/workspace/rpms/${PROJECT}/${OS_VERSION}/" \
|
|
||||||
--source_dir "${STAGED_SOURCE_DIR}" \
|
|
||||||
--cmake_build_flags "-DUSE_IPO=ON -DUSE_UNITY_BUILD=ON -DGUEZ_MODE=${GUEZ_MODE} -DBUILD_WLS=ON -DPostgreSQL_TYPE_INCLUDE_DIR=/usr/include/postgresql/ -DRELEASE_BUILD=ON" \
|
|
||||||
--build_number "${BUILD_NUMBER}" \
|
|
||||||
--release_scope; then
|
|
||||||
log_info "Package build completed successfully"
|
|
||||||
else
|
|
||||||
log_error "Package build failed (exit code: $?)"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Copy produced DEB packages to the packages-out
|
|
||||||
DEST_DIR=/workspace/packages-out
|
|
||||||
mkdir -p "${DEST_DIR}"
|
|
||||||
shopt -s nullglob
|
|
||||||
for deb in "/workspace/rpms/${PROJECT}/${OS_VERSION}/"*.deb; do
|
|
||||||
base="$(basename "${deb}")"
|
|
||||||
if [[ -e "${DEST_DIR}/${base}" ]] &&
|
|
||||||
[[ "$(stat -c '%d:%i' "${deb}")" == "$(stat -c '%d:%i' "${DEST_DIR}/${base}")" ]]; then
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
cp -f "${deb}" "${DEST_DIR}/"
|
|
||||||
done
|
|
||||||
shopt -u nullglob
|
|
||||||
log_info "DEB packages available in ${DEST_DIR} (host: ${PACKAGE_OUTPUT_DIR:-unknown}):"
|
|
||||||
ls -lh "${DEST_DIR}/"
|
|
||||||
else
|
|
||||||
log_info "Skipping DEB package production"
|
|
||||||
fi
|
|
||||||
EOF
|
|
||||||
|
|
||||||
chmod +x "${CONTAINER_SCRIPT_HOST}"
|
|
||||||
|
|
||||||
docker run --rm \
|
|
||||||
-e MIGRATE_PIPELINE_ROOT \
|
|
||||||
-e LANG \
|
|
||||||
-e LC_ALL \
|
|
||||||
-e RELEASE_BUILD \
|
|
||||||
-e RUN_CTEST \
|
|
||||||
-e RUN_JENKINS_BUILDER \
|
|
||||||
-e RUN_COVERAGE \
|
|
||||||
-e COVERAGE_OUTPUT_DIR \
|
|
||||||
-e PACKAGE_OUTPUT_DIR \
|
|
||||||
-e LTS_VERSION \
|
|
||||||
-e PROJECT \
|
|
||||||
-e GUEZ_MODE \
|
|
||||||
-e BUILD_NUMBER \
|
|
||||||
-e BUILD_TAG \
|
|
||||||
-e QT_VERSION \
|
|
||||||
-e QT_ARCH \
|
|
||||||
-e QT_ARCH_DIR \
|
|
||||||
-e QT_BASE_DIR \
|
|
||||||
-e RELEASE_BUILD_TARGETS="${RELEASE_BUILD_TARGETS_STRING}" \
|
|
||||||
-v "${WORKSPACE_ROOT_HOST}:/workspace" \
|
|
||||||
-v "${MIGRATE_PIPELINE_ROOT}/external:/workspace/external:ro" \
|
|
||||||
-v "${CONTAINER_SCRIPT_HOST}:/tmp/run-build-inside-container.sh:ro" \
|
|
||||||
-v "${PACKAGE_OUTPUT_DIR}:/workspace/packages-out" \
|
|
||||||
-v "${COVERAGE_OUTPUT_DIR}:/workspace/coverage-out" \
|
|
||||||
"${DOCKER_IMAGE}" \
|
|
||||||
bash /tmp/run-build-inside-container.sh
|
|
||||||
@@ -1,526 +0,0 @@
|
|||||||
#!/usr/bin/python3
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""
|
|
||||||
DEB package builder for Ubuntu 26.04 - Qt6 Release
|
|
||||||
Creates 5 separate DEB packages as per customer requirements:
|
|
||||||
1. qt6-release-runtime - binaries and libraries from S
|
|
||||||
2. qt6-release-sources - Qt6 C++ sources from S
|
|
||||||
3. qt6-release-ctest-runtime - CTest executables
|
|
||||||
4. qt6-release-ctest-sources - CTest source files
|
|
||||||
5. qt6-release-build-pipeline - Dockerfiles, build scripts, CI/CD files
|
|
||||||
"""
|
|
||||||
|
|
||||||
import argparse
|
|
||||||
import fnmatch
|
|
||||||
import os
|
|
||||||
import shutil
|
|
||||||
import subprocess
|
|
||||||
import sys
|
|
||||||
from email.utils import formatdate
|
|
||||||
|
|
||||||
SKIP_DIRS = {'build', 'cmake-build-debug', 'cmake-build-release', 'deb_build_tmp'}
|
|
||||||
SOURCE_EXTENSIONS = ('.cpp', '.h', '.hpp', '.cc', '.cxx', '.hxx')
|
|
||||||
PIPELINE_FILES = [
|
|
||||||
"new_docker_build.sh",
|
|
||||||
"Dockerfile",
|
|
||||||
"jenkins-ci-rme/Jenkinsfile",
|
|
||||||
"jenkins-ci-rme/jenkins_builder_ubuntu26.sh",
|
|
||||||
"jenkins-ci-rme/jenkins_publisher_ubuntu26.sh",
|
|
||||||
"jenkins-ci-rme/release-16-10-2026.sh",
|
|
||||||
"rpmbuild/make_rpm_ubuntu26.py",
|
|
||||||
"CMakeLists.txt",
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
def verbose():
|
|
||||||
verb = os.getenv("EMERGE_VERBOSE")
|
|
||||||
if verb is not None and verb.isdigit() and int(verb) > 0:
|
|
||||||
return int(verb)
|
|
||||||
return 0
|
|
||||||
|
|
||||||
|
|
||||||
def debug(message):
|
|
||||||
if verbose() >= 1:
|
|
||||||
print(f"debug: {message}")
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
def info(message):
|
|
||||||
print(f"info: {message}")
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
def warning(message):
|
|
||||||
print(f"warning: {message}")
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
def error(message):
|
|
||||||
die(message)
|
|
||||||
|
|
||||||
|
|
||||||
def die(message):
|
|
||||||
print(f"emerge fatal error: {message}", file=sys.stderr)
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
|
|
||||||
def run(cmd, label, env=None):
|
|
||||||
"""Run a shell command, print its output and die on failure."""
|
|
||||||
debug(f"Executing: {cmd}")
|
|
||||||
ret = subprocess.run(cmd, shell=True, env=env, capture_output=True, text=True)
|
|
||||||
if ret.returncode != 0:
|
|
||||||
print(ret.stdout)
|
|
||||||
print(ret.stderr)
|
|
||||||
die(f"{label} with code {ret.returncode}")
|
|
||||||
|
|
||||||
|
|
||||||
def remove_directory(path):
|
|
||||||
if os.path.exists(path):
|
|
||||||
shutil.rmtree(path)
|
|
||||||
|
|
||||||
|
|
||||||
def is_dds_file(filepath):
|
|
||||||
"""True if the path is DDS-related and must be excluded."""
|
|
||||||
return 'dds' in filepath.lower()
|
|
||||||
|
|
||||||
|
|
||||||
def prune_dirs(dirs, root, file_filter):
|
|
||||||
"""Prune hidden/build dirs in-place (and dirs matching file_filter)."""
|
|
||||||
dirs[:] = [d for d in dirs
|
|
||||||
if not d.startswith('.')
|
|
||||||
and d not in SKIP_DIRS
|
|
||||||
and (file_filter is None or not file_filter(os.path.join(root, d)))]
|
|
||||||
|
|
||||||
|
|
||||||
def copy_src_dir_to_dest_dir(src_dir, dest_dir, file_filter=None):
|
|
||||||
"""Copy the source tree, skipping hidden/build dirs and filtered files."""
|
|
||||||
os.makedirs(dest_dir, exist_ok=True)
|
|
||||||
for root, dirs, files in os.walk(src_dir):
|
|
||||||
prune_dirs(dirs, root, file_filter)
|
|
||||||
for file in files:
|
|
||||||
src_file = os.path.join(root, file)
|
|
||||||
if file_filter and file_filter(src_file):
|
|
||||||
continue
|
|
||||||
dest_file = os.path.join(dest_dir, os.path.relpath(src_file, src_dir))
|
|
||||||
os.makedirs(os.path.dirname(dest_file), exist_ok=True)
|
|
||||||
shutil.copy2(src_file, dest_file)
|
|
||||||
|
|
||||||
|
|
||||||
def find_test_module_source(pkg_dir, test_name, release_dirs):
|
|
||||||
"""Module dir (relative to pkg_dir) whose CMakeLists defines test_name, or None."""
|
|
||||||
for rel_dir in release_dirs:
|
|
||||||
module_dir = os.path.join(pkg_dir, rel_dir)
|
|
||||||
if not os.path.exists(module_dir):
|
|
||||||
continue
|
|
||||||
for root, dirs, files in os.walk(module_dir):
|
|
||||||
prune_dirs(dirs, root, None)
|
|
||||||
if 'CMakeLists.txt' not in files:
|
|
||||||
continue
|
|
||||||
try:
|
|
||||||
with open(os.path.join(root, 'CMakeLists.txt')) as f:
|
|
||||||
content = f.read()
|
|
||||||
except Exception:
|
|
||||||
continue
|
|
||||||
if f'ADD_EXECUTABLE({test_name}' in content or f'ADD_TEST(NAME {test_name}' in content:
|
|
||||||
return os.path.relpath(root, pkg_dir)
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def find_test_executables(pkg_dir, release_dirs):
|
|
||||||
"""(executable, module) pairs for the test executables in build4/bin/."""
|
|
||||||
test_executables = []
|
|
||||||
build_bin_dir = os.path.join(pkg_dir, "build4", "bin")
|
|
||||||
if not os.path.exists(build_bin_dir):
|
|
||||||
warning(f"Build bin directory not found: {build_bin_dir}")
|
|
||||||
return test_executables
|
|
||||||
for filename in os.listdir(build_bin_dir):
|
|
||||||
file_path = os.path.join(build_bin_dir, filename)
|
|
||||||
if not (os.path.isfile(file_path) and os.access(file_path, os.X_OK)):
|
|
||||||
continue
|
|
||||||
if 'test' not in filename.lower():
|
|
||||||
continue
|
|
||||||
module_path = find_test_module_source(pkg_dir, filename, release_dirs)
|
|
||||||
if module_path:
|
|
||||||
test_executables.append((file_path, module_path))
|
|
||||||
debug(f" Found test executable: {filename} from {module_path}")
|
|
||||||
else:
|
|
||||||
debug(f" Skipping test executable (no module found): {filename}")
|
|
||||||
return test_executables
|
|
||||||
|
|
||||||
|
|
||||||
def find_test_sources(pkg_dir, release_dirs):
|
|
||||||
"""Relative paths of test source files (name containing 'test', .cpp/.h)."""
|
|
||||||
test_sources = []
|
|
||||||
for rel_dir in release_dirs:
|
|
||||||
module_dir = os.path.join(pkg_dir, rel_dir)
|
|
||||||
if not os.path.exists(module_dir):
|
|
||||||
continue
|
|
||||||
for root, dirs, files in os.walk(module_dir):
|
|
||||||
prune_dirs(dirs, root, None)
|
|
||||||
for filename in files:
|
|
||||||
if 'test' in filename.lower() and filename.endswith(('.cpp', '.h')):
|
|
||||||
file_path = os.path.join(root, filename)
|
|
||||||
rel_path = os.path.relpath(file_path, pkg_dir)
|
|
||||||
test_sources.append(rel_path)
|
|
||||||
debug(f" Found test source: {rel_path}")
|
|
||||||
return test_sources
|
|
||||||
|
|
||||||
|
|
||||||
def write_deb_file(deb_dir, name, content, executable=False):
|
|
||||||
"""Write a debian/* file and log its creation."""
|
|
||||||
path = os.path.join(deb_dir, name)
|
|
||||||
with open(path, "w") as f:
|
|
||||||
f.write(content)
|
|
||||||
if executable:
|
|
||||||
os.chmod(path, 0o755)
|
|
||||||
info(f"Created {path}")
|
|
||||||
|
|
||||||
|
|
||||||
def create_debian_control(deb_dir, package_name, version, build_number, description,
|
|
||||||
depends="", section="devel"):
|
|
||||||
write_deb_file(deb_dir, "control", f"""Source: {package_name}
|
|
||||||
Section: {section}
|
|
||||||
Priority: optional
|
|
||||||
Maintainer: Legatus Team <team@legatus.example.com>
|
|
||||||
Build-Depends: debhelper (>= 13), cmake, qt6-base-dev, qt6-tools-dev
|
|
||||||
Standards-Version: 4.6.0
|
|
||||||
|
|
||||||
Package: {package_name}
|
|
||||||
Architecture: any
|
|
||||||
Depends: ${{shlibs:Depends}}, ${{misc:Depends}}{", " + depends if depends else ""}
|
|
||||||
Description: {description}
|
|
||||||
Legatus Qt6 Release Package
|
|
||||||
This package is part of the Legatus Qt6 migration release.
|
|
||||||
""")
|
|
||||||
|
|
||||||
|
|
||||||
def create_debian_changelog(deb_dir, package_name, version, build_number):
|
|
||||||
write_deb_file(deb_dir, "changelog", f"""{package_name} ({version}-{build_number}) unstable; urgency=medium
|
|
||||||
|
|
||||||
* Qt6 Release Build
|
|
||||||
|
|
||||||
-- Legatus Team <team@legatus.example.com> {formatdate(localtime=True)}
|
|
||||||
""")
|
|
||||||
|
|
||||||
|
|
||||||
def create_debian_rules(deb_dir, cmake_flags="", skip_tests=False):
|
|
||||||
test_override = """
|
|
||||||
override_dh_auto_test:
|
|
||||||
# Tests skipped for this package type
|
|
||||||
""" if skip_tests else ""
|
|
||||||
write_deb_file(deb_dir, "rules", f"""#!/usr/bin/make -f
|
|
||||||
%:
|
|
||||||
dh $@ --buildsystem=cmake
|
|
||||||
|
|
||||||
override_dh_auto_configure:
|
|
||||||
dh_auto_configure -- -DCMAKE_BUILD_TYPE=Release {cmake_flags}
|
|
||||||
|
|
||||||
override_dh_auto_build:
|
|
||||||
dh_auto_build --parallel
|
|
||||||
|
|
||||||
override_dh_auto_install:
|
|
||||||
dh_auto_install --destdir=debian/tmp
|
|
||||||
{test_override}""", executable=True)
|
|
||||||
|
|
||||||
|
|
||||||
def create_debian_rules_nobuild(deb_dir, skip_shlibdeps=False):
|
|
||||||
content = """#!/usr/bin/make -f
|
|
||||||
%:
|
|
||||||
dh $@
|
|
||||||
|
|
||||||
override_dh_auto_build:
|
|
||||||
# No build step needed - pre-built files only
|
|
||||||
|
|
||||||
override_dh_auto_configure:
|
|
||||||
# No configure step needed - pre-built files only
|
|
||||||
|
|
||||||
override_dh_auto_install:
|
|
||||||
dh_auto_install
|
|
||||||
"""
|
|
||||||
if skip_shlibdeps:
|
|
||||||
content += """
|
|
||||||
override_dh_shlibdeps:
|
|
||||||
# Skip shlibdeps for test executables - Qt6 deps are external system packages
|
|
||||||
"""
|
|
||||||
write_deb_file(deb_dir, "rules", content, executable=True)
|
|
||||||
|
|
||||||
|
|
||||||
def create_debian_install(deb_dir, install_lines):
|
|
||||||
install_file = os.path.join(deb_dir, "install")
|
|
||||||
with open(install_file, "w") as f:
|
|
||||||
for line in install_lines:
|
|
||||||
f.write(line + "\n")
|
|
||||||
info(f"Created {install_file} with {len(install_lines)} entries")
|
|
||||||
|
|
||||||
|
|
||||||
def create_manifest(output_dir, package_name, pkg_dir):
|
|
||||||
"""Write the manifest of package contents (from the DEB, or the pkg dir)."""
|
|
||||||
manifest_file = os.path.join(output_dir, "manifests", f"{package_name}.manifest")
|
|
||||||
os.makedirs(os.path.dirname(manifest_file), exist_ok=True)
|
|
||||||
deb_file = next((os.path.join(output_dir, f) for f in os.listdir(output_dir)
|
|
||||||
if f.startswith(package_name) and f.endswith(".deb")), None)
|
|
||||||
manifest_lines = []
|
|
||||||
if deb_file and os.path.exists(deb_file):
|
|
||||||
result = subprocess.run(["dpkg-deb", "--contents", deb_file],
|
|
||||||
capture_output=True, text=True)
|
|
||||||
if result.returncode == 0:
|
|
||||||
# dpkg-deb --contents: "-rw-r--r-- root/root 1234 2024-01-01 00:00 ./path"
|
|
||||||
for line in result.stdout.strip().split("\n"):
|
|
||||||
parts = line.split()
|
|
||||||
if len(parts) >= 6:
|
|
||||||
file_path = parts[-1]
|
|
||||||
if file_path.startswith("./"):
|
|
||||||
file_path = file_path[2:]
|
|
||||||
elif file_path.startswith("/"):
|
|
||||||
file_path = file_path[1:]
|
|
||||||
if file_path:
|
|
||||||
manifest_lines.append(file_path)
|
|
||||||
elif os.path.exists(pkg_dir):
|
|
||||||
info(f"Warning: DEB file not found for {package_name}, scanning directory instead")
|
|
||||||
for root, dirs, files in os.walk(pkg_dir):
|
|
||||||
for file in files:
|
|
||||||
manifest_lines.append(os.path.relpath(os.path.join(root, file), pkg_dir))
|
|
||||||
manifest_lines.sort()
|
|
||||||
with open(manifest_file, "w") as f:
|
|
||||||
for line in manifest_lines:
|
|
||||||
f.write(line + "\n")
|
|
||||||
info(f"Created manifest: {manifest_file} ({len(manifest_lines)} entries)")
|
|
||||||
return manifest_lines
|
|
||||||
|
|
||||||
|
|
||||||
def validate_package_contents(package_name, manifest_lines, allowed_patterns, forbidden_patterns=None):
|
|
||||||
"""Validate package contents against the allowlist/forbidden list."""
|
|
||||||
errors = []
|
|
||||||
warnings = []
|
|
||||||
for file_path in manifest_lines:
|
|
||||||
if file_path.endswith('/'):
|
|
||||||
continue
|
|
||||||
if forbidden_patterns:
|
|
||||||
for pattern in forbidden_patterns:
|
|
||||||
if fnmatch.fnmatch(file_path, pattern):
|
|
||||||
errors.append(f"FORBIDDEN file in {package_name}: {file_path} (matches {pattern})")
|
|
||||||
allowed = bool(allowed_patterns) and any(fnmatch.fnmatch(file_path, p) for p in allowed_patterns)
|
|
||||||
if not allowed and allowed_patterns:
|
|
||||||
warnings.append(f"Unexpected file in {package_name}: {file_path}")
|
|
||||||
for err in errors:
|
|
||||||
error(f"Validation error: {err}")
|
|
||||||
if errors:
|
|
||||||
return False
|
|
||||||
for warn in warnings:
|
|
||||||
warning(f"Validation warning: {warn}")
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
def build_deb(pkg_name, pkg_dir, output_dir, version, build_number,
|
|
||||||
cmake_flags="", nobuild=False, skip_tests=False, skip_shlibdeps=False,
|
|
||||||
install_lines=None, description="", section="devel", depends=""):
|
|
||||||
"""Build one DEB package (with or without a cmake build) and move its artifacts."""
|
|
||||||
info(f"Building DEB package {'(no-build): ' if nobuild else ''}{pkg_name}")
|
|
||||||
deb_dir = os.path.join(pkg_dir, "debian")
|
|
||||||
os.makedirs(deb_dir)
|
|
||||||
create_debian_control(deb_dir, pkg_name, version, build_number, description, depends, section)
|
|
||||||
create_debian_changelog(deb_dir, pkg_name, version, build_number)
|
|
||||||
if nobuild:
|
|
||||||
create_debian_rules_nobuild(deb_dir, skip_shlibdeps=skip_shlibdeps)
|
|
||||||
else:
|
|
||||||
create_debian_rules(deb_dir, cmake_flags, skip_tests)
|
|
||||||
os.makedirs(os.path.join(deb_dir, "source"))
|
|
||||||
with open(os.path.join(deb_dir, "source", "format"), "w") as f:
|
|
||||||
f.write("3.0 (quilt)\n")
|
|
||||||
with open(os.path.join(deb_dir, "compat"), "w") as f:
|
|
||||||
f.write("13\n")
|
|
||||||
if install_lines:
|
|
||||||
create_debian_install(deb_dir, install_lines)
|
|
||||||
|
|
||||||
info(f"Running debuild for {pkg_name}...")
|
|
||||||
os.chdir(pkg_dir)
|
|
||||||
env = os.environ.copy()
|
|
||||||
env["DEB_BUILD_OPTIONS"] = "parallel=$(nproc)"
|
|
||||||
run("debuild -us -uc -b", f"debuild failed for {pkg_name}", env=env)
|
|
||||||
|
|
||||||
parent_dir = os.path.dirname(pkg_dir)
|
|
||||||
for f in os.listdir(parent_dir):
|
|
||||||
if f.endswith((".deb", ".dsc", ".changes", ".buildinfo")):
|
|
||||||
src = os.path.join(parent_dir, f)
|
|
||||||
dst = os.path.join(output_dir, f)
|
|
||||||
if os.path.exists(dst):
|
|
||||||
os.remove(dst)
|
|
||||||
shutil.move(src, output_dir)
|
|
||||||
info(f"Moved {f} to {output_dir}")
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
def source_install_lines(pkg_dir, release_dirs):
|
|
||||||
lines = []
|
|
||||||
for rel_dir in release_dirs:
|
|
||||||
src_dir = os.path.join(pkg_dir, rel_dir)
|
|
||||||
if not os.path.exists(src_dir):
|
|
||||||
continue
|
|
||||||
for root, dirs, files in os.walk(src_dir):
|
|
||||||
dirs[:] = [d for d in dirs if not d.startswith('.')]
|
|
||||||
for file in files:
|
|
||||||
if os.path.splitext(file)[1].lower() in SOURCE_EXTENSIONS or file == "CMakeLists.txt":
|
|
||||||
rel_path = os.path.relpath(os.path.join(root, file), pkg_dir)
|
|
||||||
lines.append(f"{rel_path} {os.path.join('usr/src', os.path.dirname(rel_path))}/")
|
|
||||||
return lines
|
|
||||||
|
|
||||||
|
|
||||||
def ctest_runtime_install_lines(pkg_dir, release_dirs):
|
|
||||||
lines = []
|
|
||||||
for exe_path, module_path in find_test_executables(pkg_dir, release_dirs):
|
|
||||||
lines.append(f"{os.path.relpath(exe_path, pkg_dir)} usr/lib/ctest/")
|
|
||||||
info(f" Including test executable: {os.path.basename(exe_path)} from {module_path}")
|
|
||||||
for ctest_file in ("build4/CTestTestfile.cmake", "build4/DartConfiguration.tcl", "build4/Testing/TAG"):
|
|
||||||
if os.path.exists(os.path.join(pkg_dir, ctest_file)):
|
|
||||||
lines.append(f"{ctest_file} usr/lib/ctest/")
|
|
||||||
return lines
|
|
||||||
|
|
||||||
|
|
||||||
def test_sources_install_lines(pkg_dir, release_dirs):
|
|
||||||
return [f"{rel_path} {os.path.dirname(rel_path)}/" for rel_path in find_test_sources(pkg_dir, release_dirs)]
|
|
||||||
|
|
||||||
|
|
||||||
def pipeline_install_lines(pkg_dir):
|
|
||||||
lines = []
|
|
||||||
for pipeline_file in PIPELINE_FILES:
|
|
||||||
if os.path.exists(os.path.join(pkg_dir, pipeline_file)):
|
|
||||||
lines.append(f"{pipeline_file} {os.path.join('usr/src/pipeline', os.path.dirname(pipeline_file))}/")
|
|
||||||
info(f" Added pipeline file: {pipeline_file}")
|
|
||||||
return lines
|
|
||||||
|
|
||||||
|
|
||||||
def build_nobuild_package(name, source_dir, build_base, output_dir, version, build_number,
|
|
||||||
description, prepare, allowed_patterns, forbidden_patterns,
|
|
||||||
file_filter=None, skip_shlibdeps=False, section="devel"):
|
|
||||||
"""Stage the source tree, build a no-build DEB and validate its contents."""
|
|
||||||
info(f"\n=== Building {name} ===")
|
|
||||||
pkg_dir = os.path.join(build_base, f"{name}-{version}")
|
|
||||||
os.makedirs(pkg_dir)
|
|
||||||
copy_src_dir_to_dest_dir(source_dir, pkg_dir, file_filter=file_filter)
|
|
||||||
build_deb(pkg_name=name, pkg_dir=pkg_dir, output_dir=output_dir,
|
|
||||||
version=version, build_number=build_number, nobuild=True,
|
|
||||||
skip_shlibdeps=skip_shlibdeps, install_lines=prepare(pkg_dir),
|
|
||||||
description=description, section=section)
|
|
||||||
manifest = create_manifest(output_dir, name, pkg_dir)
|
|
||||||
validate_package_contents(name, manifest, allowed_patterns, forbidden_patterns)
|
|
||||||
|
|
||||||
|
|
||||||
def build_all_debs(source_dir, output_dir, version, build_number, cmake_flags):
|
|
||||||
"""Build the 5 DEB packages: build once from the source tree, then package."""
|
|
||||||
info("========================================")
|
|
||||||
info("Building 5 DEB packages for Qt6 Release")
|
|
||||||
info("========================================")
|
|
||||||
os.makedirs(output_dir, exist_ok=True)
|
|
||||||
os.makedirs(os.path.join(output_dir, "manifests"), exist_ok=True)
|
|
||||||
build_base = os.path.join(source_dir, "deb_build_tmp")
|
|
||||||
remove_directory(build_base)
|
|
||||||
os.makedirs(build_base)
|
|
||||||
release_dirs = ["TetraIF", "Z/src", "Lts/Common"]
|
|
||||||
|
|
||||||
# Step 1: build once from the full source tree
|
|
||||||
info("\n=== Step 1: Building from full source tree ===")
|
|
||||||
build_dir = os.path.join(source_dir, "build")
|
|
||||||
os.makedirs(build_dir, exist_ok=True)
|
|
||||||
os.chdir(build_dir)
|
|
||||||
info("Running CMake configuration...")
|
|
||||||
run(f"cmake -DCMAKE_BUILD_TYPE=Release {cmake_flags} ..", "CMake configuration failed")
|
|
||||||
info("Running build...")
|
|
||||||
run(f"make -j$(nproc)", "Build failed")
|
|
||||||
info("Build completed successfully")
|
|
||||||
|
|
||||||
# Package 1: qt6-release-runtime (binaries and libraries, built via debuild)
|
|
||||||
info("\n=== Building qt6-release-runtime ===")
|
|
||||||
pkg1_dir = os.path.join(build_base, f"qt6-release-runtime-{version}")
|
|
||||||
os.makedirs(pkg1_dir)
|
|
||||||
# FULL source tree (needed for debian/rules cmake reference)
|
|
||||||
copy_src_dir_to_dest_dir(source_dir, pkg1_dir)
|
|
||||||
# Install from all component install paths: ALL -> bin/, lib/ ; SV/ ; WS/
|
|
||||||
install_lines_1 = [
|
|
||||||
"usr/bin/* usr/bin/",
|
|
||||||
"usr/lib/*.so* usr/lib/",
|
|
||||||
"usr/SV/bin/* usr/bin/",
|
|
||||||
"usr/SV/lib/*.so* usr/lib/",
|
|
||||||
"usr/WS/bin/* usr/bin/",
|
|
||||||
"usr/WS/lib/*.so* usr/lib/",
|
|
||||||
]
|
|
||||||
build_deb(pkg_name="qt6-release-runtime", pkg_dir=pkg1_dir, output_dir=output_dir,
|
|
||||||
version=version, build_number=build_number, cmake_flags=cmake_flags,
|
|
||||||
skip_tests=True, install_lines=install_lines_1,
|
|
||||||
description="Qt6 Release Runtime - binaries and libraries from release scope S",
|
|
||||||
section="libs")
|
|
||||||
manifest_1 = create_manifest(output_dir, "qt6-release-runtime", pkg1_dir)
|
|
||||||
validate_package_contents("qt6-release-runtime", manifest_1,
|
|
||||||
allowed_patterns=["usr/bin/*", "usr/lib/*", "usr/SV/*", "usr/WS/*", "usr/share/doc/*", "debian/*"],
|
|
||||||
forbidden_patterns=["*.cpp", "*.h", "*.hpp", "tests/*", "jenkins/*", "Dockerfile*"])
|
|
||||||
|
|
||||||
# Package 2: qt6-release-sources (release-scope sources, DDS excluded)
|
|
||||||
build_nobuild_package(
|
|
||||||
"qt6-release-sources", source_dir, build_base, output_dir, version, build_number,
|
|
||||||
description="Qt6 Release Sources - C++ source files from release scope S",
|
|
||||||
prepare=lambda pkg_dir: source_install_lines(pkg_dir, release_dirs),
|
|
||||||
allowed_patterns=["usr/src/*", "usr/share/doc/*", "debian/*"],
|
|
||||||
forbidden_patterns=["build/*", "tests/*", "jenkins/*"],
|
|
||||||
file_filter=is_dds_file)
|
|
||||||
|
|
||||||
# Package 3: qt6-release-ctest-runtime (test executables from release scope)
|
|
||||||
build_nobuild_package(
|
|
||||||
"qt6-release-ctest-runtime", source_dir, build_base, output_dir, version, build_number,
|
|
||||||
description="Qt6 Release CTest Runtime - executable test programs from release scope",
|
|
||||||
prepare=lambda pkg_dir: ctest_runtime_install_lines(pkg_dir, release_dirs),
|
|
||||||
allowed_patterns=["usr/lib/ctest/*", "usr/share/doc/*", "debian/*"],
|
|
||||||
forbidden_patterns=["*.cpp", "*.h", "jenkins/*"],
|
|
||||||
skip_shlibdeps=True)
|
|
||||||
|
|
||||||
# Package 4: qt6-release-ctest-sources (test source files from release scope)
|
|
||||||
build_nobuild_package(
|
|
||||||
"qt6-release-ctest-sources", source_dir, build_base, output_dir, version, build_number,
|
|
||||||
description="Qt6 Release CTest Sources - test source files from release scope",
|
|
||||||
prepare=lambda pkg_dir: test_sources_install_lines(pkg_dir, release_dirs),
|
|
||||||
allowed_patterns=["Lts/*", "TetraIF/*", "Z/*", "usr/share/doc/*", "debian/*"],
|
|
||||||
forbidden_patterns=["build/*", "jenkins/*"])
|
|
||||||
|
|
||||||
# Package 5: qt6-release-build-pipeline (Docker, Jenkins, CMake, packaging scripts)
|
|
||||||
build_nobuild_package(
|
|
||||||
"qt6-release-build-pipeline", source_dir, build_base, output_dir, version, build_number,
|
|
||||||
description="Qt6 Release Build Pipeline - Docker, Jenkins, CMake, and packaging scripts",
|
|
||||||
prepare=pipeline_install_lines,
|
|
||||||
allowed_patterns=["usr/src/pipeline/*", "usr/share/doc/*", "debian/*"],
|
|
||||||
forbidden_patterns=["*.cpp", "*.h", "tests/*"])
|
|
||||||
|
|
||||||
# Cleanup
|
|
||||||
os.chdir(source_dir)
|
|
||||||
remove_directory(build_base)
|
|
||||||
|
|
||||||
info("\n========================================")
|
|
||||||
info(f"DEB package build completed: {output_dir}")
|
|
||||||
info("Generated packages:")
|
|
||||||
for f in os.listdir(output_dir):
|
|
||||||
if f.endswith(".deb"):
|
|
||||||
info(f" - {f}")
|
|
||||||
info("========================================")
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
parser = argparse.ArgumentParser(description="Build DEB packages for Legatus Qt6 Release")
|
|
||||||
parser.add_argument("-c", "--config", required=True, help="Config type (LTS)")
|
|
||||||
parser.add_argument("--project_name", required=True, help="Project name (qatar|ahtc|guez)")
|
|
||||||
parser.add_argument("--version", required=True, help="Version (Major.minor)")
|
|
||||||
parser.add_argument("--output_dir", required=True, help="Output directory for packages")
|
|
||||||
parser.add_argument("--source_dir", required=True, help="Source directory path")
|
|
||||||
parser.add_argument("--cmake_build_flags", default="", help="CMake build flags")
|
|
||||||
parser.add_argument("--build_number", default="1", help="Build number")
|
|
||||||
parser.add_argument("--release_scope", action="store_true", help="Only include release scope files")
|
|
||||||
|
|
||||||
args = parser.parse_args()
|
|
||||||
info(f"Building {args.config} package for {args.project_name} v{args.version}")
|
|
||||||
info(f"Output directory: {args.output_dir}")
|
|
||||||
info(f"Source directory: {args.source_dir}")
|
|
||||||
info(f"CMake flags: {args.cmake_build_flags}")
|
|
||||||
info(f"Release scope: {args.release_scope}")
|
|
||||||
build_all_debs(source_dir=args.source_dir, output_dir=args.output_dir,
|
|
||||||
version=args.version, build_number=args.build_number,
|
|
||||||
cmake_flags=args.cmake_build_flags)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
||||||
Reference in new issue
Block a user