Merge pull request 'Migrate Qt5/C++11 app to Qt6/C++23 and stabilize CI/pipeline setup' (#1) from bugfix/ci-pipeline-commissioning into main
qt-migration-copilot-demo/pipeline/head This commit looks good
qt-migration-copilot-demo/pipeline/head This commit looks good
Reviewed-on: #1
This commit was merged in pull request #1.
This commit is contained in:
commit
9e3c6eef2e
32 files changed
+1594
-64
No files matched your search
@@ -0,0 +1,5 @@
|
|||||||
|
tmp/
|
||||||
|
settings.local.json
|
||||||
|
metadata/
|
||||||
|
logs/
|
||||||
|
redactors/local/
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"enabled": true,
|
||||||
|
"telemetry": true,
|
||||||
|
"checkpoints": {
|
||||||
|
"primary": {
|
||||||
|
"type": "git-branch"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,4 +7,8 @@ export COPILOT_PROVIDER_BASE_URL="https://api.scaleway.ai/v1"
|
|||||||
export COPILOT_MODEL="${STRIX_LLM}"
|
export COPILOT_MODEL="${STRIX_LLM}"
|
||||||
|
|
||||||
export COPILOT_PROVIDER_MAX_PROMPT_TOKENS="32768"
|
export COPILOT_PROVIDER_MAX_PROMPT_TOKENS="32768"
|
||||||
export COPILOT_PROVIDER_MAX_OUTPUT_TOKENS="8192"
|
export COPILOT_PROVIDER_MAX_OUTPUT_TOKENS="8192"
|
||||||
|
|
||||||
|
export ENTIRE_TOKEN_STORE=file
|
||||||
|
export ENTIRE_TOKEN_STORE_PATH=$HOME/.config/entire/tokens.json
|
||||||
|
export ACCESSIBLE=1
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
# GitHub Copilot Repository Instructions: C++23 Modernization
|
||||||
|
|
||||||
|
## Context
|
||||||
|
- Language: C++
|
||||||
|
- Target standard: C++23
|
||||||
|
- Goal: modernize legacy C++11/14/17 code safely and incrementally
|
||||||
|
|
||||||
|
## Primary Rule
|
||||||
|
Preserve existing behavior unless functional changes are explicitly requested.
|
||||||
|
|
||||||
|
## Balanced Modernization Policy
|
||||||
|
- Prefer modern C++23 constructs when they clearly improve safety, readability, or maintainability.
|
||||||
|
- Keep refactors focused and reviewable; avoid broad rewrites unless requested.
|
||||||
|
- Prefer standard library solutions over custom or legacy patterns.
|
||||||
|
- Respect toolchain limitations, ABI-sensitive interfaces, and repository-local style.
|
||||||
|
|
||||||
|
## Preferred Modernizations
|
||||||
|
- Use `auto` where the type is obvious from the initializer; avoid it when it hides important type information.
|
||||||
|
- Prefer structured bindings over `std::tie` or manual pair/tuple access when clearer.
|
||||||
|
- Replace raw owning pointers and manual `delete` with RAII, usually `std::unique_ptr`.
|
||||||
|
- Use `std::make_unique` and `std::make_shared`; prefer `std::shared_ptr` only for real shared ownership.
|
||||||
|
- Use `std::string_view` for read-only string parameters only when lifetime safety is clear.
|
||||||
|
- Prefer `std::span` for non-owning contiguous ranges.
|
||||||
|
- Use `std::mdspan` only when multidimensional access is central and the change improves clarity or safety.
|
||||||
|
- Prefer `.contains()` over `find(...) != end()` where available and clearer.
|
||||||
|
- Prefer standard algorithms and ranges over manual loops when readability improves.
|
||||||
|
- Use `[[nodiscard]]` where ignoring the result is likely a bug.
|
||||||
|
- Prefer early returns over deeply nested control flow.
|
||||||
|
- Use `std::optional` monadic operations (`and_then`, `transform`, `or_else`) when they make the code simpler.
|
||||||
|
- Prefer `constexpr`, `if constexpr`, concepts, and `requires` over legacy `std::enable_if` / SFINAE where practical.
|
||||||
|
- Add `noexcept`, `override`, `final`, `= default`, and `= delete` where correct and useful.
|
||||||
|
- Prefer `enum class` over unscoped enums where practical.
|
||||||
|
- Prefer `std::print` / `std::println` for console output when supported by the project toolchain.
|
||||||
|
- Prefer typed `std::chrono` durations and `std::jthread` where appropriate.
|
||||||
|
|
||||||
|
## Avoid
|
||||||
|
- Do not modernize mechanically if readability becomes worse.
|
||||||
|
- Do not introduce unsupported C++23 features.
|
||||||
|
- Do not introduce dangling references, dangling `std::string_view`, or unclear ownership.
|
||||||
|
- Do not silently change ABI, object lifetime, exception behavior, or performance characteristics.
|
||||||
|
- Do not rewrite unrelated code.
|
||||||
|
|
||||||
|
## Expected Copilot Behavior
|
||||||
|
When making migration suggestions:
|
||||||
|
- produce small, focused updates
|
||||||
|
- explain non-trivial changes briefly
|
||||||
|
- call out risky refactors explicitly
|
||||||
|
- note compatibility or toolchain caveats
|
||||||
|
- leave optional follow-up improvements separate
|
||||||
|
|
||||||
|
## Preferred Output
|
||||||
|
Provide:
|
||||||
|
- updated code
|
||||||
|
- short rationale
|
||||||
|
- compatibility/toolchain caveats
|
||||||
|
- optional next modernization steps
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
{
|
||||||
|
"hooks": {
|
||||||
|
"agentStop": [
|
||||||
|
{
|
||||||
|
"type": "command",
|
||||||
|
"bash": "sh -c 'if ! command -v entire >/dev/null 2>&1; then exit 0; fi; exec entire hooks copilot-cli agent-stop'",
|
||||||
|
"comment": "Entire CLI"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"errorOccurred": [
|
||||||
|
{
|
||||||
|
"type": "command",
|
||||||
|
"bash": "sh -c 'if ! command -v entire >/dev/null 2>&1; then exit 0; fi; exec entire hooks copilot-cli error-occurred'",
|
||||||
|
"comment": "Entire CLI"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"postToolUse": [
|
||||||
|
{
|
||||||
|
"type": "command",
|
||||||
|
"bash": "sh -c 'if ! command -v entire >/dev/null 2>&1; then exit 0; fi; exec entire hooks copilot-cli post-tool-use'",
|
||||||
|
"comment": "Entire CLI"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"preToolUse": [
|
||||||
|
{
|
||||||
|
"type": "command",
|
||||||
|
"bash": "sh -c 'if ! command -v entire >/dev/null 2>&1; then exit 0; fi; exec entire hooks copilot-cli pre-tool-use'",
|
||||||
|
"comment": "Entire CLI"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"sessionEnd": [
|
||||||
|
{
|
||||||
|
"type": "command",
|
||||||
|
"bash": "sh -c 'if ! command -v entire >/dev/null 2>&1; then exit 0; fi; exec entire hooks copilot-cli session-end'",
|
||||||
|
"comment": "Entire CLI"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"sessionStart": [
|
||||||
|
{
|
||||||
|
"type": "command",
|
||||||
|
"bash": "sh -c 'if ! command -v entire >/dev/null 2>&1; then exit 0; fi; exec entire hooks copilot-cli session-start'",
|
||||||
|
"comment": "Entire CLI"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"subagentStop": [
|
||||||
|
{
|
||||||
|
"type": "command",
|
||||||
|
"bash": "sh -c 'if ! command -v entire >/dev/null 2>&1; then exit 0; fi; exec entire hooks copilot-cli subagent-stop'",
|
||||||
|
"comment": "Entire CLI"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"userPromptSubmitted": [
|
||||||
|
{
|
||||||
|
"type": "command",
|
||||||
|
"bash": "sh -c 'if ! command -v entire >/dev/null 2>&1; then exit 0; fi; exec entire hooks copilot-cli user-prompt-submitted'",
|
||||||
|
"comment": "Entire CLI"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"version": 1
|
||||||
|
}
|
||||||
@@ -0,0 +1,157 @@
|
|||||||
|
# GitHub Copilot Instructions: Qt5/C++11 to Qt6/C++23 Migration
|
||||||
|
|
||||||
|
## Mission
|
||||||
|
Migrate the legacy Qt5/C++11 desktop application to Qt6/C++23, preserve behavior unless change is strictly required, and validate the result completely in the repository’s Docker-based CI workflow.
|
||||||
|
|
||||||
|
## Operating Mode
|
||||||
|
- Work autonomously from analysis through validation.
|
||||||
|
- Do not stop after editing code.
|
||||||
|
- Continue until configure, build, tests, and policy checks have been attempted in Docker.
|
||||||
|
- Do not ask for confirmation during normal implementation.
|
||||||
|
- Stop early only if required source material is missing, the task is impossible, or a destructive action would be required.
|
||||||
|
|
||||||
|
## Boundaries
|
||||||
|
- Read the legacy project from `${PROJECT_DIR}`.
|
||||||
|
- Write the migrated project to `qt6-after/qt6-migrated-benchmark`.
|
||||||
|
- Do not modify the legacy source tree in place.
|
||||||
|
- Limit changes to the target tree and only the CI/build/test files needed to support migration and validation.
|
||||||
|
|
||||||
|
## Main Migration Targets
|
||||||
|
- Upgrade Qt5 to Qt6.
|
||||||
|
- Upgrade C++11/14/17 code to C++23.
|
||||||
|
- Keep Qt Core, Gui, and Widgets explicitly linked.
|
||||||
|
- Replace `QRegExp` with `QRegularExpression`.
|
||||||
|
- Replace `QDesktopWidget` and `QApplication::desktop()` with `QScreen`-based Qt6 APIs.
|
||||||
|
- Remove legacy `QTextCodec` usage and adopt Qt6-safe text handling.
|
||||||
|
- Replace old `SIGNAL`/`SLOT` syntax with function-pointer connect syntax.
|
||||||
|
- Replace `0`/`NULL` pointer literals with `nullptr`.
|
||||||
|
- Preserve `.ui` and `.qrc` integration.
|
||||||
|
- Preserve behavior unless Qt6 compatibility requires adaptation.
|
||||||
|
|
||||||
|
## C++23 Modernization Rules
|
||||||
|
- Preserve semantics first; modernize second.
|
||||||
|
- Use `auto` when the type is obvious; avoid it when it hides important type information.
|
||||||
|
- Prefer structured bindings where clearer.
|
||||||
|
- Replace raw owning pointers/manual `delete` with RAII, usually `std::unique_ptr`.
|
||||||
|
- Use `std::make_unique` / `std::make_shared`; use `std::shared_ptr` only for real shared ownership.
|
||||||
|
- Use `std::string_view` only when lifetime safety is clear.
|
||||||
|
- Prefer `std::span` for non-owning contiguous data; use `std::mdspan` only when multidimensional access clearly benefits.
|
||||||
|
- Prefer `.contains()` over `find(...) != end()` where available.
|
||||||
|
- Prefer algorithms and ranges over manual loops when readability improves.
|
||||||
|
- Use `[[nodiscard]]` when ignoring a result is likely a bug.
|
||||||
|
- Prefer early returns over deeply nested control flow.
|
||||||
|
- Use `std::optional` monadic operations (`and_then`, `transform`, `or_else`) when clearer.
|
||||||
|
- Prefer `constexpr`, `if constexpr`, concepts, and `requires` over legacy `std::enable_if`/SFINAE where practical.
|
||||||
|
- Add `noexcept`, `override`, `final`, `= default`, and `= delete` where correct and useful.
|
||||||
|
- Prefer `enum class` over unscoped enums where practical.
|
||||||
|
- Prefer `std::print` / `std::println` when supported by the toolchain.
|
||||||
|
- Prefer typed `std::chrono` durations and `std::jthread` where appropriate.
|
||||||
|
|
||||||
|
## Safety Rules
|
||||||
|
- Do not change business logic unless explicitly requested or required for Qt6 compatibility.
|
||||||
|
- Do not introduce unsupported Qt6/C++23 features.
|
||||||
|
- Do not silently change ABI, ownership, lifetime, exception behavior, performance, UI behavior, or event ordering.
|
||||||
|
- Do not worsen readability for the sake of modernization.
|
||||||
|
- Avoid dangling references, dangling `std::string_view`, and ownership ambiguity.
|
||||||
|
- Keep includes minimal and preserve repository-local formatting/style.
|
||||||
|
|
||||||
|
## Tests
|
||||||
|
- For every code change inside a method, add at least three tests covering the changed behavior.
|
||||||
|
- Place generated tests in `qt6-after/qt6-migrated-benchmark/tests`.
|
||||||
|
- Use policy-compatible test filenames such as:
|
||||||
|
- `test_<name>.cpp`
|
||||||
|
- `<name>_test.cpp`
|
||||||
|
- `<name>test.cpp`
|
||||||
|
- `<name>gtest.cpp`
|
||||||
|
- Update CMake so the migrated app and all tests build and run with CTest.
|
||||||
|
- Ensure all tests are registered with CTest.
|
||||||
|
|
||||||
|
## Docker-First Validation
|
||||||
|
Use `lifemaps/ci-cpp:latest` as the authoritative environment. Do not substitute host tools for missing container tools. Treat `ci/Dockerfile.ci` as the source of truth for CI dependencies.
|
||||||
|
|
||||||
|
### Required validation sequence
|
||||||
|
1. Configure in Docker
|
||||||
|
2. Build in Docker
|
||||||
|
3. Run tests in Docker
|
||||||
|
4. If tests pass, run `python3 ci/check_pr_policies.py` in Docker
|
||||||
|
|
||||||
|
### Recommended commands
|
||||||
|
- Configure:
|
||||||
|
`cmake -S qt6-after/qt6-migrated-benchmark -B build -G Ninja -DCMAKE_BUILD_TYPE=Debug`
|
||||||
|
- Build:
|
||||||
|
`cmake --build build --parallel`
|
||||||
|
- Test:
|
||||||
|
`ctest --test-dir build --output-on-failure`
|
||||||
|
- Policy:
|
||||||
|
`python3 ci/check_pr_policies.py`
|
||||||
|
|
||||||
|
Adapt paths/flags only if repository inspection proves they must differ.
|
||||||
|
|
||||||
|
## Missing-Tool Remediation
|
||||||
|
If Docker validation fails because a required tool/package is missing:
|
||||||
|
- identify the exact missing dependency
|
||||||
|
- update `Dockerfile.ci` minimally
|
||||||
|
- rebuild `lifemaps/ci-cpp:latest`
|
||||||
|
- rerun the full validation sequence
|
||||||
|
|
||||||
|
Continue until:
|
||||||
|
- validation succeeds, or
|
||||||
|
- the next blocker is a genuine project/code issue
|
||||||
|
|
||||||
|
## Failure Classification
|
||||||
|
Environment failures:
|
||||||
|
- command not found
|
||||||
|
- missing compiler/toolchain utility
|
||||||
|
- missing Qt dev package
|
||||||
|
- missing CMake/Ninja/CTest support tool
|
||||||
|
- missing dependency required by `ci/check_pr_policies.py`
|
||||||
|
|
||||||
|
Project failures:
|
||||||
|
- compile errors
|
||||||
|
- linker errors
|
||||||
|
- failing tests
|
||||||
|
- formatting/policy failures caused by migration changes
|
||||||
|
|
||||||
|
## Policy Awareness
|
||||||
|
- `ci/check_pr_policies.py` checks formatting for changed C/C++ files, expects related tests, and verifies commit-signature conditions in its diff range.
|
||||||
|
- Ensure Docker validation runs with mounted workspace and git metadata available.
|
||||||
|
- Do not claim success unless the policy script passes.
|
||||||
|
|
||||||
|
## Execution Plan
|
||||||
|
1. Inspect `${PROJECT_DIR}` and the target tree.
|
||||||
|
2. Identify Qt5 and legacy C++ constructs to migrate.
|
||||||
|
3. Migrate incrementally in `qt6-after/qt6-migrated-benchmark`.
|
||||||
|
4. Add/update tests with each behavior-relevant change.
|
||||||
|
5. Update CMake/test registration.
|
||||||
|
6. Validate in Docker.
|
||||||
|
7. If missing dependencies are found, update `Dockerfile.ci`, rebuild, and rerun.
|
||||||
|
8. Repeat until success or a real project defect remains.
|
||||||
|
|
||||||
|
## Reporting
|
||||||
|
Group change explanations by:
|
||||||
|
- CMake / build-system migration
|
||||||
|
- Qt API replacements
|
||||||
|
- C++ modernization
|
||||||
|
- UI/resource preservation
|
||||||
|
- tests added
|
||||||
|
- `Dockerfile.ci` / container updates
|
||||||
|
|
||||||
|
Also provide a concise changed-files summary.
|
||||||
|
|
||||||
|
## Completion Criteria
|
||||||
|
Success requires:
|
||||||
|
- migrated project exists under `qt6-after/qt6-migrated-benchmark`
|
||||||
|
- configure succeeds in Docker
|
||||||
|
- build succeeds in Docker
|
||||||
|
- tests succeed in Docker
|
||||||
|
- `python3 ci/check_pr_policies.py` succeeds in Docker after tests pass
|
||||||
|
|
||||||
|
## Final Response
|
||||||
|
- State whether migration is fully validated or which blocker remains.
|
||||||
|
- List the exact Docker commands used for image rebuild, configure, build, test, and policy check.
|
||||||
|
- For every failed attempt, include:
|
||||||
|
- exact command
|
||||||
|
- key error
|
||||||
|
- environment vs project classification
|
||||||
|
- fix applied
|
||||||
|
- End with a short summary of any remaining blocker.
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
.envrc
|
||||||
|
.*~
|
||||||
|
*~
|
||||||
|
build
|
||||||
Vendored
+7
-1
@@ -16,6 +16,9 @@ pipeline {
|
|||||||
PROJECT_DIR = "qt6-after/qt6-migrated-benchmark"
|
PROJECT_DIR = "qt6-after/qt6-migrated-benchmark"
|
||||||
BUILD_DIR = "build"
|
BUILD_DIR = "build"
|
||||||
CHANGE_TARGET = "${env.CHANGE_TARGET ?: 'origin/main'}"
|
CHANGE_TARGET = "${env.CHANGE_TARGET ?: 'origin/main'}"
|
||||||
|
QT_QPA_PLATFORM = "offscreen"
|
||||||
|
LANG = "C.UTF-8"
|
||||||
|
LC_ALL = "C.UTF-8"
|
||||||
}
|
}
|
||||||
|
|
||||||
stages {
|
stages {
|
||||||
@@ -41,6 +44,9 @@ pipeline {
|
|||||||
stage('Qt Diagnostics') {
|
stage('Qt Diagnostics') {
|
||||||
steps {
|
steps {
|
||||||
sh '''
|
sh '''
|
||||||
|
echo "QT_QPA_PLATFORM=$QT_QPA_PLATFORM"
|
||||||
|
echo "LANG=$LANG"
|
||||||
|
echo "LC_ALL=$LC_ALL"
|
||||||
dpkg -l | grep -E "qt6-base-dev|qtbase5-dev|qt6-tools" || true
|
dpkg -l | grep -E "qt6-base-dev|qtbase5-dev|qt6-tools" || true
|
||||||
pkg-config --list-all | grep -i qt || true
|
pkg-config --list-all | grep -i qt || true
|
||||||
'''
|
'''
|
||||||
@@ -67,7 +73,7 @@ pipeline {
|
|||||||
|
|
||||||
stage('Test') {
|
stage('Test') {
|
||||||
steps {
|
steps {
|
||||||
sh 'ctest --test-dir ${BUILD_DIR} --output-on-failure'
|
sh 'QT_QPA_PLATFORM=offscreen LANG=C.UTF-8 LC_ALL=C.UTF-8 ctest --test-dir ${BUILD_DIR} --output-on-failure'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,4 +21,10 @@ RUN apt-get update && \
|
|||||||
qt6-tools-dev-tools && \
|
qt6-tools-dev-tools && \
|
||||||
rm -rf /var/lib/apt/lists/*
|
rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# Set Qt platform for headless testing
|
||||||
|
ENV QT_QPA_PLATFORM=offscreen
|
||||||
|
|
||||||
|
# Configure git for containerized environments
|
||||||
|
RUN git config --global --add safe.directory "*"
|
||||||
|
|
||||||
WORKDIR /workspace
|
WORKDIR /workspace
|
||||||
+2
-1
@@ -1 +1,2 @@
|
|||||||
torsten.wierschin@life-maps.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIG+sdfrCTkAHvZCwBGPGUaT4VFkX8YvnqprCpCrLajSH
|
torsten.wierschin@life-maps.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIO+c+9jJKrLpTk4pLg+p1Qo0CjCYzfKfEhXEu0MAlZpj
|
||||||
|
nkana@outlook.de ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBR68AzU7UtY+NJPIRloEeIlQIZIP3xhvkWB8BediMeQ
|
||||||
+10
-1
@@ -209,4 +209,13 @@ def main():
|
|||||||
if not has_related_test(path):
|
if not has_related_test(path):
|
||||||
print(
|
print(
|
||||||
"ERROR: Kein passender Test unter tests/, test/ oder "
|
"ERROR: Kein passender Test unter tests/, test/ oder "
|
||||||
f
|
"qt6-after/qt6-migrated-benchmark/tests/ gefunden für: "
|
||||||
|
f"{rel}"
|
||||||
|
)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
print("PR-Policy-Prüfungen erfolgreich.")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -196,11 +196,39 @@ clang-format -i main.cpp tests/test_main.cpp
|
|||||||
python3 ci/check_pr_policies.py
|
python3 ci/check_pr_policies.py
|
||||||
```
|
```
|
||||||
|
|
||||||
### Projekt lokal bauen
|
## Projekt lokal im CI-Container bauen
|
||||||
|
|
||||||
|
Zuerst das lokale CI-Image bauen:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Debug
|
docker build -t lifemaps/ci-cpp:latest -f Dockerfile.ci .
|
||||||
cmake --build build --parallel
|
```
|
||||||
ctest --test-dir build --output-on-failure
|
|
||||||
|
Danach das Projekt im Container bauen und testen:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker run --rm -it \
|
||||||
|
-v "$PWD:/workspace" \
|
||||||
|
-w /workspace \
|
||||||
|
lifemaps/ci-cpp:latest \
|
||||||
|
bash -lc '
|
||||||
|
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Debug &&
|
||||||
|
cmake --build build --parallel &&
|
||||||
|
ctest --test-dir build --output-on-failure
|
||||||
|
'
|
||||||
|
```
|
||||||
|
|
||||||
|
Damit wird dieselbe Toolchain verwendet wie in der Jenkins-CI.
|
||||||
|
|
||||||
|
|
||||||
|
## Policy-Check lokal im CI-Container ausführen
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker run --rm -it \
|
||||||
|
-v "$PWD:/workspace" \
|
||||||
|
-w /workspace \
|
||||||
|
lifemaps/ci-cpp:latest \
|
||||||
|
bash -lc 'python3 ci/check_pr_policies.py'
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -0,0 +1,336 @@
|
|||||||
|
# Entire auf Headless-Server mit EU-Kontext einrichten
|
||||||
|
|
||||||
|
Diese Anleitung beschreibt die Einrichtung von Entire auf einem Headless-Host mit bestehendem Git-Repository auf einem eigenen Gitea-Server und Nutzung des **EU-Kontexts**.
|
||||||
|
|
||||||
|
## Ziel
|
||||||
|
|
||||||
|
- Entire ohne GUI/Browser auf dem Server verwenden
|
||||||
|
- Login über Device-Code-Flow
|
||||||
|
- Tokens ohne OS-Keyring in Datei speichern
|
||||||
|
- EU-Jurisdiktion / EU-Cluster verwenden
|
||||||
|
- Entire lokal in einem bestehenden Git-Repository aktivieren
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Voraussetzungen
|
||||||
|
|
||||||
|
- `entire` CLI ist installiert
|
||||||
|
- Zugriff per SSH auf den Headless-Server
|
||||||
|
- funktionierendes lokales Git-Checkout
|
||||||
|
- `origin`-Remote ist gesetzt
|
||||||
|
- Browser auf einem **anderen lokalen Rechner** verfügbar
|
||||||
|
|
||||||
|
Beispiel prüfen:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git remote -v
|
||||||
|
```
|
||||||
|
|
||||||
|
Beispielausgabe:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
origin git@devel:lifemaps/qt-migration-copilot-demo.git (fetch)
|
||||||
|
origin git@devel:lifemaps/qt-migration-copilot-demo.git (push)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Token-Speicherung für Headless-Betrieb aktivieren
|
||||||
|
|
||||||
|
Auf Headless-Systemen gibt es oft keinen Linux-Keyring (`org.freedesktop.secrets`).
|
||||||
|
Deshalb sollten Entire-Tokens in einer Datei gespeichert werden.
|
||||||
|
|
||||||
|
Empfohlene Umgebungsvariablen:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export ENTIRE_TOKEN_STORE=file
|
||||||
|
export ENTIRE_TOKEN_STORE_PATH="$HOME/.config/entire/tokens.json"
|
||||||
|
export ACCESSIBLE=1
|
||||||
|
```
|
||||||
|
|
||||||
|
Temporär in der aktuellen Shell:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export ENTIRE_TOKEN_STORE=file
|
||||||
|
export ENTIRE_TOKEN_STORE_PATH="$HOME/.config/entire/tokens.json"
|
||||||
|
export ACCESSIBLE=1
|
||||||
|
```
|
||||||
|
|
||||||
|
Dauerhaft in `~/.bashrc`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
echo 'export ENTIRE_TOKEN_STORE=file' >> ~/.bashrc
|
||||||
|
echo 'export ENTIRE_TOKEN_STORE_PATH="$HOME/.config/entire/tokens.json"' >> ~/.bashrc
|
||||||
|
echo 'export ACCESSIBLE=1' >> ~/.bashrc
|
||||||
|
source ~/.bashrc
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Im EU-Kontext anmelden
|
||||||
|
|
||||||
|
Für Headless-Systeme den Device-Code-Flow verwenden:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
entire login --device --server https://eu.auth.entire.io
|
||||||
|
```
|
||||||
|
|
||||||
|
Das CLI zeigt dann etwa:
|
||||||
|
|
||||||
|
- einen **Device Code**
|
||||||
|
- eine **Login-URL**
|
||||||
|
|
||||||
|
Die URL im Browser **auf dem lokalen Rechner** öffnen und die Anmeldung dort bestätigen.
|
||||||
|
|
||||||
|
### Wichtiger Hinweis
|
||||||
|
|
||||||
|
Wenn auf dem Server kein Browser verfügbar ist, ist eine Meldung wie diese normal:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Warning: failed to open browser: xdg-open not found
|
||||||
|
```
|
||||||
|
|
||||||
|
Das ist **nicht** das eigentliche Problem.
|
||||||
|
|
||||||
|
Falls Entire versucht, Tokens im Keyring zu speichern und dabei fehlschlägt, war `ENTIRE_TOKEN_STORE=file` nicht gesetzt.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Login prüfen
|
||||||
|
|
||||||
|
Nach erfolgreicher Anmeldung:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
entire auth status
|
||||||
|
```
|
||||||
|
|
||||||
|
Beispiel:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Logged in to https://eu.auth.entire.io
|
||||||
|
Context: eu.auth.entire.io
|
||||||
|
Token: stored in file /home/<user>/.config/entire/tokens.json
|
||||||
|
```
|
||||||
|
|
||||||
|
Falls mehrere Kontexte existieren:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
entire auth contexts
|
||||||
|
entire auth use --help
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Prüfen, ob wirklich EU verwendet wird
|
||||||
|
|
||||||
|
Zusätzlich zum Login-Kontext sollte geprüft werden, auf welchem Cluster die Entire-Repositories liegen.
|
||||||
|
|
||||||
|
Projekt-Repositories anzeigen:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
entire repo list <project-id>
|
||||||
|
```
|
||||||
|
|
||||||
|
Wenn in der Spalte `CLUSTER` z. B. Folgendes erscheint:
|
||||||
|
|
||||||
|
```text
|
||||||
|
aws-eu-central-1.entire.io
|
||||||
|
```
|
||||||
|
|
||||||
|
dann liegen diese Repositories auf einem **EU-Cluster**.
|
||||||
|
|
||||||
|
### Empfohlener Doppel-Check
|
||||||
|
|
||||||
|
```bash
|
||||||
|
entire auth status
|
||||||
|
entire repo list <project-id>
|
||||||
|
```
|
||||||
|
|
||||||
|
EU ist praktisch bestätigt, wenn:
|
||||||
|
|
||||||
|
- `Context: eu.auth.entire.io` aktiv ist
|
||||||
|
- die Repositories auf `aws-eu-central-1.entire.io` liegen
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Entire im lokalen Repository aktivieren
|
||||||
|
|
||||||
|
In das lokale Repository wechseln:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd ~/coplint.d/qt-migration-copilot-demo
|
||||||
|
```
|
||||||
|
|
||||||
|
Dann Entire aktivieren:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
entire enable
|
||||||
|
```
|
||||||
|
|
||||||
|
Status prüfen:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
entire status
|
||||||
|
```
|
||||||
|
|
||||||
|
Beispiel:
|
||||||
|
|
||||||
|
```text
|
||||||
|
● Enabled · branch bugfix/ci-pipeline-commissioning
|
||||||
|
Agents · Copilot CLI
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. Agent-Integration prüfen oder ergänzen
|
||||||
|
|
||||||
|
Verfügbare Agenten anzeigen:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
entire agent list
|
||||||
|
```
|
||||||
|
|
||||||
|
Hilfe für das Hinzufügen:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
entire agent add --help
|
||||||
|
```
|
||||||
|
|
||||||
|
Neuen Agenten hinzufügen:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
entire agent add <name>
|
||||||
|
```
|
||||||
|
|
||||||
|
Danach erneut prüfen:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
entire status
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. Unterschied zwischen lokalem Git-Repo und Entire-Repo verstehen
|
||||||
|
|
||||||
|
Wichtig: Entire verwendet hier **zwei verschiedene Konzepte**.
|
||||||
|
|
||||||
|
### Lokales Git-Repository
|
||||||
|
Das echte Code-Repository, z. B.:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git@devel:lifemaps/qt-migration-copilot-demo.git
|
||||||
|
```
|
||||||
|
|
||||||
|
### Entire-Repository
|
||||||
|
Ein separates Objekt in Entire, verwaltet über:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
entire repo list <project-id>
|
||||||
|
entire repo get <repo> --project <project-id>
|
||||||
|
entire repo create <name> --project <project-id>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Konsequenz
|
||||||
|
|
||||||
|
`entire enable` aktiviert das **lokale Git-Repository**,
|
||||||
|
aber es erzeugt **nicht automatisch** ein neues `entire repo`-Objekt.
|
||||||
|
|
||||||
|
Darum kann es sein, dass:
|
||||||
|
|
||||||
|
- `entire status` = aktiviert
|
||||||
|
- aber `entire repo list <project-id>` dein lokales Repo **nicht** zeigt
|
||||||
|
|
||||||
|
Das ist normales Verhalten.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. Optional: Entire-Repo im Projekt anlegen
|
||||||
|
|
||||||
|
Wenn zusätzlich ein eigenes Entire-Repo-Objekt für das lokale Projekt gewünscht ist:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
entire repo create qt-migration-copilot-demo --project <project-id>
|
||||||
|
```
|
||||||
|
|
||||||
|
Danach prüfen:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
entire repo list <project-id>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Hinweis
|
||||||
|
|
||||||
|
Nach bisherigem CLI-Verhalten wird dabei nur ein **Entire-internes Repo-Objekt** erzeugt.
|
||||||
|
Es gibt in der gezeigten Hilfe keinen Hinweis darauf, dass dabei automatisch eine Git-URL aus Gitea importiert oder synchronisiert wird.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9. Typischer Minimal-Workflow
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export ENTIRE_TOKEN_STORE=file
|
||||||
|
export ENTIRE_TOKEN_STORE_PATH="$HOME/.config/entire/tokens.json"
|
||||||
|
export ACCESSIBLE=1
|
||||||
|
|
||||||
|
entire login --device --server https://eu.auth.entire.io
|
||||||
|
entire auth status
|
||||||
|
|
||||||
|
cd ~/coplint.d/qt-migration-copilot-demo
|
||||||
|
entire enable
|
||||||
|
entire status
|
||||||
|
entire agent list
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 10. Troubleshooting
|
||||||
|
|
||||||
|
### Kein Browser auf dem Server
|
||||||
|
Normal auf Headless-Hosts.
|
||||||
|
Device-Code-URL auf lokalem Rechner öffnen.
|
||||||
|
|
||||||
|
### Login erfolgreich, aber `Not logged in`
|
||||||
|
Ursache meist fehlender Keyring und keine Datei-Speicherung.
|
||||||
|
|
||||||
|
Lösung:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export ENTIRE_TOKEN_STORE=file
|
||||||
|
entire login --device --server https://eu.auth.entire.io
|
||||||
|
```
|
||||||
|
|
||||||
|
### Entire ist aktiviert, aber nicht in `entire repo list`
|
||||||
|
Das ist erwartbar, weil lokales Git-Repo und Entire-Projektrepo getrennte Objekte sind.
|
||||||
|
|
||||||
|
### Diagnose
|
||||||
|
Bei Problemen:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
entire doctor
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 11. Empfehlung für dieses Setup
|
||||||
|
|
||||||
|
Für ein Setup mit **Gitea + Jenkins + Entire** gilt:
|
||||||
|
|
||||||
|
- **Gitea** bleibt Source-of-Truth für den Code
|
||||||
|
- **Jenkins** bleibt CI/CD-System
|
||||||
|
- **Entire** ergänzt Session-, Agent- und Checkpoint-Tracking im lokalen Repository
|
||||||
|
- **Entire-Projekte/Repos** sind zusätzliche Verwaltungsobjekte und nicht identisch mit dem Gitea-Remote
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 12. Nützliche Befehle
|
||||||
|
|
||||||
|
```bash
|
||||||
|
entire auth status
|
||||||
|
entire auth contexts
|
||||||
|
entire project list
|
||||||
|
entire repo list <project-id>
|
||||||
|
entire enable
|
||||||
|
entire status
|
||||||
|
entire agent list
|
||||||
|
entire doctor
|
||||||
|
```
|
||||||
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,40 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.16)
|
||||||
|
|
||||||
|
project(Qt6MigratedBenchmark LANGUAGES CXX)
|
||||||
|
|
||||||
|
set(CMAKE_CXX_STANDARD 23)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||||
|
|
||||||
|
set(CMAKE_AUTOMOC ON)
|
||||||
|
set(CMAKE_AUTOUIC ON)
|
||||||
|
set(CMAKE_AUTORCC ON)
|
||||||
|
|
||||||
|
find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets)
|
||||||
|
|
||||||
|
qt_standard_project_setup(REQUIRES 6.5)
|
||||||
|
|
||||||
|
add_executable(Qt6MigratedBenchmark
|
||||||
|
main.cpp
|
||||||
|
MainWindow.h
|
||||||
|
MainWindow.cpp
|
||||||
|
MainWindow.ui
|
||||||
|
resources.qrc
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(Qt6MigratedBenchmark PRIVATE
|
||||||
|
Qt6::Core
|
||||||
|
Qt6::Gui
|
||||||
|
Qt6::Widgets
|
||||||
|
)
|
||||||
|
|
||||||
|
target_compile_features(Qt6MigratedBenchmark PRIVATE cxx_std_23)
|
||||||
|
|
||||||
|
# Enable warnings
|
||||||
|
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
|
||||||
|
target_compile_options(Qt6MigratedBenchmark PRIVATE -Wall -Wextra -pedantic)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Add tests
|
||||||
|
enable_testing()
|
||||||
|
add_subdirectory(tests)
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
#include "MainWindow.h"
|
||||||
|
|
||||||
|
#include "ui_MainWindow.h"
|
||||||
|
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QPixmap>
|
||||||
|
#include <QScreen>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
MainWindow::MainWindow(QWidget* parent)
|
||||||
|
: QMainWindow(parent), ui(new Ui::MainWindow), pattern(QRegularExpression(R"(^[A-Za-z]+\d+$)"))
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
|
||||||
|
// Qt6 uses UTF-8 by default; no codec needed
|
||||||
|
setWindowTitle(QString::fromUtf8("Qt6 Migrated Benchmark"));
|
||||||
|
ui->label->setText(QString::fromUtf8("Bitte Text wie Test123 eingeben."));
|
||||||
|
ui->iconLabel->setPixmap(QPixmap(":/icons/app.png").scaled(48, 48));
|
||||||
|
|
||||||
|
// Modern function-pointer connect syntax
|
||||||
|
connect(ui->validateButton, &QPushButton::clicked, this, &MainWindow::onValidateClicked);
|
||||||
|
connect(ui->screenButton, &QPushButton::clicked, this, &MainWindow::onScreenInfoClicked);
|
||||||
|
}
|
||||||
|
|
||||||
|
MainWindow::~MainWindow()
|
||||||
|
{
|
||||||
|
delete ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::onValidateClicked()
|
||||||
|
{
|
||||||
|
const QString text = ui->lineEdit->text();
|
||||||
|
|
||||||
|
if (pattern.match(text).hasMatch())
|
||||||
|
{
|
||||||
|
ui->resultLabel->setText(QString::fromUtf8("Match"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ui->resultLabel->setText(QString::fromUtf8("No match"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::onScreenInfoClicked()
|
||||||
|
{
|
||||||
|
// Qt6: Use QScreen instead of deprecated QDesktopWidget
|
||||||
|
const QScreen* screen = QApplication::primaryScreen();
|
||||||
|
if (screen)
|
||||||
|
{
|
||||||
|
const QRect screenGeometry = screen->geometry();
|
||||||
|
const QString info =
|
||||||
|
QString::fromUtf8("Screen: %1x%2").arg(screenGeometry.width()).arg(screenGeometry.height());
|
||||||
|
ui->resultLabel->setText(info);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QMainWindow>
|
||||||
|
#include <QRegularExpression>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
namespace Ui
|
||||||
|
{
|
||||||
|
class MainWindow;
|
||||||
|
}
|
||||||
|
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
class MainWindow : public QMainWindow
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit MainWindow(QWidget* parent = nullptr);
|
||||||
|
~MainWindow() override;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void onValidateClicked();
|
||||||
|
void onScreenInfoClicked();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Ui::MainWindow* ui;
|
||||||
|
QRegularExpression pattern;
|
||||||
|
};
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>MainWindow</class>
|
||||||
|
<widget class="QMainWindow" name="MainWindow">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>420</width>
|
||||||
|
<height>240</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Qt5 Legacy App</string>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="centralwidget">
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="text">
|
||||||
|
<string>Initial text</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="lineEdit">
|
||||||
|
<property name="placeholderText">
|
||||||
|
<string>Enter value like Test123</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="iconLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="buttonLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="validateButton">
|
||||||
|
<property name="text">
|
||||||
|
<string>Validate</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="screenButton">
|
||||||
|
<property name="text">
|
||||||
|
<string>Screen Info</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="resultLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>Result appears here</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 100 KiB |
@@ -0,0 +1,19 @@
|
|||||||
|
#include "MainWindow.h"
|
||||||
|
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QScreen>
|
||||||
|
|
||||||
|
#if __has_include(<print>)
|
||||||
|
#include <print>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
[[nodiscard]] auto main(int argc, char* argv[]) -> int
|
||||||
|
{
|
||||||
|
QApplication app{argc, argv};
|
||||||
|
|
||||||
|
// Qt6 uses UTF-8 by default; no codec setup needed
|
||||||
|
MainWindow window;
|
||||||
|
window.show();
|
||||||
|
|
||||||
|
return app.exec();
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
<RCC>
|
||||||
|
<qresource prefix="/icons">
|
||||||
|
<file>app.png</file>
|
||||||
|
</qresource>
|
||||||
|
</RCC>
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.16)
|
||||||
|
project(Qt6MigratedBenchmarkTests LANGUAGES CXX)
|
||||||
|
|
||||||
|
set(CMAKE_CXX_STANDARD 23)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
|
||||||
|
find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets Test)
|
||||||
|
|
||||||
|
add_executable(main_test
|
||||||
|
main_test.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(main_test PRIVATE
|
||||||
|
Qt6::Core
|
||||||
|
Qt6::Gui
|
||||||
|
Qt6::Widgets
|
||||||
|
Qt6::Test
|
||||||
|
)
|
||||||
|
|
||||||
|
add_test(NAME main_test COMMAND main_test)
|
||||||
|
|
||||||
|
add_executable(MainWindow_test
|
||||||
|
MainWindow_test.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(MainWindow_test PRIVATE
|
||||||
|
Qt6::Core
|
||||||
|
Qt6::Gui
|
||||||
|
Qt6::Widgets
|
||||||
|
Qt6::Test
|
||||||
|
)
|
||||||
|
|
||||||
|
add_test(NAME MainWindow_test COMMAND MainWindow_test)
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
#include <QRect>
|
||||||
|
#include <QRegularExpression>
|
||||||
|
#include <QScreen>
|
||||||
|
#include <QString>
|
||||||
|
#include <QTest>
|
||||||
|
|
||||||
|
class MainWindowPatternTest : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void testPatternValidLettersThenDigits();
|
||||||
|
void testPatternInvalidDigitsThenLetters();
|
||||||
|
void testPatternInvalidSpecialCharacters();
|
||||||
|
void testScreenGeometryExtraction();
|
||||||
|
void testRegularExpressionContainsMethod();
|
||||||
|
};
|
||||||
|
|
||||||
|
void MainWindowPatternTest::testPatternValidLettersThenDigits()
|
||||||
|
{
|
||||||
|
QRegularExpression pattern(R"(^[A-Za-z]+\d+$)");
|
||||||
|
|
||||||
|
QVERIFY(pattern.match(QString::fromUtf8("Test123")).hasMatch());
|
||||||
|
QVERIFY(pattern.match(QString::fromUtf8("ABC456")).hasMatch());
|
||||||
|
QVERIFY(pattern.match(QString::fromUtf8("a1")).hasMatch());
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindowPatternTest::testPatternInvalidDigitsThenLetters()
|
||||||
|
{
|
||||||
|
QRegularExpression pattern(R"(^[A-Za-z]+\d+$)");
|
||||||
|
|
||||||
|
QVERIFY(!pattern.match(QString::fromUtf8("123Test")).hasMatch());
|
||||||
|
QVERIFY(!pattern.match(QString::fromUtf8("1a")).hasMatch());
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindowPatternTest::testPatternInvalidSpecialCharacters()
|
||||||
|
{
|
||||||
|
QRegularExpression pattern(R"(^[A-Za-z]+\d+$)");
|
||||||
|
|
||||||
|
QVERIFY(!pattern.match(QString::fromUtf8("Test@123")).hasMatch());
|
||||||
|
QVERIFY(!pattern.match(QString::fromUtf8("Test_123")).hasMatch());
|
||||||
|
QVERIFY(!pattern.match(QString::fromUtf8("")).hasMatch());
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindowPatternTest::testScreenGeometryExtraction()
|
||||||
|
{
|
||||||
|
const QScreen* screen = QGuiApplication::primaryScreen();
|
||||||
|
if (screen)
|
||||||
|
{
|
||||||
|
const QRect geometry = screen->geometry();
|
||||||
|
QVERIFY(geometry.width() > 0);
|
||||||
|
QVERIFY(geometry.height() > 0);
|
||||||
|
|
||||||
|
const QString info = QString::fromUtf8("Screen: %1x%2").arg(geometry.width()).arg(geometry.height());
|
||||||
|
QVERIFY(!info.isEmpty());
|
||||||
|
QVERIFY(info.contains(QString::fromUtf8("Screen:")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindowPatternTest::testRegularExpressionContainsMethod()
|
||||||
|
{
|
||||||
|
QRegularExpression pattern(R"(^[A-Za-z]+\d+$)");
|
||||||
|
|
||||||
|
const QString validInput = QString::fromUtf8("Test123");
|
||||||
|
const QRegularExpressionMatch match = pattern.match(validInput);
|
||||||
|
QVERIFY(match.hasMatch());
|
||||||
|
|
||||||
|
const QString invalidInput = QString::fromUtf8("Invalid");
|
||||||
|
const QRegularExpressionMatch noMatch = pattern.match(invalidInput);
|
||||||
|
QVERIFY(!noMatch.hasMatch());
|
||||||
|
}
|
||||||
|
|
||||||
|
QTEST_MAIN(MainWindowPatternTest)
|
||||||
|
|
||||||
|
#include "MainWindow_test.moc"
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
#include <QRegularExpression>
|
||||||
|
#include <QString>
|
||||||
|
#include <QTest>
|
||||||
|
|
||||||
|
class MainTest : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void testRegularExpressionValidation_data();
|
||||||
|
void testRegularExpressionValidation();
|
||||||
|
void testQStringUtf8Conversion();
|
||||||
|
void testRegularExpressionPattern();
|
||||||
|
};
|
||||||
|
|
||||||
|
void MainTest::testRegularExpressionValidation_data()
|
||||||
|
{
|
||||||
|
QTest::addColumn<QString>("input");
|
||||||
|
QTest::addColumn<bool>("expectedMatch");
|
||||||
|
|
||||||
|
QTest::newRow("valid_input_Test123") << QString::fromUtf8("Test123") << true;
|
||||||
|
QTest::newRow("valid_input_ABC456") << QString::fromUtf8("ABC456") << true;
|
||||||
|
QTest::newRow("valid_input_a1") << QString::fromUtf8("a1") << true;
|
||||||
|
QTest::newRow("invalid_input_123Test") << QString::fromUtf8("123Test") << false;
|
||||||
|
QTest::newRow("invalid_input_special") << QString::fromUtf8("Test@123") << false;
|
||||||
|
QTest::newRow("invalid_input_empty") << QString::fromUtf8("") << false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainTest::testRegularExpressionValidation()
|
||||||
|
{
|
||||||
|
QFETCH(QString, input);
|
||||||
|
QFETCH(bool, expectedMatch);
|
||||||
|
|
||||||
|
QRegularExpression pattern(R"(^[A-Za-z]+\d+$)");
|
||||||
|
const bool matches = pattern.match(input).hasMatch();
|
||||||
|
|
||||||
|
QCOMPARE(matches, expectedMatch);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainTest::testQStringUtf8Conversion()
|
||||||
|
{
|
||||||
|
const QString title = QString::fromUtf8("Qt6 Migrated Benchmark");
|
||||||
|
QCOMPARE(title, QString::fromUtf8("Qt6 Migrated Benchmark"));
|
||||||
|
|
||||||
|
const QString label = QString::fromUtf8("Bitte Text wie Test123 eingeben.");
|
||||||
|
QCOMPARE(label, QString::fromUtf8("Bitte Text wie Test123 eingeben."));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainTest::testRegularExpressionPattern()
|
||||||
|
{
|
||||||
|
QRegularExpression pattern(R"(^[A-Za-z]+\d+$)");
|
||||||
|
QVERIFY(pattern.isValid());
|
||||||
|
|
||||||
|
const QRegularExpressionMatch match = pattern.match(QString::fromUtf8("Test123"));
|
||||||
|
QVERIFY(match.hasMatch());
|
||||||
|
|
||||||
|
const QRegularExpressionMatch noMatch = pattern.match(QString::fromUtf8("123Test"));
|
||||||
|
QVERIFY(!noMatch.hasMatch());
|
||||||
|
}
|
||||||
|
|
||||||
|
QTEST_MAIN(MainTest)
|
||||||
|
|
||||||
|
#include "main_test.moc"
|
||||||
@@ -0,0 +1,157 @@
|
|||||||
|
# GitHub Copilot Instructions: Qt5/C++11 to Qt6/C++23 Migration
|
||||||
|
|
||||||
|
## Mission
|
||||||
|
Migrate the legacy Qt5/C++11 desktop application to Qt6/C++23, preserve behavior unless change is strictly required, and validate the result completely in the repository’s Docker-based CI workflow.
|
||||||
|
|
||||||
|
## Operating Mode
|
||||||
|
- Work autonomously from analysis through validation.
|
||||||
|
- Do not stop after editing code.
|
||||||
|
- Continue until configure, build, tests, and policy checks have been attempted in Docker.
|
||||||
|
- Do not ask for confirmation during normal implementation.
|
||||||
|
- Stop early only if required source material is missing, the task is impossible, or a destructive action would be required.
|
||||||
|
|
||||||
|
## Boundaries
|
||||||
|
- Read the legacy project from `${PROJECT_DIR}`.
|
||||||
|
- Write the migrated project to `qt6-after/qt6-migrated-benchmark`.
|
||||||
|
- Do not modify the legacy source tree in place.
|
||||||
|
- Limit changes to the target tree and only the CI/build/test files needed to support migration and validation.
|
||||||
|
|
||||||
|
## Main Migration Targets
|
||||||
|
- Upgrade Qt5 to Qt6.
|
||||||
|
- Upgrade C++11/14/17 code to C++23.
|
||||||
|
- Keep Qt Core, Gui, and Widgets explicitly linked.
|
||||||
|
- Replace `QRegExp` with `QRegularExpression`.
|
||||||
|
- Replace `QDesktopWidget` and `QApplication::desktop()` with `QScreen`-based Qt6 APIs.
|
||||||
|
- Remove legacy `QTextCodec` usage and adopt Qt6-safe text handling.
|
||||||
|
- Replace old `SIGNAL`/`SLOT` syntax with function-pointer connect syntax.
|
||||||
|
- Replace `0`/`NULL` pointer literals with `nullptr`.
|
||||||
|
- Preserve `.ui` and `.qrc` integration.
|
||||||
|
- Preserve behavior unless Qt6 compatibility requires adaptation.
|
||||||
|
|
||||||
|
## C++23 Modernization Rules
|
||||||
|
- Preserve semantics first; modernize second.
|
||||||
|
- Use `auto` when the type is obvious; avoid it when it hides important type information.
|
||||||
|
- Prefer structured bindings where clearer.
|
||||||
|
- Replace raw owning pointers/manual `delete` with RAII, usually `std::unique_ptr`.
|
||||||
|
- Use `std::make_unique` / `std::make_shared`; use `std::shared_ptr` only for real shared ownership.
|
||||||
|
- Use `std::string_view` only when lifetime safety is clear.
|
||||||
|
- Prefer `std::span` for non-owning contiguous data; use `std::mdspan` only when multidimensional access clearly benefits.
|
||||||
|
- Prefer `.contains()` over `find(...) != end()` where available.
|
||||||
|
- Prefer algorithms and ranges over manual loops when readability improves.
|
||||||
|
- Use `[[nodiscard]]` when ignoring a result is likely a bug.
|
||||||
|
- Prefer early returns over deeply nested control flow.
|
||||||
|
- Use `std::optional` monadic operations (`and_then`, `transform`, `or_else`) when clearer.
|
||||||
|
- Prefer `constexpr`, `if constexpr`, concepts, and `requires` over legacy `std::enable_if`/SFINAE where practical.
|
||||||
|
- Add `noexcept`, `override`, `final`, `= default`, and `= delete` where correct and useful.
|
||||||
|
- Prefer `enum class` over unscoped enums where practical.
|
||||||
|
- Prefer `std::print` / `std::println` when supported by the toolchain.
|
||||||
|
- Prefer typed `std::chrono` durations and `std::jthread` where appropriate.
|
||||||
|
|
||||||
|
## Safety Rules
|
||||||
|
- Do not change business logic unless explicitly requested or required for Qt6 compatibility.
|
||||||
|
- Do not introduce unsupported Qt6/C++23 features.
|
||||||
|
- Do not silently change ABI, ownership, lifetime, exception behavior, performance, UI behavior, or event ordering.
|
||||||
|
- Do not worsen readability for the sake of modernization.
|
||||||
|
- Avoid dangling references, dangling `std::string_view`, and ownership ambiguity.
|
||||||
|
- Keep includes minimal and preserve repository-local formatting/style.
|
||||||
|
|
||||||
|
## Tests
|
||||||
|
- For every code change inside a method, add at least three tests covering the changed behavior.
|
||||||
|
- Place generated tests in `qt6-after/qt6-migrated-benchmark/tests`.
|
||||||
|
- Use policy-compatible test filenames such as:
|
||||||
|
- `test_<name>.cpp`
|
||||||
|
- `<name>_test.cpp`
|
||||||
|
- `<name>test.cpp`
|
||||||
|
- `<name>gtest.cpp`
|
||||||
|
- Update CMake so the migrated app and all tests build and run with CTest.
|
||||||
|
- Ensure all tests are registered with CTest.
|
||||||
|
|
||||||
|
## Docker-First Validation
|
||||||
|
Use `lifemaps/ci-cpp:latest` as the authoritative environment. Do not substitute host tools for missing container tools. Treat `Dockerfile.ci` as the source of truth for CI dependencies.
|
||||||
|
|
||||||
|
### Required validation sequence
|
||||||
|
1. Configure in Docker
|
||||||
|
2. Build in Docker
|
||||||
|
3. Run tests in Docker
|
||||||
|
4. If tests pass, run `python3 ci/check_pr_policies.py` in Docker
|
||||||
|
|
||||||
|
### Recommended commands
|
||||||
|
- Configure:
|
||||||
|
`cmake -S qt6-after/qt6-migrated-benchmark -B build -G Ninja -DCMAKE_BUILD_TYPE=Debug`
|
||||||
|
- Build:
|
||||||
|
`cmake --build build --parallel`
|
||||||
|
- Test:
|
||||||
|
`ctest --test-dir build --output-on-failure`
|
||||||
|
- Policy:
|
||||||
|
`python3 ci/check_pr_policies.py`
|
||||||
|
|
||||||
|
Adapt paths/flags only if repository inspection proves they must differ.
|
||||||
|
|
||||||
|
## Missing-Tool Remediation
|
||||||
|
If Docker validation fails because a required tool/package is missing:
|
||||||
|
- identify the exact missing dependency
|
||||||
|
- update `Dockerfile.ci` minimally
|
||||||
|
- rebuild `lifemaps/ci-cpp:latest`
|
||||||
|
- rerun the full validation sequence
|
||||||
|
|
||||||
|
Continue until:
|
||||||
|
- validation succeeds, or
|
||||||
|
- the next blocker is a genuine project/code issue
|
||||||
|
|
||||||
|
## Failure Classification
|
||||||
|
Environment failures:
|
||||||
|
- command not found
|
||||||
|
- missing compiler/toolchain utility
|
||||||
|
- missing Qt dev package
|
||||||
|
- missing CMake/Ninja/CTest support tool
|
||||||
|
- missing dependency required by `ci/check_pr_policies.py`
|
||||||
|
|
||||||
|
Project failures:
|
||||||
|
- compile errors
|
||||||
|
- linker errors
|
||||||
|
- failing tests
|
||||||
|
- formatting/policy failures caused by migration changes
|
||||||
|
|
||||||
|
## Policy Awareness
|
||||||
|
- `ci/check_pr_policies.py` checks formatting for changed C/C++ files, expects related tests, and verifies commit-signature conditions in its diff range.
|
||||||
|
- Ensure Docker validation runs with mounted workspace and git metadata available.
|
||||||
|
- Do not claim success unless the policy script passes.
|
||||||
|
|
||||||
|
## Execution Plan
|
||||||
|
1. Inspect `${PROJECT_DIR}` and the target tree.
|
||||||
|
2. Identify Qt5 and legacy C++ constructs to migrate.
|
||||||
|
3. Migrate incrementally in `qt6-after/qt6-migrated-benchmark`.
|
||||||
|
4. Add/update tests with each behavior-relevant change.
|
||||||
|
5. Update CMake/test registration.
|
||||||
|
6. Validate in Docker.
|
||||||
|
7. If missing dependencies are found, update `Dockerfile.ci`, rebuild, and rerun.
|
||||||
|
8. Repeat until success or a real project defect remains.
|
||||||
|
|
||||||
|
## Reporting
|
||||||
|
Group change explanations by:
|
||||||
|
- CMake / build-system migration
|
||||||
|
- Qt API replacements
|
||||||
|
- C++ modernization
|
||||||
|
- UI/resource preservation
|
||||||
|
- tests added
|
||||||
|
- `Dockerfile.ci` / container updates
|
||||||
|
|
||||||
|
Also provide a concise changed-files summary.
|
||||||
|
|
||||||
|
## Completion Criteria
|
||||||
|
Success requires:
|
||||||
|
- migrated project exists under `qt6-after/qt6-migrated-benchmark`
|
||||||
|
- configure succeeds in Docker
|
||||||
|
- build succeeds in Docker
|
||||||
|
- tests succeed in Docker
|
||||||
|
- `python3 ci/check_pr_policies.py` succeeds in Docker after tests pass
|
||||||
|
|
||||||
|
## Final Response
|
||||||
|
- State whether migration is fully validated or which blocker remains.
|
||||||
|
- List the exact Docker commands used for image rebuild, configure, build, test, and policy check.
|
||||||
|
- For every failed attempt, include:
|
||||||
|
- exact command
|
||||||
|
- key error
|
||||||
|
- environment vs project classification
|
||||||
|
- fix applied
|
||||||
|
- End with a short summary of any remaining blocker.
|
||||||
@@ -0,0 +1,119 @@
|
|||||||
|
# GitHub Copilot Repository Instructions: C++ Modernization
|
||||||
|
|
||||||
|
## Project Context
|
||||||
|
- **Language:** C++
|
||||||
|
- **Target Standard:** C++23 (Strict enforcement)
|
||||||
|
- **Migration Goal:** Systematically upgrade legacy C++11/C++14/C++17 code to modern C++23 paradigms.
|
||||||
|
|
||||||
|
## Core Objective
|
||||||
|
Modernize the codebase incrementally and safely. Preserve existing behavior unless the task explicitly requests functional changes. Prefer small, reviewable refactors that improve correctness, safety, readability, and maintainability.
|
||||||
|
|
||||||
|
## Global Migration Principles
|
||||||
|
- Preserve semantics first; modernize second.
|
||||||
|
- Prefer standard C++23 library facilities over custom utilities where equivalent.
|
||||||
|
- Favor compile-time validation, explicit ownership, and strong type safety.
|
||||||
|
- Reduce boilerplate only when readability improves.
|
||||||
|
- Avoid unnecessary churn in code that is already modern and clear.
|
||||||
|
- Keep ABI-sensitive or externally exposed interfaces stable unless breaking changes are explicitly allowed.
|
||||||
|
- For larger migrations, refactor file-by-file or subsystem-by-subsystem.
|
||||||
|
|
||||||
|
## Migration Rules
|
||||||
|
|
||||||
|
### 1. Type Inference & Variables
|
||||||
|
- Replace explicit types with `auto` where the type is obvious from the initializer.
|
||||||
|
- Do not use `auto` when it obscures important type information or changes value/reference semantics unintentionally.
|
||||||
|
- Prefer `const auto` and `const auto&` where appropriate.
|
||||||
|
- Use structured bindings (`auto [x, y] = ...`) instead of `std::tie`, `.first/.second`, or tuple indexing where it improves clarity.
|
||||||
|
- Prefer uniform initialization where appropriate.
|
||||||
|
|
||||||
|
### 2. Memory & Resource Management
|
||||||
|
- Replace raw owning pointers and manual `delete` with `std::unique_ptr` or `std::shared_ptr`.
|
||||||
|
- Prefer `std::unique_ptr` by default; use `std::shared_ptr` only for true shared ownership.
|
||||||
|
- Use `std::make_unique` and `std::make_shared`.
|
||||||
|
- Enforce RAII for all resource management.
|
||||||
|
- Replace manual lifetime management with scoped objects where possible.
|
||||||
|
- Distinguish clearly between owning and non-owning access; prefer references, `std::span`, or observer-style usage for non-owning views.
|
||||||
|
|
||||||
|
### 3. Containers, Views & Strings
|
||||||
|
- Use `std::string_view` for read-only string parameters where lifetime safety is guaranteed.
|
||||||
|
- Never introduce dangling `std::string_view`.
|
||||||
|
- Replace `if (items.find(key) != items.end())` with `if (items.contains(key))` where supported.
|
||||||
|
- Prefer `.starts_with()`, `.ends_with()`, and `.contains()` when they improve readability.
|
||||||
|
- Prefer `std::span` for non-owning contiguous views.
|
||||||
|
- Use `std::mdspan` for multidimensional indexing only where it meaningfully improves safety or clarity.
|
||||||
|
- Prefer standard algorithms and ranges over manual loops when they improve readability and maintainability.
|
||||||
|
- Avoid unnecessary copies; prefer move semantics, `emplace`, and views where safe.
|
||||||
|
|
||||||
|
### 4. Control Flow & Error Handling
|
||||||
|
- Prefer early returns over deep nesting.
|
||||||
|
- Use `[[nodiscard]]` for functions whose return values should not be ignored.
|
||||||
|
- Modernize `std::optional` usage with `.and_then()`, `.transform()`, and `.or_else()` where this makes the logic clearer.
|
||||||
|
- Replace sentinel values with `std::optional`, strong types, or `std::expected` if supported by the project/toolchain.
|
||||||
|
- Preserve existing exception guarantees and error behavior unless changes are explicitly requested.
|
||||||
|
|
||||||
|
### 5. Formatting & Output
|
||||||
|
- Replace `printf` and legacy `<iostream>` console output with `<print>` where toolchain support exists.
|
||||||
|
- Use `std::print` and `std::println` for standard console output.
|
||||||
|
- If `<print>` is unavailable in the project toolchain, note the limitation and prefer the most modern supported alternative.
|
||||||
|
- Do not mix output styles in the same updated code path without a strong reason.
|
||||||
|
|
||||||
|
### 6. Compile-Time Optimization & Templates
|
||||||
|
- Maximize appropriate use of `constexpr`.
|
||||||
|
- Use `consteval` and `constinit` where semantically beneficial.
|
||||||
|
- Replace legacy SFINAE / `std::enable_if` with Concepts and `requires` clauses.
|
||||||
|
- Use `if constexpr` to simplify compile-time branching.
|
||||||
|
- Prefer readable template constraints and diagnostics over complex metaprogramming.
|
||||||
|
|
||||||
|
### 7. API & Interface Modernization
|
||||||
|
- Add `noexcept` where correct and useful.
|
||||||
|
- Use `override` consistently for overridden virtual functions.
|
||||||
|
- Use `final` where appropriate.
|
||||||
|
- Prefer `= default` and `= delete` for special member functions.
|
||||||
|
- Prefer `enum class` over unscoped enums where practical.
|
||||||
|
- Replace output parameters with return values or small result structs where this improves clarity and does not break required interfaces.
|
||||||
|
|
||||||
|
### 8. Concurrency & Time
|
||||||
|
- Prefer modern standard library concurrency primitives.
|
||||||
|
- Use `std::jthread` instead of `std::thread` where automatic joining and cancellation semantics are beneficial.
|
||||||
|
- Prefer typed `std::chrono` durations and literals over raw integer time values.
|
||||||
|
|
||||||
|
## Code Style Enforcement
|
||||||
|
- Avoid C-style macros where `constexpr`, `const`, enums, or inline functions are better.
|
||||||
|
- Never introduce deprecated or removed standard library facilities.
|
||||||
|
- Prefer expressive, self-documenting code over mechanical modernization.
|
||||||
|
- Keep includes minimal and correct.
|
||||||
|
- Avoid hidden lifetime bugs, dangling references, dangling views, and ownership ambiguity.
|
||||||
|
- Preserve repository formatting and local style conventions unless explicitly changing them.
|
||||||
|
|
||||||
|
## Safety Constraints
|
||||||
|
- Do not change business logic unless explicitly requested.
|
||||||
|
- Do not silently alter ownership semantics without calling it out.
|
||||||
|
- Do not replace code with newer constructs if the result is harder to read.
|
||||||
|
- Do not introduce C++23 features that are unsupported by the project compiler/toolchain.
|
||||||
|
- Highlight any modernization that may affect ABI, performance, exception behavior, or object lifetime.
|
||||||
|
|
||||||
|
## Review Checklist
|
||||||
|
For each proposed migration, verify:
|
||||||
|
- Behavior is preserved.
|
||||||
|
- Ownership and lifetime are clearer and safer.
|
||||||
|
- Readability is improved.
|
||||||
|
- Interface compatibility is maintained unless breaking changes are allowed.
|
||||||
|
- C++23 features are applied only where beneficial.
|
||||||
|
- Toolchain compatibility is respected.
|
||||||
|
- Tests and warnings should still pass after the change.
|
||||||
|
|
||||||
|
## Expected Copilot Behavior
|
||||||
|
When modernizing code:
|
||||||
|
1. Start from the existing implementation and refactor incrementally.
|
||||||
|
2. Prefer minimal, reviewable patches over broad rewrites.
|
||||||
|
3. Briefly explain non-trivial modernizations.
|
||||||
|
4. Call out risky or behavior-adjacent changes explicitly.
|
||||||
|
5. Provide optional follow-up refactors separately when they are useful but non-essential.
|
||||||
|
6. Avoid touching unrelated code.
|
||||||
|
|
||||||
|
## Preferred Output Format
|
||||||
|
For each migration task, provide:
|
||||||
|
- the modernized code,
|
||||||
|
- a short rationale,
|
||||||
|
- any compatibility/toolchain caveats,
|
||||||
|
- and optional next-step improvements.tes
|
||||||
@@ -0,0 +1,152 @@
|
|||||||
|
Migrate the legacy Qt5/C++11 desktop application to Qt6/C++23 and validate the migration completely using the repository’s Docker-based CI workflow.
|
||||||
|
|
||||||
|
Operating mode:
|
||||||
|
- Execute the task autonomously from analysis through validation.
|
||||||
|
- Do not stop after code edits; continue until configure, build, tests, and policy checks have been attempted in the CI container workflow.
|
||||||
|
- Do not ask for confirmation between normal implementation steps.
|
||||||
|
- Only stop early if the repository is missing required source material, the task is logically impossible, or a destructive action would be required.
|
||||||
|
|
||||||
|
Project boundaries:
|
||||||
|
- Read the legacy source project from ${PROJECT_DIR}.
|
||||||
|
- Write the migrated project into qt6-after/qt6-migrated-benchmark.
|
||||||
|
- Do not modify the legacy source tree in place.
|
||||||
|
- Keep the migration isolated to the target tree and related CI/build/test files only when necessary.
|
||||||
|
|
||||||
|
Primary migration goals:
|
||||||
|
- Update the build system from Qt5 to Qt6.
|
||||||
|
- Upgrade the language standard from C++11 to C++23.
|
||||||
|
- Keep Qt Core, Gui, and Widgets explicitly linked.
|
||||||
|
- Replace QRegExp with QRegularExpression.
|
||||||
|
- Replace QDesktopWidget and QApplication::desktop() usage with QScreen-based Qt6 APIs.
|
||||||
|
- Remove legacy QTextCodec usage and adopt modern Qt6-safe text handling.
|
||||||
|
- Replace old SIGNAL/SLOT syntax with function-pointer connect syntax.
|
||||||
|
- Replace legacy null pointer literals with nullptr.
|
||||||
|
- Preserve .ui integration.
|
||||||
|
- Preserve .qrc integration.
|
||||||
|
- Preserve application behavior unless a Qt6-compatible adaptation is strictly necessary.
|
||||||
|
|
||||||
|
Testing requirements:
|
||||||
|
- For every code change inside a method, add at least three tests covering the changed behavior.
|
||||||
|
- Place all generated tests in qt6-after/qt6-migrated-benchmark/tests.
|
||||||
|
- Keep test filenames compatible with repository policy checks, for example patterns like:
|
||||||
|
- test_<name>.cpp
|
||||||
|
- <name>_test.cpp
|
||||||
|
- <name>test.cpp
|
||||||
|
- <name>gtest.cpp
|
||||||
|
- Update CMake so the migrated application and all tests are buildable and runnable with CTest.
|
||||||
|
- Ensure tests are actually registered with CTest.
|
||||||
|
|
||||||
|
Container-first build policy:
|
||||||
|
- Use lifemaps/ci-cpp:latest as the authoritative environment for configure, build, test, and policy validation.
|
||||||
|
- Do not rely on host-installed build tools as a substitute for missing container tools.
|
||||||
|
- Execute all validation commands inside Docker using the mounted repository workspace.
|
||||||
|
- Treat Dockerfile.ci as the source of truth for CI dependencies and container tool availability.
|
||||||
|
|
||||||
|
Execution plan:
|
||||||
|
1. Inspect the legacy project under ${PROJECT_DIR}.
|
||||||
|
2. Inspect the target tree qt6-after/qt6-migrated-benchmark.
|
||||||
|
3. Identify all Qt5/C++11 constructs that must be migrated.
|
||||||
|
4. Apply the migration incrementally in the target tree.
|
||||||
|
5. Add or update tests together with each behavior-relevant code change.
|
||||||
|
6. Update CMake and test registration.
|
||||||
|
7. Validate inside the Docker container.
|
||||||
|
8. If validation reveals missing tools inside the container, update Dockerfile.ci, rebuild the image, and rerun validation.
|
||||||
|
9. Repeat until full success or until a genuine project defect remains.
|
||||||
|
|
||||||
|
Mandatory container validation sequence:
|
||||||
|
- Run CMake configure inside lifemaps/ci-cpp:latest.
|
||||||
|
- Run the build inside lifemaps/ci-cpp:latest.
|
||||||
|
- Run tests with CTest inside lifemaps/ci-cpp:latest.
|
||||||
|
- Only if tests succeed, run:
|
||||||
|
python3 ci/check_pr_policies.py
|
||||||
|
inside the same Docker container against the mounted workspace.
|
||||||
|
|
||||||
|
Missing-tool remediation loop:
|
||||||
|
- If configure, build, test, or policy validation fails because a required tool or package is missing in the container:
|
||||||
|
- identify the missing tool precisely
|
||||||
|
- update Dockerfile.ci to install it
|
||||||
|
- rebuild the Docker image
|
||||||
|
- rerun the full validation sequence in the rebuilt image
|
||||||
|
- Do not stop after rebuilding once if another missing dependency appears.
|
||||||
|
- Continue until:
|
||||||
|
- the environment is complete and the next failure is a real project/code issue, or
|
||||||
|
- the entire validation flow succeeds
|
||||||
|
|
||||||
|
Failure classification rules:
|
||||||
|
- Treat these as environment failures:
|
||||||
|
- command not found
|
||||||
|
- missing compiler/toolchain utility
|
||||||
|
- missing Qt development package
|
||||||
|
- missing CMake/Ninja/CTest support tool
|
||||||
|
- missing formatting or git verification dependency needed by ci/check_pr_policies.py
|
||||||
|
- Treat these as project failures:
|
||||||
|
- compile errors in migrated source
|
||||||
|
- linker errors caused by project configuration or code
|
||||||
|
- failing tests
|
||||||
|
- policy check failures caused by formatting, missing tests, or related project issues introduced by the migration
|
||||||
|
|
||||||
|
Policy-check awareness:
|
||||||
|
- The repository policy script checks changed C/C++ files for formatting via clang-format.
|
||||||
|
- The policy script also expects related tests for changed C/C++ files.
|
||||||
|
- The policy script verifies commit signatures in its comparison range.
|
||||||
|
- When running local validation in the container, ensure the workspace and git metadata are available so the script can evaluate diffs properly.
|
||||||
|
- If the script fails because of issues caused by your migration, fix them and rerun validation.
|
||||||
|
- Do not claim policy success unless the script passes.
|
||||||
|
|
||||||
|
Container command expectations:
|
||||||
|
- Use Docker commands that mount the current repository into /workspace or an equivalent work directory.
|
||||||
|
- Run commands from the mounted repository root.
|
||||||
|
- Use explicit configure/build/test commands rather than vague summaries.
|
||||||
|
- Reuse the same image name lifemaps/ci-cpp:latest unless Dockerfile.ci changes require rebuilding that image.
|
||||||
|
|
||||||
|
Recommended validation shape:
|
||||||
|
- Configure:
|
||||||
|
cmake -S qt6-after/qt6-migrated-benchmark -B build -G Ninja -DCMAKE_BUILD_TYPE=Debug
|
||||||
|
- Build:
|
||||||
|
cmake --build build --parallel
|
||||||
|
- Test:
|
||||||
|
ctest --test-dir build --output-on-failure
|
||||||
|
- Policy:
|
||||||
|
python3 ci/check_pr_policies.py
|
||||||
|
- If the repository uses a different build directory or requires additional flags discovered during inspection, adapt accordingly.
|
||||||
|
|
||||||
|
Dockerfile maintenance rules:
|
||||||
|
- If you modify Dockerfile.ci, keep changes minimal and focused on missing CI dependencies.
|
||||||
|
- Do not remove already needed packages without evidence.
|
||||||
|
- After editing Dockerfile.ci, rebuild the CI image before retrying validation.
|
||||||
|
- Use the rebuilt image for all subsequent validation attempts.
|
||||||
|
|
||||||
|
Change reporting requirements:
|
||||||
|
- Briefly explain each migration change.
|
||||||
|
- Group the explanation by:
|
||||||
|
- CMake / build-system migration
|
||||||
|
- Qt API replacements
|
||||||
|
- C++ modernization
|
||||||
|
- UI/resource preservation
|
||||||
|
- tests added
|
||||||
|
- Dockerfile.ci / container updates
|
||||||
|
- Include a concise changed-files summary.
|
||||||
|
|
||||||
|
Completion criteria:
|
||||||
|
- Success requires all of the following:
|
||||||
|
- migrated project exists under qt6-after/qt6-migrated-benchmark
|
||||||
|
- configure succeeds in the Docker container
|
||||||
|
- build succeeds in the Docker container
|
||||||
|
- tests succeed in the Docker container
|
||||||
|
- python3 ci/check_pr_policies.py succeeds in the Docker container after tests pass
|
||||||
|
- If full success is not achieved, continue until the remaining blocker is a genuine project problem rather than a missing CI dependency.
|
||||||
|
|
||||||
|
Final response requirements:
|
||||||
|
- State whether the migration is fully validated or which blocker remains.
|
||||||
|
- List the exact Docker commands used for:
|
||||||
|
- image rebuild
|
||||||
|
- configure
|
||||||
|
- build
|
||||||
|
- test
|
||||||
|
- policy check
|
||||||
|
- For every failed attempt, report:
|
||||||
|
- the exact command
|
||||||
|
- the key error
|
||||||
|
- whether it was an environment issue or a project issue
|
||||||
|
- the fix applied, if any
|
||||||
|
- End with a short summary of what remains, if anything.
|
||||||
Executable
+50
@@ -0,0 +1,50 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
PROJECT_DIR="${1:-qt5-before/qt5-legacy-migration-benchmark}"
|
||||||
|
COPILOT_MODEL="${2:-qwen3.5-397b-a17b}"
|
||||||
|
|
||||||
|
need_cmd() {
|
||||||
|
command -v "$1" >/dev/null 2>&1 || {
|
||||||
|
echo "ERROR: '$1' not found in PATH." >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
need_cmd entire
|
||||||
|
need_cmd copilot
|
||||||
|
need_cmd git
|
||||||
|
|
||||||
|
if ! git rev-parse --show-toplevel >/dev/null 2>&1; then
|
||||||
|
echo "ERROR: Dieses Skript muss innerhalb eines bestehenden Git-Repositories gestartet werden." >&2
|
||||||
|
echo "Bitte zuerst im Repo-Root 'git init' oder in einem bestehenden Repo arbeiten." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
REPO_ROOT="$(git rev-parse --show-toplevel)"
|
||||||
|
cd "$REPO_ROOT"
|
||||||
|
|
||||||
|
if [ ! -d "$PROJECT_DIR" ]; then
|
||||||
|
echo "ERROR: project directory '$PROJECT_DIR' not found relative to repo root '$REPO_ROOT'." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Repo root: $REPO_ROOT"
|
||||||
|
echo "Legacy project: $PROJECT_DIR"
|
||||||
|
echo "Copilot model: $COPILOT_MODEL"
|
||||||
|
|
||||||
|
entire agent add copilot-cli
|
||||||
|
entire status
|
||||||
|
|
||||||
|
git add .
|
||||||
|
if git diff --cached --quiet; then
|
||||||
|
git commit --allow-empty -m "baseline: Qt5/C++11 legacy benchmark before Qt6/C++23 migration"
|
||||||
|
else
|
||||||
|
git commit -m "baseline: Qt5/C++11 legacy benchmark before Qt6/C++23 migration"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "== Checkpoints vor der Session =="
|
||||||
|
entire checkpoint list
|
||||||
|
|
||||||
|
envsubst < scripts/migration.prompt
|
||||||
Executable
+34
@@ -0,0 +1,34 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
PROJECT_DIR="${1:-qt5-before/qt5-legacy-migration-benchmark}"
|
||||||
|
COPILOT_MODEL="${2:-qwen3.5-397b-a17b}"
|
||||||
|
|
||||||
|
need_cmd() {
|
||||||
|
command -v "$1" >/dev/null 2>&1 || {
|
||||||
|
echo "ERROR: '$1' not found in PATH." >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
need_cmd entire
|
||||||
|
need_cmd copilot
|
||||||
|
need_cmd git
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "== Git status after Copilot session =="
|
||||||
|
git status --short
|
||||||
|
|
||||||
|
git add .
|
||||||
|
|
||||||
|
if git diff --cached --quiet; then
|
||||||
|
echo "No changes to commit."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
git commit -m "migrate: Qt5/C++11 app to Qt6/C++23 with tests and modern Qt APIs"
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "== Checkpoints nach der Session =="
|
||||||
|
entire checkpoint list
|
||||||
|
entire checkpoint explain HEAD || true
|
||||||
@@ -47,34 +47,7 @@ echo
|
|||||||
echo "== Checkpoints vor der Session =="
|
echo "== Checkpoints vor der Session =="
|
||||||
entire checkpoint list
|
entire checkpoint list
|
||||||
|
|
||||||
cat <<PROMPT
|
envsubst < scripts/migration.prompt | copilot --model "${COPILOT_MODEL}"
|
||||||
|
|
||||||
Use this prompt in Copilot CLI:
|
|
||||||
|
|
||||||
Migrate the legacy Qt5/C++11 desktop application to Qt6/C++23.
|
|
||||||
|
|
||||||
Requirements:
|
|
||||||
- Read the legacy source project from ${PROJECT_DIR}
|
|
||||||
- Write the migrated project into qt6-after/qt6-migrated-benchmark
|
|
||||||
- Do not modify the legacy source tree in place
|
|
||||||
- Update CMake from Qt5 to Qt6
|
|
||||||
- Keep Core, Gui, and Widgets explicitly linked
|
|
||||||
- Replace QRegExp with QRegularExpression
|
|
||||||
- Replace QDesktopWidget / QApplication::desktop() usage with QScreen-based Qt6 APIs
|
|
||||||
- Remove legacy QTextCodec usage and use modern Qt6-safe text handling
|
|
||||||
- Modernize old SIGNAL/SLOT syntax to function-pointer connect syntax
|
|
||||||
- Replace legacy null pointer literals with nullptr
|
|
||||||
- Preserve the .ui and .qrc integration
|
|
||||||
- Preserve application behavior
|
|
||||||
- Upgrade the project from C++11 to C++23
|
|
||||||
- For every code change inside a method, add at least three tests covering the changed behavior
|
|
||||||
- Place all generated tests in qt6-after/qt6-migrated-benchmark/tests
|
|
||||||
- Update CMake so the migrated application and all tests build successfully with CTest
|
|
||||||
- Keep the test file naming compatible with repository policy checks
|
|
||||||
- Briefly explain each migration change
|
|
||||||
PROMPT
|
|
||||||
|
|
||||||
copilot --model "${COPILOT_MODEL}"
|
|
||||||
|
|
||||||
echo
|
echo
|
||||||
echo "== Git status after Copilot session =="
|
echo "== Git status after Copilot session =="
|
||||||
|
|||||||
@@ -47,34 +47,7 @@ echo
|
|||||||
echo "== Checkpoints vor der Session =="
|
echo "== Checkpoints vor der Session =="
|
||||||
entire checkpoint list
|
entire checkpoint list
|
||||||
|
|
||||||
cat <<PROMPT
|
envsubst < scripts/migration.prompt | copilot --model "${COPILOT_MODEL}"
|
||||||
|
|
||||||
Use this prompt in Copilot CLI:
|
|
||||||
|
|
||||||
Migrate the legacy Qt5/C++11 desktop application to Qt6/C++23.
|
|
||||||
|
|
||||||
Requirements:
|
|
||||||
- Read the legacy source project from ${PROJECT_DIR}
|
|
||||||
- Write the migrated project into qt6-after/qt6-migrated-benchmark
|
|
||||||
- Do not modify the legacy source tree in place
|
|
||||||
- Update CMake from Qt5 to Qt6
|
|
||||||
- Keep Core, Gui, and Widgets explicitly linked
|
|
||||||
- Replace QRegExp with QRegularExpression
|
|
||||||
- Replace QDesktopWidget / QApplication::desktop() usage with QScreen-based Qt6 APIs
|
|
||||||
- Remove legacy QTextCodec usage and use modern Qt6-safe text handling
|
|
||||||
- Modernize old SIGNAL/SLOT syntax to function-pointer connect syntax
|
|
||||||
- Replace legacy null pointer literals with nullptr
|
|
||||||
- Preserve the .ui and .qrc integration
|
|
||||||
- Preserve application behavior
|
|
||||||
- Upgrade the project from C++11 to C++23
|
|
||||||
- For every code change inside a method, add at least three tests covering the changed behavior
|
|
||||||
- Place all generated tests in qt6-after/qt6-migrated-benchmark/tests
|
|
||||||
- Update CMake so the migrated application and all tests build successfully with CTest
|
|
||||||
- Keep the test file naming compatible with repository policy checks
|
|
||||||
- Briefly explain each migration change
|
|
||||||
PROMPT
|
|
||||||
|
|
||||||
copilot --model "${COPILOT_MODEL}"
|
|
||||||
|
|
||||||
echo
|
echo
|
||||||
echo "== Git status after Copilot session =="
|
echo "== Git status after Copilot session =="
|
||||||
|
|||||||
Reference in new issue
Block a user