Skip to content

Commit 451ea4a

Browse files
committed
try try again
1 parent 1b25a92 commit 451ea4a

2 files changed

Lines changed: 167 additions & 12 deletions

File tree

.github/workflows/self_hosted_build_and_test.yml

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -114,12 +114,15 @@ jobs:
114114
run: |
115115
set -o pipefail
116116
mkdir -p coverage/unit
117-
lcov -c -d . -o coverage/unit/lcov.output --no-external --base-directory ${{ github.workspace }} --source-directory ${{ github.workspace }} --ignore-errors source,source
118-
lcov -e coverage/unit/lcov.output "${{ github.workspace }}/src/EnergyPlus/*" "src/EnergyPlus/*" -o coverage/unit/lcov.output.filtered --ignore-errors unused,unused,empty,empty
119-
grep -q '^DA:' coverage/unit/lcov.output.filtered
120-
# Coveralls needs repo-relative SF paths to fetch source for line views.
121-
sed "s#^SF:${{ github.workspace }}/#SF:#" coverage/unit/lcov.output.filtered > coverage/unit/lcov.output.coveralls
122-
genhtml coverage/unit/lcov.output.filtered -o coverage/unit/lcov-html --source-directory ${{ github.workspace }} --demangle-cpp --function-coverage --synthesize-missing --ignore-errors source,source | tee coverage/unit/cover.txt
117+
lcov -c -d . -o coverage/unit/lcov.output --base-directory ${{ github.workspace }} --ignore-errors source,source
118+
${{ steps.setup-runner.outputs.python-root-dir }}/bin/python \
119+
${{ github.workspace }}/scripts/dev/normalize_lcov_paths.py \
120+
coverage/unit/lcov.output \
121+
--workspace ${{ github.workspace }} \
122+
--build-directory ${{ github.workspace }}/${{ env.BUILD_DIR }} \
123+
--absolute-output coverage/unit/lcov.output.filtered \
124+
--relative-output coverage/unit/lcov.output.coveralls
125+
genhtml coverage/unit/lcov.output.filtered -o coverage/unit/lcov-html --demangle-cpp --function-coverage --ignore-errors source,source | tee coverage/unit/cover.txt
123126
124127
- name: Process unit test coverage summary
125128
working-directory: ${{ env.BUILD_DIR }}/coverage/unit
@@ -147,12 +150,15 @@ jobs:
147150
run: |
148151
set -o pipefail
149152
mkdir -p coverage/integration
150-
lcov -c -d . -o coverage/integration/lcov.output --no-external --base-directory ${{ github.workspace }} --source-directory ${{ github.workspace }} --ignore-errors source,source
151-
lcov -e coverage/integration/lcov.output "${{ github.workspace }}/src/EnergyPlus/*" "src/EnergyPlus/*" -o coverage/integration/lcov.output.filtered --ignore-errors unused,unused,empty,empty
152-
grep -q '^DA:' coverage/integration/lcov.output.filtered
153-
# Coveralls needs repo-relative SF paths to fetch source for line views.
154-
sed "s#^SF:${{ github.workspace }}/#SF:#" coverage/integration/lcov.output.filtered > coverage/integration/lcov.output.coveralls
155-
genhtml coverage/integration/lcov.output.filtered -o coverage/integration/lcov-html --source-directory ${{ github.workspace }} --demangle-cpp --function-coverage --synthesize-missing --ignore-errors source,source | tee coverage/integration/cover.txt
153+
lcov -c -d . -o coverage/integration/lcov.output --base-directory ${{ github.workspace }} --ignore-errors source,source
154+
${{ steps.setup-runner.outputs.python-root-dir }}/bin/python \
155+
${{ github.workspace }}/scripts/dev/normalize_lcov_paths.py \
156+
coverage/integration/lcov.output \
157+
--workspace ${{ github.workspace }} \
158+
--build-directory ${{ github.workspace }}/${{ env.BUILD_DIR }} \
159+
--absolute-output coverage/integration/lcov.output.filtered \
160+
--relative-output coverage/integration/lcov.output.coveralls
161+
genhtml coverage/integration/lcov.output.filtered -o coverage/integration/lcov-html --demangle-cpp --function-coverage --ignore-errors source,source | tee coverage/integration/cover.txt
156162
157163
- name: Process integration test coverage summary
158164
working-directory: ${{ env.BUILD_DIR }}/coverage/integration
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
#!/usr/bin/env python3
2+
3+
import argparse
4+
import sys
5+
from pathlib import Path
6+
7+
8+
def build_source_index(workspace: Path) -> dict[str, list[Path]]:
9+
source_index: dict[str, list[Path]] = {}
10+
source_root = workspace / "src" / "EnergyPlus"
11+
for source_file in source_root.rglob("*"):
12+
if source_file.is_file():
13+
relative_path = source_file.relative_to(workspace)
14+
source_index.setdefault(source_file.name, []).append(relative_path)
15+
return source_index
16+
17+
18+
def repo_relative_source(
19+
source_file: str,
20+
workspace: Path,
21+
build_directory: Path | None,
22+
source_index: dict[str, list[Path]],
23+
) -> Path | None:
24+
source_path = Path(source_file)
25+
candidates: list[Path] = []
26+
27+
if source_path.is_absolute():
28+
candidates.append(source_path)
29+
else:
30+
candidates.append(workspace / source_path)
31+
if build_directory is not None:
32+
candidates.append(build_directory / source_path)
33+
34+
for candidate in candidates:
35+
try:
36+
relative_path = candidate.resolve().relative_to(workspace.resolve())
37+
except ValueError:
38+
continue
39+
40+
parts = relative_path.parts
41+
for index in range(len(parts) - 1):
42+
if parts[index] == "src" and parts[index + 1] == "EnergyPlus":
43+
relative_path = Path(*parts[index:])
44+
break
45+
46+
if not relative_path.as_posix().startswith("src/EnergyPlus/"):
47+
continue
48+
49+
if (workspace / relative_path).is_file():
50+
return relative_path
51+
52+
basename_matches = source_index.get(source_path.name, [])
53+
if len(basename_matches) == 1:
54+
return basename_matches[0]
55+
56+
return None
57+
58+
59+
def flush_record(
60+
record_lines: list[str],
61+
relative_source: Path | None,
62+
workspace: Path,
63+
absolute_records: list[str],
64+
relative_records: list[str],
65+
) -> int:
66+
if relative_source is None:
67+
return 0
68+
69+
da_lines = sum(1 for line in record_lines if line.startswith("DA:"))
70+
if da_lines == 0:
71+
return 0
72+
73+
absolute_source = (workspace / relative_source).as_posix()
74+
relative_source_text = relative_source.as_posix()
75+
76+
for line in record_lines:
77+
if line.startswith("SF:"):
78+
absolute_records.append(f"SF:{absolute_source}")
79+
relative_records.append(f"SF:{relative_source_text}")
80+
else:
81+
absolute_records.append(line)
82+
relative_records.append(line)
83+
84+
return da_lines
85+
86+
87+
def normalize_lcov_paths(
88+
input_file: Path,
89+
workspace: Path,
90+
build_directory: Path | None,
91+
absolute_output: Path,
92+
relative_output: Path,
93+
) -> int:
94+
source_index = build_source_index(workspace)
95+
absolute_records: list[str] = []
96+
relative_records: list[str] = []
97+
record_lines: list[str] = []
98+
relative_source: Path | None = None
99+
da_lines = 0
100+
101+
with input_file.open("r", encoding="utf-8") as input_stream:
102+
for raw_line in input_stream:
103+
line = raw_line.rstrip("\n")
104+
if line.startswith("SF:"):
105+
relative_source = repo_relative_source(line[3:], workspace, build_directory, source_index)
106+
record_lines.append(line)
107+
elif line == "end_of_record":
108+
record_lines.append(line)
109+
da_lines += flush_record(record_lines, relative_source, workspace, absolute_records, relative_records)
110+
record_lines = []
111+
relative_source = None
112+
else:
113+
record_lines.append(line)
114+
115+
absolute_output.parent.mkdir(parents=True, exist_ok=True)
116+
relative_output.parent.mkdir(parents=True, exist_ok=True)
117+
absolute_output.write_text("\n".join(absolute_records) + ("\n" if absolute_records else ""), encoding="utf-8")
118+
relative_output.write_text("\n".join(relative_records) + ("\n" if relative_records else ""), encoding="utf-8")
119+
120+
return da_lines
121+
122+
123+
def main() -> int:
124+
parser = argparse.ArgumentParser(description="Filter LCOV records to real repo source files and normalize SF paths.")
125+
parser.add_argument("input_file", type=Path)
126+
parser.add_argument("--workspace", type=Path, required=True)
127+
parser.add_argument("--build-directory", type=Path)
128+
parser.add_argument("--absolute-output", type=Path, required=True)
129+
parser.add_argument("--relative-output", type=Path, required=True)
130+
args = parser.parse_args()
131+
132+
da_lines = normalize_lcov_paths(
133+
input_file=args.input_file,
134+
workspace=args.workspace,
135+
build_directory=args.build_directory,
136+
absolute_output=args.absolute_output,
137+
relative_output=args.relative_output,
138+
)
139+
140+
if da_lines == 0:
141+
print("No LCOV data records matched real files under src/EnergyPlus", file=sys.stderr)
142+
return 1
143+
144+
print(f"Wrote normalized LCOV data with {da_lines} DA records")
145+
return 0
146+
147+
148+
if __name__ == "__main__":
149+
raise SystemExit(main())

0 commit comments

Comments
 (0)