Skip to content

Commit

Permalink
Merge branch 'master' into 2.x-dev
Browse files Browse the repository at this point in the history
  • Loading branch information
caendesilva committed Jul 10, 2024
2 parents 1086372 + 35d33a3 commit 8319a4d
Show file tree
Hide file tree
Showing 3 changed files with 326 additions and 0 deletions.
38 changes: 38 additions & 0 deletions .github/workflows/continuous-integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,26 @@ jobs:
path: '_site'


build-git-history-graph:
runs-on: ubuntu-latest
needs: run-smoke-tests

steps:
- uses: actions/checkout@v4
with:
# We need to fetch all history to generate the graph
fetch-depth: 0

- name: Generate Git history graph
run: php monorepo/scripts/build-git-history-graph.php

- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: 'git-history-graph'
path: 'monorepo/scripts/graphs'


upload-generated-reports:
environment:
name: live-reports
Expand All @@ -423,6 +443,7 @@ jobs:
- build-upcoming-documentation
- build-preview-site
- build-test-fixture-docs
- build-git-history-graph

steps:
- uses: actions/checkout@v4
Expand All @@ -436,6 +457,7 @@ jobs:
rm -rf master/api-docs && mkdir master/api-docs
rm -rf master/preview && mkdir master/preview
rm -rf master/test-fixtures && mkdir master/test-fixtures
rm -rf master/git && mkdir master/git
- name: Download coverage report artifact
uses: actions/download-artifact@v4
Expand Down Expand Up @@ -467,6 +489,12 @@ jobs:
name: test-fixture-docs
path: master/test-fixtures/docs

- name: Download Git history graph artifact
uses: actions/download-artifact@v4
with:
name: git-history-graph
path: master/git

- name: Create README.md
run: echo '# CI/CD generated reports for [${{ github.sha }}](https://github.com/hydephp/develop/commit/${{ github.sha }})' > master/README.md

Expand All @@ -491,6 +519,16 @@ jobs:
- name: Compile static master directory listing
run: cp .build.php master/.build.php && cd master && php .build.php

- name: Compile subdirectory listings
run: |
cd master
for dir in media test-fixtures git; do
cp .build.php $dir/.build.php
cd $dir
php .build.php
cd ..
done
# End directory listing

- name: Commit changes
Expand Down
20 changes: 20 additions & 0 deletions monorepo/docs/hydefront.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,26 @@
- Make sure you have authorization to publish the package to NPM and push to the HydeFront repository.
- **Make sure that you have linked the local HydeFront package to the monorepo with `npm link`.**

If you need to set up the "submodule", run the following commands:

```bash
cd packages/hydefront
git init
git remote add origin [email protected]:hydephp/hydefront.git
git fetch
git checkout master --force
```

If you need to set up the NPM link, run the following commands:

```bash
cd packages/hydefront
npm link

cd ../../
npm link hydefront
```

### Build and setup

