Skip to content

Conversation

@HTRamsey
Copy link
Collaborator

Summary

Major CI/CD infrastructure improvements focused on security, performance, and maintainability.

Security Hardening

  • Add AWS OIDC support for credential-free uploads (backward compatible)
  • Add SBOM attestations with Sigstore for supply chain security
  • Standardize all actions to @v6 (checkout, upload-artifact)
  • Add harden-runner to platform workflows
  • Add CodeQL and zizmor security scanning

Performance Optimization

  • CPM package lock - Cache invalidates only on dependency changes, not all CMake files
  • ARM64 ccache - Enable compiler caching for Linux/Windows ARM builds
  • GStreamer consolidation - 614→98 lines (84% reduction) via matrix strategy
  • Add retry wrapper for transient network failures
  • Standardize timeouts across all workflows

New Capabilities

  • GStreamer build-from-source workflows for all platforms
  • Performance metrics workflow with artifact size tracking
  • MAVLink benchmark for regression detection
  • JUnit XML test output with GitHub annotations
  • Manual clazy, IWYU, and sanitizer workflows

Consolidation

  • Merge analysis workflows (clazy/iwyu/sanitizers)
  • Create reusable composite actions (build-setup, cache, upload)
  • Simplify CMake presets with default caching

Documentation

  • Condense tools/ README files

Test Plan

  • CPM lock file tested locally - cache key stable on unrelated CMake changes
  • CI workflows pass on this PR
  • AWS upload still works with existing static credentials
  • GStreamer builds succeed on all platforms

Migration Notes

AWS OIDC (optional): Once AWS IAM role is configured, add AWS_ROLE_ARN secret. Current static credentials continue working.

CPM lock update: Run cmake --build build --target cpm-update-package-lock when dependencies change.

- Uncomment CodeQL init and analyze steps in linux.yml (Debug builds)
- Add zizmor pre-commit hook for GitHub Actions security scanning
Add --unittest-output CLI option to generate JUnit XML test results:
- QGCCommandLineParser: Add --unittest-output <file> option
- UnitTest::run(): Pass -o flag to QTest::qExec() when output specified
- UnitTestList::runTests(): Thread output file parameter through

Update linux.yml CI workflow:
- Use --unittest-output to generate junit-results.xml
- Add dorny/test-reporter for PR test visualization
- Activate trunk.io flaky test detection (requires TRUNK_ORG_SLUG/TOKEN)
- Include JUnit XML in test artifacts
Upload action improvements:
- Add retention_days input (default: 7 for PRs, 30 for pushes)
- Add compression_level input (use 0 for pre-compressed binaries)

Linux workflow:
- Dynamic test artifact retention (3 days for PRs, 14 for pushes)
- Add unity_build workflow_dispatch input (experimental, opt-in)
- Unity Build uses batch size 16 for optimal parallelization

Note: Submodule caching skipped - QGC has no submodules
- Replace actions/setup-java gradle cache with gradle/actions/setup-gradle@v4
- Add cache-read-only for PR builds (save storage)
- Enable gradle-home-cache-cleanup to remove stale entries
- Add GRADLE_OPTS to enable configuration cache and build caching

NDK caching already in place via nttld/setup-ndk with local-cache: true
Restore file timestamps from git history after checkout to improve
ccache hit rates. Without this, all files appear modified at checkout
time, causing ccache misses on unchanged files.

Changes:
- Add chetan/git-restore-mtime-action@v2 to ios.yml and macos.yml
- Use fetch-depth: 0 (required for mtime restoration)
Merge queue support:
- Add merge_group trigger to linux, windows, macos, android workflows
- Enables GitHub merge queue for automated PR merging

SBOM attestation:
- Add actions/attest-sbom@v3 for release artifacts (AppImage, DMG, EXE, APK)
- Uses SPDX SBOM generated by anchore/sbom-action
- Add job-level permissions (id-token, attestations) for signing
Refactor release workflow for manual version control:
- Trigger on tag push (v*) instead of workflow_dispatch
- Remove semantic-release job and Node.js dependency
- Remove tools/release.sh (no longer needed)
- Simplify to: wait-for-builds → upload-artifacts

