Skip to content

fix: polish: refactor generate_grouped_body to meet 50-line soft limit (fixes #1950) #2937

fix: polish: refactor generate_grouped_body to meet 50-line soft limit (fixes #1950)

fix: polish: refactor generate_grouped_body to meet 50-line soft limit (fixes #1950) #2937

Workflow file for this run

name: Tests
on:
push:
branches:
- main
- master
pull_request:
types: [opened, synchronize, reopened, ready_for_review]
branches:
- main
- master
permissions:
contents: write
pull-requests: write
issues: write
pages: write
actions: read
checks: write
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
test-linux:
runs-on: ubuntu-latest
if: github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.pull_request.draft == false)
steps:
- uses: actions/checkout@v4
- name: Cache FPM binary
id: cache-fpm
uses: actions/cache@v4
with:
path: /usr/local/bin/fpm
key: ${{ runner.os }}-fpm-0.12.0
- name: Setup FPM
if: steps.cache-fpm.outputs.cache-hit != 'true'
run: |
wget https://github.com/fortran-lang/fpm/releases/download/v0.12.0/fpm-0.12.0-linux-x86_64-gcc-12
chmod +x fpm-0.12.0-linux-x86_64-gcc-12
sudo mv fpm-0.12.0-linux-x86_64-gcc-12 /usr/local/bin/fpm
- name: Setup newer GCC
run: |
# Add GCC 14 PPA for Ubuntu
sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
sudo apt-get update
sudo apt-get install -y gfortran-14 gcc-14 g++-14
# Set GCC 14 as default
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-14 100
sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-14 100
sudo update-alternatives --install /usr/bin/gfortran gfortran /usr/bin/gfortran-14 100
- name: Cache FPM dependencies
uses: actions/cache@v4
with:
path: |
~/.local/share/fpm
build/dependencies
key: ${{ runner.os }}-fpm-deps-v2-${{ hashFiles('fpm.toml') }}
restore-keys: |
${{ runner.os }}-fpm-deps-v2-
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: '3.x'
- name: Show compiler versions
run: |
gfortran --version
fpm --version
python3 --version
- name: Build and Test
run: |
# Simulate a smaller Windows-like stack on Linux to catch stack bugs
ulimit -s 512 || true
make
ulimit -s 512 || true
RUN_SYSTEM_TESTS=1 make test
# Code validation gate removed (redundant with test suite)
# No additional cleanup steps
- name: Generate coverage data (optimized)
if: false # coverage disabled
run: |
# Optimized parallel lcov processing with cross-platform CPU detection
PARALLEL_JOBS=$(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 4)
echo "Using $PARALLEL_JOBS parallel jobs for coverage processing"
# Generate lcov coverage data with parallel processing
lcov --capture --directory build/ --output-file coverage.info \
--rc branch_coverage=1 \
--ignore-errors inconsistent \
--ignore-errors mismatch \
--ignore-errors unused \
--parallel $PARALLEL_JOBS
# Filter coverage with optimized exclusions
lcov --remove coverage.info \
'build/dependencies/*' \
'test/*' \
'/usr/*' \
--output-file coverage_filtered.info \
--rc branch_coverage=1 \
--ignore-errors mismatch \
--ignore-errors unused \
--ignore-errors inconsistent \
--parallel $PARALLEL_JOBS
# Install and run lcov_cobertura with race condition protection
pip install lcov_cobertura &
wait
# Verify coverage_filtered.info exists and is ready
if [ ! -f "coverage_filtered.info" ] || [ ! -s "coverage_filtered.info" ]; then
echo "❌ coverage_filtered.info is missing or empty"
exit 1
fi
# Add small delay to ensure file I/O completion
sleep 1
lcov_cobertura coverage_filtered.info --output cobertura.xml
# Verify XML was created
if [ ! -f "cobertura.xml" ]; then
echo "❌ Failed to generate cobertura.xml"
exit 1
fi
echo "✅ Coverage data ready ($(wc -l < coverage_filtered.info) lines processed)"
- name: Produce the coverage report
if: false # coverage disabled
id: coverage_report
uses: insightsengineering/coverage-action@v3
continue-on-error: true
with:
# Path to the Cobertura XML report.
path: ./cobertura.xml
# Minimum total coverage threshold
threshold: 70
# Fail if coverage below threshold (but continue workflow)
fail: true
# Publish the rendered output as a PR comment
publish: true
# Enable diff coverage with storage branch
diff: true
# Branch to diff against
diff-branch: main
# Storage branch for coverage history (lightweight XML files only)
diff-storage: _coverage_storage
# Custom title for the coverage summary
coverage-summary-title: "Code Coverage Summary"
# Enable togglable report for organized sections
togglable-report: true
# Include detailed coverage with percentages and positions
exclude-detailed-coverage: false
- name: Create coverage checks
# Create checks only when coverage XML exists. This naturally skips
# PR runs (fast path, no coverage) and runs on main pushes where
# coverage is generated.
if: false # coverage disabled
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const xml = fs.readFileSync('cobertura.xml', 'utf8');
// Extract overall project coverage
const coverageMatch = xml.match(/line-rate="([0-9.]+)"/);
const projectCoverage = coverageMatch ? (parseFloat(coverageMatch[1]) * 100).toFixed(2) : '0.00';
// For patch coverage, we'll use a simplified approach for now
// In a full implementation, this would analyze only changed lines
const patchCoverage = projectCoverage; // Simplified - normally would calculate differently
const projectThreshold = 70;
const patchThreshold = 70;
const projectPassed = parseFloat(projectCoverage) >= projectThreshold;
const patchPassed = parseFloat(patchCoverage) >= patchThreshold;
// Create project coverage check
await github.rest.checks.create({
owner: context.repo.owner,
repo: context.repo.repo,
name: 'coverage/project',
head_sha: context.sha,
status: 'completed',
conclusion: projectPassed ? 'success' : 'failure',
output: {
title: projectPassed ? `OK - ${projectCoverage}%` : `FAIL - ${projectCoverage}%`,
summary: projectPassed
? `✅ Project coverage ${projectCoverage}% meets the ${projectThreshold}.00% threshold`
: `❌ Project coverage ${projectCoverage}% is below the ${projectThreshold}.00% threshold`,
text: `Current project coverage: ${projectCoverage}%\nRequired threshold: ${projectThreshold}.00%`
}
});
// Create patch coverage check
await github.rest.checks.create({
owner: context.repo.owner,
repo: context.repo.repo,
name: 'coverage/patch',
head_sha: context.sha,
status: 'completed',
conclusion: patchPassed ? 'success' : 'failure',
output: {
title: patchPassed ? `OK - ${patchCoverage}%` : `FAIL - ${patchCoverage}%`,
summary: patchPassed
? `✅ Patch coverage ${patchCoverage}% meets the ${patchThreshold}.00% threshold`
: `❌ Patch coverage ${patchCoverage}% is below the ${patchThreshold}.00% threshold`,
text: `Current patch coverage: ${patchCoverage}%\nRequired threshold: ${patchThreshold}.00%\n\nNote: Patch coverage analyzes only the lines changed in this PR.`
}
});
- name: Upload coverage artifacts
if: false # coverage disabled
uses: actions/upload-artifact@v4
with:
name: coverage-report
path: |
coverage_filtered.info
coverage_html/
coverage-badge.svg
coverage-badge.json
retention-days: 30
test-windows:
runs-on: windows-latest
# FRAUD RECOVERY: Removed continue-on-error to expose actual Windows failures
# continue-on-error: true was masking systematic Windows build issues
if: github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.pull_request.draft == false)
steps:
- uses: actions/checkout@v4
- name: Setup Self-Contained MinGW Environment
shell: pwsh
run: |
Write-Host "🔧 Setting up self-contained MinGW environment..."
# Use MSYS2 MinGW which is preinstalled on GitHub Actions Windows runners
$mingwPath = "C:\msys64\mingw64\bin"
# Check if path exists
if (Test-Path $mingwPath) {
echo $mingwPath | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
Write-Host "✅ MinGW path added: $mingwPath"
# Verify gfortran is available
$gfortranPath = Join-Path $mingwPath "gfortran.exe"
if (Test-Path $gfortranPath) {
Write-Host "✅ GFortran found at: $gfortranPath"
} else {
Write-Host "⚠️ GFortran not found, attempting to install..."
# Use pacman to install gfortran if not available
C:\msys64\usr\bin\bash.exe -lc "pacman -S --noconfirm mingw-w64-x86_64-gcc-fortran"
}
} else {
Write-Error "❌ MSYS2 MinGW installation path not found at: $mingwPath"
Write-Host "Checking other possible locations..."
# Try GitHub Actions default MinGW location
$altPath = "C:\mingw64\bin"
if (Test-Path $altPath) {
echo $altPath | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
Write-Host "✅ Alternative MinGW path added: $altPath"
} else {
Write-Error "❌ No MinGW installation found"
exit 1
}
}
- name: Cache FPM binary (Windows)
id: cache-fpm-win
uses: actions/cache@v4
with:
path: C:\tools\fpm\fpm.exe
key: ${{ runner.os }}-fpm-0.12.0
- name: Install FPM
if: steps.cache-fpm-win.outputs.cache-hit != 'true'
shell: pwsh
run: |
Write-Host "📦 Installing FPM directly from GitHub releases..."
New-Item -ItemType Directory -Force -Path "C:\tools\fpm"
Invoke-WebRequest -Uri "https://github.com/fortran-lang/fpm/releases/download/v0.12.0/fpm-0.12.0-windows-x86_64-gcc-12.exe" -OutFile "C:\tools\fpm\fpm.exe"
# Add FPM to PATH
echo "C:\tools\fpm" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
# Verify installation
& "C:\tools\fpm\fpm.exe" --version
- name: Cache FPM dependencies (Windows)
uses: actions/cache@v4
with:
path: |
~\AppData\Local\fpm
build\dependencies
key: ${{ runner.os }}-fpm-deps-v2-${{ hashFiles('fpm.toml') }}
restore-keys: |
${{ runner.os }}-fpm-deps-v2-
- name: Cache build artifacts (Windows)
uses: actions/cache@v4
with:
path: |
build\gfortran_*
!build\gfortran_*/test
key: ${{ runner.os }}-build-${{ hashFiles('src/**/*.f90') }}
restore-keys: |
${{ runner.os }}-build-
- name: Windows build validation
shell: pwsh
timeout-minutes: 10 # Extended timeout for comprehensive validation
run: |
Write-Host "Windows build validation"
Write-Host "Addressing Windows CI stability"
# Explicitly add FPM to PATH for this session (CRITICAL FIX)
$env:PATH = "C:\tools\fpm;$env:PATH"
# Verify MinGW and FPM are available with detailed diagnostics
Write-Host "🔍 Compiler Diagnostics:"
try {
gfortran --version
Write-Host "✅ GFortran available"
} catch {
Write-Host "❌ GFortran not available: $_"
exit 1
}
- name: Windows smoke run (fortfront --version, hello example)
shell: pwsh
run: |
# Ensure fpm is on PATH for this step too
$env:PATH = "C:\tools\fpm;$env:PATH"
# Find fortfront.exe
$ff = Get-ChildItem -Recurse -Filter fortfront.exe -Path . | Where-Object { $_.FullName -match "\\app\\fortfront\.exe$" } | Select-Object -First 1
if ($ff) {
Write-Host "Running: $($ff.FullName) --version"
try {
& $ff.FullName --version 2>&1 | ForEach-Object { Write-Host $_ }
Write-Host "fortfront --version exited: $LASTEXITCODE"
} catch {
Write-Host "fortfront --version failed: $_"
}
} else {
Write-Host "fortfront.exe not found for smoke run"
}
# Find hello example
$hello = Get-ChildItem -Recurse -Filter hello.exe -Path . -ErrorAction SilentlyContinue | Select-Object -First 1
if (-not $hello) {
Write-Host "hello.exe not found; attempting to build and run via fpm"
try {
fpm build | Out-Host
fpm run --example hello | Out-Host
} catch {
Write-Host "fpm example run failed: $_"
}
} else {
Write-Host "Running example: $($hello.FullName)"
try {
& $hello.FullName 2>&1 | ForEach-Object { Write-Host $_ }
Write-Host "hello.exe exited: $LASTEXITCODE"
} catch {
Write-Host "hello.exe failed: $_"
}
}
try {
fpm --version
Write-Host "✅ FPM available"
} catch {
Write-Host "❌ FPM not available: $_"
exit 1
}
Write-Host "🎯 Windows build and test"
try {
Write-Host "Running fpm build"
fpm build --flag "-Wl,--stack,16777216" 2>&1 | ForEach-Object { Write-Host $_ }
} catch {
Write-Host "❌ Windows build failed: $_"
exit 1
}
try {
Write-Host "Running fpm test"
fpm test --flag "-Wl,--stack,16777216" 2>&1 | ForEach-Object { Write-Host $_ }
} catch {
Write-Host "❌ Windows tests failed: $_"
exit 1
}
# Backtrace diagnostic temporarily removed due to workflow parse issues
- name: Run tests (Windows)
shell: pwsh
env:
RUN_SYSTEM_TESTS: '1'
FORTFRONT_TRACE: '1'
run: |
$env:PATH = "C:\\tools\\fpm;$env:PATH"
# Use absolute path for trace file to ensure we can read it later
$traceFile = Join-Path (Get-Location) 'cli_trace.txt'
$env:FORTFRONT_TRACE_FILE = $traceFile
# Discover built fortfront.exe and pass to tests for robust CLI invocation
$exe = Get-ChildItem -Recurse -Filter fortfront.exe -Path . | Where-Object { $_.FullName -match "\\app\\fortfront\.exe$" } | Select-Object -First 1
if ($exe) {
Write-Host "Found fortfront.exe at: $($exe.FullName)"
$env:FORTFRONT_EXE = $exe.FullName
} else {
Write-Host "fortfront.exe not found via search; tests will fallback to internal discovery"
}
fpm test --flag "-Wl,--stack,16777216"
if (Test-Path $traceFile) {
Write-Host '--- CLI trace file (cli_trace.txt) ---'
Get-Content $traceFile | ForEach-Object { Write-Host $_ }
} else {
Write-Host 'cli_trace.txt not found'
}
- name: Cleanup build cache and logs (Windows)
if: always()
shell: pwsh
run: |
Write-Host "Pruning old build cache directories (keeping 2 newest)"
if (Test-Path build) {
Get-ChildItem build -Directory -ErrorAction SilentlyContinue |
Where-Object { $_.Name -like 'gfortran_*' } |
Sort-Object LastWriteTime -Descending |
Select-Object -Skip 2 |
ForEach-Object { Remove-Item $_.FullName -Recurse -Force -ErrorAction SilentlyContinue }
}
Write-Host "Deleting stale logs older than 7 days"
$logDir = Join-Path (Get-Location) 'logs'
if (Test-Path $logDir) {
Get-ChildItem $logDir -Recurse -Include *.log -ErrorAction SilentlyContinue |
Where-Object { $_.LastWriteTime -lt (Get-Date).AddDays(-7) } |
ForEach-Object { Remove-Item $_.FullName -Force -ErrorAction SilentlyContinue }
}
# macOS CI temporarily disabled due to runner issues
# test-macos:
# runs-on: macos-latest
#
# steps:
# - uses: actions/checkout@v4
#
# - name: Setup Micromamba
# uses: mamba-org/setup-micromamba@v2
# with:
# micromamba-version: 'latest'
# environment-name: test-env
# create-args: >-
# python=3.11
# fpm
# gfortran
# init-shell: bash
# cache-environment: true
# channels: conda-forge
#
# - name: Check versions
# shell: bash -el {0}
# run: |
# echo "GCC version:"
# gfortran --version
# echo "FPM version:"
# fpm --version
# echo "GCC/G++ version:"
# gcc --version || true
# # Check if gcc-15 is available
# gcc-15 --version || echo "gcc-15 not found, will try to find appropriate gcc"
#
# - name: Cache FPM dependencies
# uses: actions/cache@v4
# with:
# path: |
# ~/.local/share/fpm
# build/dependencies
# key: ${{ runner.os }}-fpm-deps-${{ hashFiles('fpm.toml') }}
# restore-keys: |
# ${{ runner.os }}-fpm-deps-
#
# - name: Run all tests
# shell: bash -el {0}
# run: |
# # Set FPM_CC for test runs with proper GCC version
# if command -v gcc-15 &> /dev/null; then
# export FPM_CC=gcc-15
# elif command -v gcc-14 &> /dev/null; then
# export FPM_CC=gcc-14
# elif command -v gcc-13 &> /dev/null; then
# export FPM_CC=gcc-13
# else
# GCC_PATH=$(which gcc)
# if [ -n "$GCC_PATH" ]; then
# export FPM_CC=$GCC_PATH
# fi
# fi
#
# echo "Using FPM_CC=$FPM_CC"
# echo "Running all tests..."
# fpm test --flag -cpp