```bash
Expand Down
268 changes: 268 additions & 0 deletions monorepo/scripts/build-git-history-graph.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,268 @@
<?php

declare(strict_types=1);

/**
* @internal This script is used to build the Git history graphs.
*
* @todo The HTML page has serious memory issues and may need pagination.
*
* @link https://hydephp.github.io/develop/master/git/history-graph.html
* @link https://hydephp.github.io/develop/master/git/history-graph.txt
*/
const CHUNK_SIZE = 100000;
const GRAPHS_DIR = __DIR__.'/graphs';
const TEMP_FILE = 'chunks.temp';

echo 'Building the Git history graph...'.PHP_EOL;

createGraphsDirectoryIfNotExists();
buildPlainTextGraph();
buildHtmlGraph();

echo 'Git history graphs built successfully!'.PHP_EOL;

function createGraphsDirectoryIfNotExists(): void
{
if (! file_exists(GRAPHS_DIR)) {
mkdir(GRAPHS_DIR);
}
}

function buildPlainTextGraph(): void
{
echo 'Building the plaintext Git history graph... (This may take a while)'.PHP_EOL;
$text = cached_shell_exec('git log --graph --oneline --all');
echo 'Saving the plaintext Git history graph...'.PHP_EOL;
file_put_contents(GRAPHS_DIR.'/history-graph.txt', $text);
}

function buildHtmlGraph(): void
{
echo 'Building the HTML Git history graph... (This may take a while)'.PHP_EOL;
$html = cached_shell_exec('git log --graph --oneline --all --color=always');
echo 'Converting ANSI color codes to HTML...'.PHP_EOL;
$html = processHtml($html);
echo 'Generating header...';
$graph = file_get_contents(GRAPHS_DIR.'/history-graph.txt');
$header = generateHeader($graph);
echo ' Done.'.PHP_EOL;
echo 'Wrapping the HTML...';
$html = wrapHtml($html, $header);
echo ' Done.'.PHP_EOL;
echo 'Saving the HTML Git history graph...'.PHP_EOL;
file_put_contents(GRAPHS_DIR.'/history-graph.html', $html);
}

function processHtml(string $html): string
{
$chunks = chunkHtml($html);
$message = 'Processing '.count($chunks).' chunks...';
echo $message;

foreach ($chunks as $index => $chunk) {
echo "\033[0K\rProcessing chunk ".($index + 1).' of '.count($chunks).'...';
$chunkHtml = ansiToHtml($chunk);
$chunkHtml = postProcessChunk($chunkHtml);

// Since this process takes so much memory, we store the chunks on disk instead of memory.
file_put_contents(TEMP_FILE, $chunkHtml, FILE_APPEND);
}

$html = file_get_contents(TEMP_FILE);
unlink(TEMP_FILE);
echo PHP_EOL;

return $html;
}

function chunkHtml(string $html): array
{
$lines = explode("\n", $html);
$chunks = [];
$chunk = '';

foreach ($lines as $line) {
$chunk .= $line."\n";
if (strlen($chunk) > CHUNK_SIZE) {
$chunks[] = $chunk;
$chunk = '';
}
}

if ($chunk !== '') {
$chunks[] = $chunk;
}

return $chunks;
}

function ansiToHtml(string $ansi): string
{
$colors = [
1 => '#C50F1F',
30 => '#0C0C0C',
31 => '#C50F1F',
32 => '#13A10E',
33 => '#C19C00',
34 => '#0037DA',
35 => '#881798',
36 => '#3A96DD',
37 => '#CCCCCC',
];

$ansi = preg_replace('/\x1b\[(\d+)(;\d+)*m/', '</span><span style="color: $1">', $ansi);
$ansi = preg_replace_callback('/<span style="color: (\d+)">/', function (array $matches) use ($colors): string {
return '<span style="color: '.$colors[$matches[1]].'">';
}, $ansi);
$ansi = str_replace("\033[m", '</span>', $ansi);

return trim($ansi);
}

function wrapHtml(string $html, string $header): string
{
return <<<HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Git History Graph</title>
<style>
body {
background-color: #121212;
color: #fff;
}
header, main {
font-family: monospace;
white-space: pre;
}
</style>
</head>
<body>
<header>$header</header>
<main>
$html
</main>
</body>
HTML;
}

function generateHeader(string $text): string
{
$commitCount = countCommitLines($text);
$head = trim(shell_exec('git rev-parse --short HEAD'));
$date = date('Y-m-d H:i:s');

return <<<HTML
Git History Graph
================
repository: https://github.com/hydephp/develop.git
branch: master
head: $head
date: $date
commits: $commitCount
----------------
HTML;
}

function countCommitLines(string $text): int
{
$count = 0;
$lines = explode("\n", $text);

foreach ($lines as $line) {
if (str_starts_with(ltrim($line, ' /\\|'), '*')) {
$count++;
}
}

return $count;
}

function postProcessChunk(string $chunk): string
{
$lines = explode("\n", $chunk);

$ignore = [
'Upload documentation preview for PR',
'Upload live reports from test suite run',
'Upload site preview from test suite run with ref',
'Upload coverage report from test suite run with ref',
'Upload API documentation from test suite run with ref',
];

foreach ($lines as $index => $line) {
$line = cleanSpanTags($line);
$line = cleanAsterisk($line);
// assertValidLine($line, $index);

if (shouldIgnoreLine($line, $ignore)) {
$line = '';
}

$lines[$index] = trim($line);
}

return implode("\n", array_filter($lines));
}

function cleanSpanTags(string $line): string
{
$line = str_replace(
['</span></span>', '</span> </span>', '</span> </span>', '</span> </span>'],
['</span>', '</span> ', '</span> ', '</span> '],
$line
);

if (str_starts_with($line, '</span>')) {
$line = substr($line, 7);
}

if (str_starts_with($line, ' </span>')) {
$line = substr($line, 8).' ';
}

return $line;
}

function cleanAsterisk(string $line): string
{
if (preg_match('/^\*\s*<\/span>/', $line)) {
$line = '* '.preg_replace('/^\*\s*<\/span>/', '', $line);
}

return $line;
}

function assertValidLine(string $line, int $index): void
{
$trimmedLine = trim($line);
assert(! str_starts_with($trimmedLine, '</span>'), "Line $index starts with closing span tag");

$openTags = substr_count($line, '<span');
$closeTags = substr_count($line, '</span>');
assert($openTags === $closeTags, "Line $index has $openTags opening and $closeTags closing span tags");
}

function shouldIgnoreLine(string $line, array $ignore): bool
{
foreach ($ignore as $str) {
if (str_contains($line, $str)) {
return true;
}
}

return false;
}

function cached_shell_exec(string $command): string
{
$cacheFile = __DIR__.'/cache/'.sha1($command).'.txt';
$cache = file_exists($cacheFile) ? file_get_contents($cacheFile) : '';
$output = $cache ?: shell_exec($command);

file_put_contents($cacheFile, $output);

return $output;
}

0 comments on commit 8319a4d

Please sign in to comment.