Flow: push tag → platform builds run → release workflow waits →
downloads artifacts → generates SBOMs → attests → uploads to release
Clazy workflow (workflow_dispatch):
- Input: path to analyze (file or directory)
- Option to analyze all source files
- Generates compile_commands.json then runs clazy
- Uses tools/analyze.sh for consistent analysis

Sanitizers workflow (workflow_dispatch):
- Choice of ASAN, UBSAN, TSAN, or ASAN+UBSAN
- Debug build with sanitizer flags
- Runs unit tests and checks for sanitizer errors
- Uploads output as artifact for debugging
Manual workflow_dispatch trigger for IWYU analysis:
- Optional path input to analyze specific directories
- Uses Clang compiler with cmake/modules/IWYU.cmake
- Outputs include suggestions to artifact
- Useful for cleaning up unnecessary #includes

Note: Qt generates many false positives, review suggestions carefully
Skip unnecessary Docker builds on PRs when only one platform's files
changed:
- If only android/** changes, skip Linux Docker build (~2 hours saved)
- If only deploy/linux/** changes, skip Android Docker build
- If shared files (src/**, cmake/**) change, build both platforms

Uses dorny/paths-filter@v3 to detect which paths changed, then
conditionally skips build steps for unaffected platforms.
Consolidate repeated setup steps into a reusable composite action:
- Harden Runner
- Checkout with configurable fetch-depth
- build-config
- common
- cache
- qt-install

Applied to linux.yml, windows.yml, macos.yml workflows.
Reduces duplication by ~79 lines across workflows.

Platform-specific steps (dependencies, Xcode, MSVC, CodeQL, packaging)
remain in individual workflows.
Add manual dispatch workflows to build GStreamer with only the plugins
needed for QGC video streaming (RTSP, RTP, UDP, H.264/H.265, MPEG-TS,
Qt6 integration).

Workflows:
- build-gstreamer-windows.yml: Native and cross-compile for x64/ARM64
- build-gstreamer-macos.yml: Universal, ARM64, or x86_64 builds
- build-gstreamer-linux.yml: x86_64 and aarch64 builds
- build-gstreamer-ios.yml: Device and simulator builds via Cerbero
- build-gstreamer-android.yml: All ABIs via Cerbero

Build scripts in tools/setup/gstreamer/:
- Windows uses Meson with MSVC, supports ARM64 cross-compilation
- macOS uses Meson with universal binary support via lipo
- Linux uses Meson with VA-API and Wayland support
- iOS/Android use GStreamer's Cerbero build system

Features:
- Version configurable or read from build-config.json
- Artifacts uploaded to GitHub (30 days) and S3
- Qt6 integration for qml6 video sink plugin
- Minimal plugin set reduces binary size

Also updates:
- src/pch.h: Optimize precompiled header includes
- install-dependencies-windows.ps1: ARM64 GStreamer support
Add workflow that tracks reliable size metrics and optional runtime
benchmarks using benchmark-action/github-action-benchmark.

Size metrics (reliable, no variance):
- Binary size (raw and stripped)
- Symbol count
- Section sizes via `size -A`
- Top symbols and compilation units via bloaty

Runtime benchmarks (optional, on push to master):
- Catch2 benchmarks if available
- Falls back to startup time measurement
- 150% threshold for alerts (accounts for runner variance)

Features:
- Charts published to GitHub Pages at /dev/size and /dev/bench
- PR comments on size regressions >5%
- Only runs on src/cmake changes
- Manual dispatch option to force benchmark run

Note: Runtime benchmarks have ~3x variance on shared runners.
Size metrics are the reliable indicator for tracking bloat.
Add Qt Test benchmarks for core MAVLink operations:
- benchmarkHeartbeatPack: Pack heartbeat message (most frequent)
- benchmarkHeartbeatUnpack: Unpack heartbeat message
- benchmarkAttitudePack: Pack attitude (high-frequency telemetry)
- benchmarkAttitudeUnpack: Unpack attitude
- benchmarkGpsRawPack: Pack GPS raw (complex payload)
- benchmarkMessageRoundTrip: Full pack + CRC + unpack cycle
- benchmarkParseByteStream: Parse message from byte stream

Run locally with:
  ./QGroundControl --unittest:MAVLinkBenchmark

Updates performance.yml workflow to:
- Run MAVLinkBenchmark on push to master
- Parse Qt Test QBENCHMARK output to JSON
- Track results via github-action-benchmark

These benchmarks measure operations critical for real-time vehicle
communication. Results are normalized to microseconds per iteration.
- Enable ccache by default for Linux, macOS, Android, iOS
- Enable sccache by default for Windows
- Remove separate ccache/sccache preset variants
- Keep only essential presets: release, debug, coverage (Linux)
- Add usage documentation to CMakePresets.json.template
- Add platform conditions to show relevant presets only
- Downgrade CMake preset version from 6 to 5 for Qt Creator compatibility
- Comment out relative paths in ccache.conf (CMake sets via env vars)

The relative paths caused ccache errors when IDEs loaded the config
directly without CMake's environment variable overrides.
Workflow consolidation (~320 lines saved):
- Merge clazy/iwyu/sanitizers into single analysis.yml with tool selector
- Merge 5 GStreamer build workflows into single build-gstreamer.yml
- Merge Crowdin upload/download into single crowdin.yml

Security and reliability:
- Add harden-runner to GStreamer and performance workflows
- Add timeout-minutes to performance.yml jobs (60/90 min)
- Use build-config and qt-install actions in performance.yml
- Standardize artifact retention-days (flatpak.yml: 14 days)
- Enable iOS workflow on push/PR (was manual-only, never tested)

The consolidated workflows use conditional jobs based on input parameters,
reducing duplication while maintaining platform-specific configurations.
GStreamer build consolidation:
- Merge 5 duplicate jobs (640 lines) into single parameterized job (98 lines)
- Create unified gstreamer action handling all platforms
- Dynamic runner selection based on platform/arch inputs
- Single action handles: deps, Qt, build, verify, archive, S3 upload, summary

Python setup consolidation:
- Add tools/pyproject.toml with dependency groups (ci, qt, coverage, dev, lsp)
- Add tools/setup/install-python.sh for local development (uses uv or pip)
- Add setup-python composite action that calls the script
- Skip pip installs in Qt/GStreamer scripts if tools already available

Action simplifications:
- build-config: Use read-config.sh --github-output (125→67 lines)
- install-dependencies: Use nick-fields/retry@v3 (115→85 lines)
- read-config.sh: Add --github-output and --get modes

Total reduction: ~300 lines removed, improved maintainability
- Add aws_role_arn input to aws-upload and upload actions
- Both OIDC and static credentials work via conditional steps
- OIDC preferred when AWS_ROLE_ARN secret exists, falls back to static
- Update all platform workflows to pass aws_role_arn
- Reduce GStreamer build timeout from 180 to 120 minutes

Migration: Once AWS IAM role is configured, add AWS_ROLE_ARN secret
and optionally remove AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY.
Remove redundant content and streamline documentation for tools/,
tools/coding-style/, and tools/qtcreator/ directories.
- Add CPMUsePackageLock() to CMakeLists.txt
- Generate and commit package-lock.cmake with versioned dependencies
- Update cache action to hash only lock file instead of all CMake files

This eliminates spurious cache invalidation when CMake files change
without affecting dependencies. Update lock with:
  cmake --build build --target cpm-update-package-lock
Copilot AI review requested due to automatic review settings December 27, 2025 05:38
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This is a comprehensive GitHub Actions infrastructure overhaul focused on security, performance, and maintainability improvements for the QGroundControl CI/CD pipeline.

Key Changes:

  • Security: AWS OIDC authentication, SBOM attestations, harden-runner, CodeQL/zizmor scanning, action version standardization (@v6)
  • Performance: CPM package lock caching (cache only on dependency changes), ARM64 ccache support, GStreamer workflow consolidation (614→98 lines), retry wrappers for network failures
  • New Capabilities: GStreamer build-from-source workflows for all platforms, performance metrics tracking, MAVLink benchmarks, JUnit XML test output with GitHub annotations

Reviewed changes

Copilot reviewed 64 out of 65 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
tools/setup/read-config.sh Added --github-output mode for CI integration
tools/setup/install-python.sh New unified Python environment setup with uv support
tools/setup/install-qt-*.{sh,ps1} Skip reinstallation if aqtinstall exists (venv optimization)
tools/setup/install-dependencies-windows.ps1 ARM64 GStreamer support via ZIP archives
tools/setup/gstreamer/build-gstreamer-*.{sh,ps1} New cross-platform GStreamer build scripts
package-lock.cmake CPM dependency lock file for stable caching
cmake/presets/*.json Consolidated presets, downgraded version 6→5, added ARM64 variants
test/**/UnitTest.* JUnit XML output support
test/MAVLink/MAVLinkBenchmark.* New MAVLink performance benchmarks
src/pch.h Optimized precompiled headers
.github/workflows/*.yml Security hardening, performance tracking, consolidation
.github/actions/build-setup/ New composite action consolidating setup steps
.github/actions/gstreamer/ Comprehensive GStreamer build action
.github/actions/cache/ ARM64 ccache, CPM lock-based caching
.github/actions/aws-upload/ OIDC authentication support
tools/README.md Condensed documentation
.pre-commit-config.yaml Added zizmor security scanning

@@ -1,37 +1,25 @@
{
"version": 6,
"version": 5,
Copy link

Copilot AI Dec 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Downgrading CMake presets from version 6 to version 5 may lose features. CMake 3.25 (specified in cmakeMinimumRequired) supports preset version 5, but newer CMake versions support version 6 with additional features. Verify that no version 6-specific features are needed, or document why the downgrade is necessary.

Copilot uses AI. Check for mistakes.
key: ${{ github.workflow }}-cpm-modules-${{ hashFiles('**/CMakeLists.txt', '**/*.cmake') }}
restore-keys: ${{ github.workflow }}-cpm-modules-
key: ${{ github.workflow }}-cpm-${{ hashFiles('package-lock.cmake') }}
restore-keys: ${{ github.workflow }}-cpm-
Copy link

Copilot AI Dec 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The cache key now depends only on package-lock.cmake instead of all CMakeLists.txt and .cmake files. This is a significant improvement for cache hit rates, but ensure that the CPM lock file is properly updated when dependencies change. Consider adding a CI check or pre-commit hook to verify package-lock.cmake is in sync with dependency declarations.

Suggested change
restore-keys: ${{ github.workflow }}-cpm-

Copilot uses AI. Check for mistakes.
Comment on lines +16 to 29
wait-for-builds:
name: Wait for Platform Builds
runs-on: ubuntu-latest
timeout-minutes: 15
outputs:
new_release: ${{ steps.release.outputs.new_release }}
version: ${{ steps.release.outputs.version }}
timeout-minutes: 180

steps:
- name: Harden Runner
uses: step-security/harden-runner@v2
with:
egress-policy: audit

- name: Checkout
uses: actions/checkout@v6
with:
fetch-depth: 0
persist-credentials: false

- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: 'lts/*'

- name: Run semantic-release
id: release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
./tools/release.sh --install
# Capture semantic-release output
set +e
OUTPUT=$(./tools/release.sh --run 2>&1)
EXIT_CODE=$?
echo "$OUTPUT"
set -e
# Check if a new release was created
if echo "$OUTPUT" | grep -q "Published release"; then
VERSION=$(printf '%s\n' "$OUTPUT" | sed -n 's/.*Published release \([0-9]\+\.[0-9]\+\.[0-9]\+\).*/\1/p' | head -n1)
echo "new_release=true" >> $GITHUB_OUTPUT
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "New release: v$VERSION"
else
echo "new_release=false" >> $GITHUB_OUTPUT
echo "No new release"
fi
wait-for-builds:
name: Wait for Platform Builds
needs: semantic-release
if: needs.semantic-release.outputs.new_release == 'true'
runs-on: ubuntu-latest
timeout-minutes: 180

