Skip to content
Merged

CI #1

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions .github/actions/build/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
name: Run and build with coverage
description: Build the project

inputs:
path:
description: Path to project root
required: true
default: ''
repository:
description: Repository that is being built
required: true
default: ''
ref:
description: Git ref of the state of the project being built
required: true
default: ''
commit:
description: Git commit of the state of the project being built
required: true
default: ''
targets:
description: B2 targets to build (separated by spaces)
required: false
default: ''

runs:
using: composite
steps:
- name: Setup environment variables
shell: bash
run: |
set -ex
export LCOV_BRANCH_COVERAGE=0
export B2_TOOLSET=gcc-14
export CXX=g++-14
export B2_CI_VERSION=1
export B2_CXXSTD=20
export B2_VARIANT=debug
export B2_TARGETS=${{ github.targets }}
export B2_FLAGS="link=shared cxxflags=-fkeep-static-functions cxxflags=--coverage linkflags=--coverage"
export DRONE_BUILD_EVENT=${{ github.event_name }}
export DRONE_JOB_BUILDTYPE=boost
export DRONE_COMMIT=${{ github.sha }}
export DRONE_BRANCH=${{ inputs.ref }}
export DRONE_REPO=${{ inputs.repo }}

cd ${{ inputs.path }}
. .drone/drone.sh
119 changes: 119 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
name: CI

on:
push

jobs:
build:
runs-on: ubuntu-latest

steps:
- name: Fetch head
uses: actions/checkout@v5

- id: fetch-target
name: Fetch Boost.JSON target
uses: actions/checkout@v5
with:
repository: 'boostorg/json'
ref: 4c97cd0ff39c453043cf1b474bdbcacb1979d0f0
path: target/root

- name: Build target
uses: ./.github/actions/build
with:
path: target/root
repository: booostorg/json
ref: ${{ steps.fetch-target.outputs.ref }}
commit: ${{ steps.fetch-target.outputs.commit }}
targets: libs/json/test

- id: fetch-baseline
name: Fetch Boost.JSON baseline
uses: actions/checkout@v5
with:
repository: 'boostorg/json'
ref: develop
path: base/root

- name: Build baseline
uses: ./.github/actions/build
with:
path: base/root
repository: booostorg/json
ref: ${{ steps.fetch-baseline.outputs.ref }}
commit: ${{ steps.fetch-baseline.outputs.commit }}
targets: libs/json/test

- name: Collect coverage
run: |
set -ex

sudo apt install lcov

lcov --rc branch_coverage=0 --rc geninfo_unexecuted_blocks=1 \
--gcov-tool=gcov-14 --capture --initial --directory base/boost-root/bin.v2/libs/json \
--output-file base/zero.info
lcov --rc branch_coverage=0 --rc geninfo_unexecuted_blocks=1 \
--gcov-tool=gcov-14 --capture --directory base/boost-root/bin.v2/libs/json \
--output-file base/run.info
lcov -a base/zero.info -a base/run.info --output-file base/all.info
lcov --extract base/all.info '*/json/*' --output-file base/filter1.info
lcov --remove base/filter1.info '*/json/test/*' '*/json/bench/*' \
'*/json/example/*' --output-file base/filter2.info

lcov --rc branch_coverage=0 --rc geninfo_unexecuted_blocks=1 \
--gcov-tool=gcov-14 --capture --initial --directory target/boost-root/bin.v2/libs/json \
--output-file target/zero.info
lcov --rc branch_coverage=0 --rc geninfo_unexecuted_blocks=1 \
--gcov-tool=gcov-14 --capture --directory target/boost-root/bin.v2/libs/json \
--output-file target/run.info
lcov -a target/zero.info -a target/run.info --output-file target/all.info
lcov --extract target/all.info '*/json/*' --output-file target/filter1.info
lcov --remove target/filter1.info '*/json/test/*' '*/json/bench/*' \
'*/json/example/*' --output-file target/filter2.info

git diff -U0 --no-indent-heuristic --minimal \
base/boost-root/libs/json target/boost-root/libs/json >diff

