diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..5423147 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,2 @@ +* +!report.php \ No newline at end of file diff --git a/.drone.yml b/.drone.yml new file mode 100644 index 0000000..aab4cb0 --- /dev/null +++ b/.drone.yml @@ -0,0 +1,120 @@ +--- +kind: pipeline +type: docker +name: main + +steps: + - name: Fetch tags + image: alpine/git + commands: + - git fetch --tags + - name: Update version and changelog + image: registry.riba-interactive.de/conventi:0.1.0 + - name: Commit changelog updates + image: alpine/git + commands: + - git add . + - git commit -m "version and changelog update [CI SKIP]" + - git push origin $DRONE_TARGET_BRANCH + - name: Tag commit + image: registry.riba-interactive.de/conventi:0.1.0 + commands: + - export VERSION=$(conventi.sh get_version) + - git tag -am "Tagging new version $VERSION" "$VERSION" + - git push origin "$VERSION" + +trigger: + branch: + - main + event: + - push + +image_pull_secrets: + - dockerconfig +--- +kind: pipeline +type: docker +name: tag + +steps: + - name: Build release + image: docker:dind + volumes: + - name: dockersock + path: /var/run + environment: + DOCKER_USER: + from_secret: docker_user + DOCKER_PASSWORD: + from_secret: docker_password + commands: + - sleep 5 # give docker enough time to start + - echo "$DOCKER_PASSWORD" | docker login --username $DOCKER_USER --password-stdin registry.riba-interactive.de + - docker pull registry.riba-interactive.de/reportly:latest || true + - DOCKER_BUILDKIT=1 docker build --cache-from registry.riba-interactive.de/reportly:latest --tag registry.riba-interactive.de/reportly:latest . + - docker tag registry.riba-interactive.de/reportly:latest registry.riba-interactive.de/reportly:$DRONE_TAG + - docker push --all-tags registry.riba-interactive.de/reportly + +trigger: + event: + - tag + +services: + - name: docker + image: docker:dind + privileged: true + volumes: + - name: dockersock + path: /var/run + +volumes: + - name: dockersock + temp: {} + +image_pull_secrets: + - dockerconfig +--- +kind: pipeline +type: docker +name: Build and Test + +steps: + - name: Build image + image: docker:dind + volumes: + - name: dockersock + path: /var/run + environment: + DOCKER_USER: + from_secret: docker_user + DOCKER_PASSWORD: + from_secret: docker_password + commands: + - sleep 5 # give docker enough time to start + - echo "$DOCKER_PASSWORD" | docker login --username $DOCKER_USER --password-stdin registry.riba-interactive.de + - docker pull registry.riba-interactive.de/reportly:latest || true + - DOCKER_BUILDKIT=1 docker build --cache-from registry.riba-interactive.de/reportly:latest --tag registry.riba-interactive.de/reportly:latest . + - docker tag registry.riba-interactive.de/reportly:latest registry.riba-interactive.de/reportly:build-$DRONE_BUILD_NUMBER + - docker push --all-tags registry.riba-interactive.de/reportly + +trigger: + branch: + - develop + - feature/* + - bugfix/* + +services: + - name: docker + image: docker:dind + privileged: true + volumes: + - name: dockersock + path: /var/run + +volumes: + - name: dockersock + temp: {} + +image_pull_secrets: + - dockerconfig +... \ No newline at end of file diff --git a/.version.json b/.version.json new file mode 100644 index 0000000..3de53a7 --- /dev/null +++ b/.version.json @@ -0,0 +1,5 @@ +{ + "version": "0.0.0", + "sha": "", + "url": "https://git.riba-interactive.de/rick/reportly" +} diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..f7ecd09 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,8 @@ +# Changelog + +All notable changes to this project will be documented in this file. See [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) for commit guidelines. + +This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +---- + diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..0cd860c --- /dev/null +++ b/Dockerfile @@ -0,0 +1,12 @@ +FROM php:8.1-cli-alpine3.16 + +RUN echo "@testing https://dl-cdn.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories; \ + apk --no-cache add \ + lcov@testing \ + composer; \ + cd /usr/local/bin/ \ + && composer require erusev/parsedown + +COPY report.php /usr/local/bin/ + +ENTRYPOINT ["report.php"] \ No newline at end of file diff --git a/LICENSE b/LICENSE index e06aa93..17aef81 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) year copyright holder. All Rights Reserved. +Copyright (c) 2022 Rick Barenthin. All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/README.md b/README.md index f91c304..c6121c5 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,3 @@ # reportly +[![Build Status](https://drone.riba-interactive.de/api/badges/rick/reportly/status.svg)](https://drone.riba-interactive.de/rick/reportly) diff --git a/report.php b/report.php new file mode 100755 index 0000000..80ddbcb --- /dev/null +++ b/report.php @@ -0,0 +1,164 @@ +#!/usr/bin/env php +%s', + $reportTitle, + '*,:after,:before{box-sizing:border-box}body{color:#444;font:18px/1.6 Georgia,Times New Roman,Times,serif;margin:40px auto;padding:0 20px}h1,h2,h3,h4,h5{font-family:Helvetica Neue,Helvetica,Arial,sans-serif;line-height:1.2}a{color:#07c;text-decoration:none}a:hover{color:#059;text-decoration:underline}hr{border:0;margin:25px 0}table{border-collapse:collapse;border-spacing:0;padding-bottom:25px;text-align:left}hr,td,th{border-bottom:1px solid #ddd}button,select{background:#ddd;border:0;font-size:14px;padding:9px 20px}input,table{font-size:1pc}input,td,th{padding:5px;vertical-align:bottom}button:hover,code,pre{background:#eee}pre{overflow-x:scroll;padding:8px;font-size:14px}textarea{border-color:#ccc}.row{display:block;min-height:1px;width:auto}.row:after{clear:both;content:"";display:table}.row .c{float:left}.g2,.g3,.g3-2,.m2,.m3,.m3-2,table{width:100%}@media(min-width:8in){.g2{width:50%}.m2{margin-left:50%}.g3{width:33.33%}.g3-2{width:66.66%}.m3{margin-left:33.33%}.m3-2{margin-left:66.66%}}' +); +$htmlFooter = ''; + +$output .= sprintf("%s\n%s\n\n\n", $reportTitle, str_repeat('=', strlen($reportTitle))); + +$coverageInfoFile = join_paths($inputDir, 'coverage.info'); +$outputLcov = []; +exec('lcov --rc lcov_branch_coverage=1 --list ' . $coverageInfoFile, $outputLcov); + +array_shift($outputLcov); + +$headerCovreport= 'Coverage report'; +$output .= sprintf("%s\n%s\n\n\n", $headerCovreport, str_repeat('-', strlen($headerCovreport))); +$output .= sprintf("%s\n", '```'); +$output .= implode("\n", $outputLcov); +$output .= sprintf("\n"); +$output .= sprintf("%s\n\n", '```'); + +$output .= sprintf("%s\n\n", '[See full coverage report](coverage/index.html)'); + +if($verbose) { + echo "Coverage report:\n"; + echo implode("\n", $outputLcov) . "\n\n"; +} + +$inputReportDir = join_paths($inputDir, 'Testing'); +$inputReportFolder = ''; +foreach (new DirectoryIterator($inputReportDir) as $fileInfo) { + if ($fileInfo->isDot()) continue; + if (preg_match('/\d+-\d+/', $fileInfo->getFilename())) { + $inputReportFolder = $fileInfo->getFilename(); + break; + } +} + +function join_paths(...$paths) { + return preg_replace('~[/\\\\]+~', DIRECTORY_SEPARATOR, implode(DIRECTORY_SEPARATOR, $paths)); +} + +$inputReportFile = join_paths($inputReportDir, $inputReportFolder, 'DynamicAnalysis.xml'); +$xmlstr = file_get_contents($inputReportFile); + +$tests = new SimpleXMLElement($xmlstr); + +$countTests = count($tests->DynamicAnalysis->Test); +$numTest = 1; + +$testMapping = []; +$typeMapping = [ + 'FIM' => 'Free Invalid Memory', + 'FMM' => 'Free Mismatched Memory', + 'UMR' => 'Uninitialised Memory Read', + 'UMC' => 'Uninitialised Memory Conditional', + 'IPW' => 'Invalid Pointer Write', +]; + +$headerMemreport = 'Memory check report'; +$output .= sprintf("%s\n%s\n\n\n", $headerMemreport, str_repeat('-', strlen($headerMemreport))); + +$memLeaksFound = count($tests->DynamicAnalysis->Test) != 0; + +$outputMem = ''; + +if ($memLeaksFound) { + $outputMem .= sprintf("%s\n", '```'); + foreach ($tests->DynamicAnalysis->Test as $test) { + $testMapping[$numTest] = $test->Name; + $outputMem .= sprintf("%d/%d MemCheck #%d: %s\n", $numTest, $countTests, $numTest, $test->Name); + + $numResult = 1; + foreach ($test->Results->Defect as $result) { + $type = $result->attributes()->{'type'}->__toString(); + $outputMem .= sprintf("\t%d: %s %s : %d\n", + $numResult, + str_repeat('.', 40), + ($typeMapping[$type] ?? $type), $result); + $numResult++; + } + $numTest++; + } + $outputMem .= sprintf("%s\n\n", '```'); + + $outputMem .= sprintf("\n"); + foreach (new DirectoryIterator(join_paths($inputReportDir, 'Temporary')) as $fileInfo) { + if ($fileInfo->isDot()) continue; + if (preg_match('/MemoryChecker/', $fileInfo->getFilename())) { + $memReport = file_get_contents($fileInfo->getPathname()); + if (strlen($memReport) == 0) continue; + + $number = explode('.', $fileInfo->getFilename())[1]; + $testName = $testMapping[$number]; + + $headerMemreport = sprintf("Report #%d %s:", $number, $testName); + $outputMem .= sprintf("%s\n%s\n\n", $headerMemreport, str_repeat('-', strlen($headerMemreport))); + + $memReport = file_get_contents($fileInfo->getPathname()); + + $outputMem .= sprintf("%s\n", '```'); + $outputMem .= sprintf("%s", $memReport); + $outputMem .= sprintf("%s\n\n", '```'); + } + } +} else { + $outputMem .= sprintf("%s\n\n", "NO MEMORY ISSUES, well done!"); +} + +if($verbose) { + echo "Memory check report\n"; + echo $outputMem; +} + +$output .= sprintf("%s", $outputMem); + +file_put_contents(join_paths($outputDir, 'report.html'), $htmlHeader . $Parsedown->text($output) . $htmlFooter); + +$coverageDirectoryOut = join_paths($outputDir, 'coverage'); +mkdir($coverageDirectoryOut); +foreach ( +$iterator = new \RecursiveIteratorIterator( + new \RecursiveDirectoryIterator(join_paths($inputDir, 'coverage'), \RecursiveDirectoryIterator::SKIP_DOTS), + \RecursiveIteratorIterator::SELF_FIRST) as $item +) { + if ($item->isDir()) { + mkdir(join_paths($coverageDirectoryOut, $iterator->getSubPathname())); + } else { + copy($item, join_paths($coverageDirectoryOut, $iterator->getSubPathname())); + } +} + +return 0;