steps:
- name: Wait for builds to complete
uses: int128/wait-for-workflows-action@v1
with:
Copy link

Copilot AI Dec 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The release workflow no longer validates that semantic-release created a new release before waiting for builds. This means the workflow will wait for builds even if no release was created. Consider adding a check to skip the wait-for-builds step if the tag doesn't trigger any platform builds, or document that this is intentional for manual tag pushes.

Copilot uses AI. Check for mistakes.
- Create qt-ios composite action (replaces 7 steps with 1)
- Create test-report composite action for unified test reporting
- Refactor qt-android to use qt-install composite action
- Refactor gstreamer action to use qt-install instead of direct jurplel
- Update all platform workflows to use install-dependencies action
- Add restore-timestamps option to build-setup action
- Add --autodesktop flag to Qt install scripts for cross-compilation
- Add libpulse-dev to Linux dependencies (audio support)
- Consolidate ccache install steps with arch parameterization
- Add minisign verification for ccache binaries (supply chain security)
- Update ccache to 4.12.2
- Fix shell quoting in gstreamer action (use env vars)
- Fix GSTREAMER_MACOS_VERSION variable name in macOS script
- Add CMakeLists.txt to CPM cache key
- Add logs/ to gitignore (puppeteer MCP)
Security (H2):
- Add step-security/harden-runner to 10 utility workflows
- Consistent security hardening across all workflows