./diff-coverage-report.py -O pages -S target/boost-root/libs/json \
-B base/filter2.info -T target/filter2.info -D diff \
-P $PWD/base/boost-root/boost $PWD/target/boost-root/libs/json/include/boost \
$PWD/target/boost-root/boost $PWD/target/boost-root/libs/json/include/boost \
$PWD/base/boost-root $PWD/target/boost-root \
1/base/boost-root $PWD/target/boost-root \
2/target/boost-root $PWD/target/boost-root

- name: Save coverage info
uses: actions/upload-artifact@v4
with:
name: coverage
path: |
base/filter2.info
target/filter2.info
diff
if-no-files-found: error
retention-days: 1
compression-level: 9

- name: Upload result as an artifact
uses: actions/upload-pages-artifact@v3
with:
path: pages/

deploy:
needs: build

permissions:
pages: write
id-token: write

environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}

runs-on: ubuntu-latest
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
40 changes: 23 additions & 17 deletions diff-coverage-report.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
#!/usr/bin/env python

import argparse
from io import IOBase
from re import S
import itertools
import io
import jinja2
import os
import os.path
Expand All @@ -14,15 +14,16 @@ def main(argv):
args = parse_args(argv)

source_dir = os.path.abspath(args.source_dir)
prefix_map = list(itertools.batched(args.map_prefix or [], 2))

with open(args.target_info, 'r') as f:
files = parse_tracefile(f, source_dir)
files = parse_tracefile(f, source_dir, prefix_map)

with open(args.base_info, 'r') as f:
files = parse_tracefile(f, source_dir, files)
files = parse_tracefile(f, source_dir, prefix_map, files)

with open(args.diff, 'r') as f:
files = parse_diff(f, files, source_dir)
files = parse_diff(f, files, source_dir, prefix_map)

dirs = collect_directories(files, source_dir)

Expand Down Expand Up @@ -91,10 +92,14 @@ def parse_args(argv):
parser.add_argument(
'-O', '--output-dir', default=os.getcwd(), help=f'Output directory',
)
parser.add_argument(
'-P', '--map-prefix', nargs='*', help=f'Output directory',
)

return parser.parse_args(argv[1:])


def parse_tracefile(lines, source_dir, files=None):
def parse_tracefile(lines, source_dir, prefix_map, files=None):
is_base = files is not None
if not is_base:
files = {}
Expand All @@ -112,7 +117,7 @@ def parse_tracefile(lines, source_dir, files=None):

if directive == 'SF':
assert cur_file is None
cur_file = FileData(parts[1], source_dir)
cur_file = FileData(fix_path(parts[1], prefix_map), source_dir)

elif directive == 'FNL':
assert cur_file is not None
Expand Down Expand Up @@ -203,7 +208,7 @@ def parse_tracefile(lines, source_dir, files=None):
return files


def parse_diff(lines, result, source_dir):
def parse_diff(lines, result, source_dir, prefix_map):
old_file = None
new_file = None
file_data = None
Expand All @@ -228,11 +233,11 @@ def commit():
new_line = -1

_, old_file = l.split(' ', 1)
old_file = fix_path(old_file.rstrip())
old_file = fix_path(old_file.rstrip(), prefix_map)

elif l.startswith('+++ '):
_, new_file = l.split(' ', 1)
new_file = fix_path(new_file.rstrip())
new_file = fix_path(new_file.rstrip(), prefix_map)
assert old_file == new_file

file_data = result.get(new_file)
Expand Down Expand Up @@ -314,11 +319,12 @@ def collect_directories(files, source_dir):
return dirs.values()


def fix_path(path: str) -> str:
if os.path.isabs(path):
return path
else:
return os.sep.join(path.split(os.sep, 1)[1:])
def fix_path(path: str, prefix_map) -> str:
for src, tgt in prefix_map:
if path.startswith(src):
path = tgt + path[len(src):]
break
return path


def path_suffix(path: str, source_dir: str) -> str:
Expand Down Expand Up @@ -408,7 +414,7 @@ def __init__(self, path: str, source_dir: str):
def output_path(self):
return self.source_path + '.html'

def calc(self, text: IOBase):
def calc(self, text: io.IOBase):
assert self.base
result = []
diff = DiffedLines(text, self)
Expand Down Expand Up @@ -598,7 +604,7 @@ def add_line(self, number, count, _=None):


class DiffedLines():
def __init__(self, lines: IOBase, data: FileData):
def __init__(self, lines: io.IOBase, data: FileData):
self.lines = lines
self.data = data

Expand Down