New actions (M1):
- Create checkout-setup composite action with optional harden-runner
  and initial-setup flags for flexible reuse

Reliability (M3):
- Add nick-fields/retry to gstreamer apt-get steps (Linux, Android)
- Consistent retry behavior across all dependency installations

Consolidation (M4, M5, M6):
- Update performance.yml to use install-dependencies action
- Update analysis.yml to use install-dependencies for iwyu/sanitizers
- Update custom-build.yml to use install-dependencies action
- Reduces code duplication and ensures consistent retry behavior
Local composite actions require the repository to be checked out before
they can be used. The build-setup action contains checkout but can't be
invoked until checkout happens first.

Fixes:
- Linux, MacOS, Windows workflows: Add checkout step before build-setup
- setup-python action: Set cache-dependency-glob="" since no uv.lock exists

This resolves "Can't find action.yml" errors in CI.
GitHub Actions composite actions do not support pre/post execution hooks.
The step-security/harden-runner action uses these hooks, causing "'pre'
execution is not supported for local action" errors.

Fixes:
- Remove harden-runner from build-setup and checkout-setup actions
  (workflows already have harden-runner at job level)
- Change qt-install to use setup-python: true so jurplel/install-qt-action
  manages its own Python with aqtinstall, instead of using project venv
Fixes:
- Skip sccache for Windows ARM64 (no binaries available, 404 error)
- Use ccache instead of sccache for Windows ARM64 native builds
- Download minisign from GitHub releases instead of apt (not in Ubuntu repos)
- Handle both x86_64 and aarch64 minisign binaries for Linux builds
- Explicitly set CMAKE_OSX_ARCHITECTURES=arm64 for iOS to avoid x86_64h
- Remove gstreamer_good_plugins from package-lock.cmake to allow
  version to match per-platform GStreamer binaries (Android uses
  1.22.12, others use 1.24.13). Locking caused header mismatches
  where 1.24.13 sources required gst-plugins-bad headers not in
  1.22.12 Android binaries.

- Fix iOS x86_64h architecture error by using CMake initial cache
  file to set CMAKE_OSX_ARCHITECTURES before platform detection.
  CMake 4.x on ARM Macs defaults to multi-arch builds including
  x86_64h which doesn't exist for iOS.

- Fix bloaty installation in performance workflow by building from
  source since it's not in Ubuntu apt repositories. Includes timeout
  to prevent CI hangs.
iOS:
- Pass CMAKE_OSX_ARCHITECTURES directly on command line instead of via
  -C cache file. CMake 4.x runs platform detection before processing
  cache files, causing it to try building for x86_64h on ARM Macs.
  Command-line -D options take precedence and are applied earlier.

Size Metrics:
- Fix binary path from build/QGroundControl to build/Release/QGroundControl.
  With CMAKE_BUILD_TYPE=Release, CMake places the binary in a Release/
  subdirectory. Add fallback to handle both paths.
- Fix the same path issue in Bloaty analysis and benchmarks steps.
CMake:
- Pin to CMake 3.31.6 in common action. CMake 4.x has breaking changes
  for Apple platforms causing x86_64h architecture detection issues on
  ARM runners. This fixes both iOS and macOS builds.

macOS:
- Add explicit CMAKE_OSX_ARCHITECTURES=arm64 for extra robustness.

Performance:
- Add continue-on-error to PR comparison step since gh-pages branch
  may not exist yet (first run of size metrics).
@HTRamsey HTRamsey force-pushed the ci/github-actions-improvements branch 2 times, most recently from 879d2b7 to 8343711 Compare January 1, 2026 06:03
Use qt-cmake directly without architecture overrides or toolchain
wrappers. Let Qt's toolchain handle platform detection natively.
@HTRamsey HTRamsey force-pushed the ci/github-actions-improvements branch from 8343711 to 79e6cdf Compare January 1, 2026 06:05
- Fix coverage/action.yml path to coverage-comment.py script
- Remove unused checkout-setup action (checkout must be in workflow)
- Inline coverage-comment functionality into coverage action
- Use build-setup in custom-build workflow instead of manual steps
- Delete checkout-setup and coverage-comment actions (no references)
- size-metrics uploads the built binary as artifact
- benchmarks downloads binary instead of rebuilding
- Reduces benchmarks timeout from 90 to 30 minutes
- Saves ~30 minutes of redundant build time
@HTRamsey HTRamsey marked this pull request as draft January 2, 2026 03:59
Phase 1 - Bug fixes:
- Fix coverage.sh XML_ONLY logic bug (both branches were identical)
- Add get_default_branch() to common.sh for dynamic branch detection
- Fix configure.sh unsafe glob expansion (ls -d $pattern)
- Add error verification to qgc-lupdate.sh

Phase 2 - Consolidation (~1,630 lines removed):
- Delete 4 legacy gstreamer shell scripts (build-gstreamer.py is unified)
- Extend install-qt.py with Android/iOS support, convert shell to wrappers
- Simplify read-config.sh (153→41 lines) and read-config.ps1 (174→72 lines)
- Consolidate logging: configure.sh, run-tests.sh, profile.sh now source common.sh

Phase 3 - Infrastructure:
- Add tools/smoke-test.sh for end-to-end tool validation
- Add --timeout option to profile.sh (prevents CI hangs)
- Improve clean.sh --dry-run with sizes and summary
- Add tools/lint-fix.sh for auto-applying formatting fixes

Architecture: Python as single source of truth with thin shell wrappers.
Phase 2 - Cleanup & Consistency:
- Rename param-docs.py → param_docs.py, update-headers.py → update_headers.py
- Delete build-gstreamer-windows.ps1 (Python handles Windows)
- Fix relative paths in coverage action to use github.workspace

Phase 3 - Platform Portability:
- Add CCACHE_PREFIX env var override in install_ccache.py
- Add GSTREAMER_PREFIX env var override in gstreamer_archive.py
- Add Linux/macOS AWS CLI installation support
- Add run_command() helper for better subprocess error output

Phase 4 - Testing & Documentation:
- Add unit tests for install_ccache.py (10 tests)
- Add unit tests for gstreamer_archive.py (14 tests)
- Add unit tests for generate-matrix.py (6 tests)
- Create .github/scripts/README.md documenting CI scripts
- Update tools/README.md with Python-first script listing
- Add pyproject.toml entry points for CLI tools
- Add .envrc for direnv development environment
The generated translation file belongs in translations/, not tools/translations/.
Accidentally committed during the tools overhaul.
- Remove unused 'docs' output from all platform workflows
- Consolidate Python setup to use 3.12 consistently across:
  - common/action.yml
  - performance.yml benchmarks job
  - Remove redundant setup from qt-install/action.yml
- Extract duplicate attestation condition checks into new
  attest-condition action (used by attest and attest-sbom)
- Remove unused --no-fail backwards compat flag from check_sizes.py
- Create detect-changes action for platform-specific path filtering
- Create generate-matrix action for sparse checkout + matrix generation
- Convert build-action to Python script with tests
- Add build_action.py for building GitHub Actions from source
- Continue Python migration for tools/ directory
- Create common/logging.py with unified Colors and Logger classes
- Create common/errors.py with QGCToolError exception hierarchy
- Add shared pytest fixtures in tests/conftest.py
- Add test suites for 7 Python tools (119 new tests):
  - test_analyze.py (24 tests)
  - test_check_deps.py (12 tests)
  - test_lint_fix.py (18 tests)
  - test_coverage_tool.py (13 tests)
  - test_generate_docs.py (15 tests)
  - test_pre_commit.py (15 tests)
  - test_run_tests_tool.py (22 tests)
- Refactor scripts to use common utilities (net -293 lines)
- Fix factgroup generator msg_id_constant to use uppercase
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant