Skip to content
Draft
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
1 change: 1 addition & 0 deletions .github/actions/verify-generated-files/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@ runs:
ext/tokenizer/tokenizer_data_gen.php
build/gen_stub.php -f --generate-optimizer-info --verify
ext/phar/makestub.php
.github/scripts/download-bundled/make-workflow-file.php
.github/scripts/test-directory-unchanged.sh .
212 changes: 212 additions & 0 deletions .github/scripts/download-bundled/make-workflow-file.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
#!/usr/bin/env php
<?php

declare(strict_types=1);

namespace Phpsrc\Ci\DownloadBundled;

$bundles = [
new Bundle('boost.context', ['Zend/asm']),
new Bundle('XSSE', ['Zend/zend_simd.h']),
new Bundle('timelib', ['ext/date/lib']),
new Bundle('xxHash', ['ext/hash/xxhash']),
new Bundle('Unicode Character Database', ['ext/mbstring']),
new Bundle('PCRE2', ['ext/pcre/pcre2lib']),
new Bundle('uriparser', ['ext/uri/uriparser']),
];

class Bundle
{
/**
* @param list<string> $directories
*/
public function __construct(
public string $name,
public array $directories
) {}

public function getNameForPath(): string
{
return preg_replace('~\W+~', '-', strtolower($this->name));
}
}

class Generator
{
/**
* @param list<Bundle> $bundles
*/
public function __construct(
public array $bundles
) {}

protected function getRepoDirectory(): string
{
return dirname(__DIR__, 3);
}

protected function indentString(string $value, int $levels, bool $inclFirstLine): string
{
return preg_replace(
'~' . ($inclFirstLine ? '^|' : '') . '(?<=\n)~',
str_repeat(' ', $levels),
$value
);
}

/**
* @param mixed $data
*/
protected function encodeYml($data): string
{
if (is_array($data)) {
$isList = array_is_list($data);
$resParts = [];
foreach ($data as $k => $v) {
$kEncoded = $isList
? '-'
: $this->encodeYml($k) . ':';
$vEncoded = $this->encodeYml($v);

$resParts[] = $kEncoded
. (!$isList && is_array($v) && $v !== [] ? "\n " : ' ')
. (is_array($v) ? $this->indentString($vEncoded, 1, false) : $vEncoded);
}

return implode("\n", $resParts);
}

if (preg_match('~^(\w+|\$\{\{[^\}]+\}\})$~', $data)) {
return $data;
}

return strpos($data, "\n") !== false
? '|' . "\n" . $this->indentString($data, 1, true)
: '\'' . str_replace('\'', '\'\'', $data) . '\'';
}

public function makeWorkflowFile(): void
{
$content = <<<'EOD'
name: Verify Bundled Files

on:
push:
paths: &paths
%paths%
pull_request:
paths: *paths
schedule:
- cron: "0 1 * * *"
workflow_dispatch: ~

permissions:
contents: read

jobs:
VERIFY_BUNDLED_FILES:
if: github.repository == 'php/php-src' || github.event_name == 'workflow_dispatch'
name: Verify Bundled Files
runs-on: ubuntu-24.04
steps:
- name: git checkout
uses: actions/checkout@v6

- name: Detect changed files
if: ${{ github.event_name == 'push' || github.event_name == 'pull_request' }}
uses: dorny/paths-filter@v3
id: changes
with:
filters: %filters%

%steps%

EOD;

$paths = [
'.github/scripts/download-bundled/**',
];
foreach ($this->bundles as $bundle) {
foreach ($this->makeDornyPathsFilterFilters($bundle) as $p) {
if (str_starts_with($p, '.github/scripts/download-bundled/')) {
continue;
}

$paths[] = $p;
}
}
$content = str_replace('%paths%', $this->indentString($this->encodeYml($paths), 3, false), $content);

$filters = [];
foreach ($this->bundles as $bundle) {
$filters[$bundle->getNameForPath()] = $this->makeDornyPathsFilterFilters($bundle);
}
$content = str_replace('%filters%', $this->indentString($this->encodeYml($this->encodeYml($filters)), 5, false), $content);

$steps = [];
foreach ($this->bundles as $bundle) {
$steps[] = [
'name' => $bundle->name,
'if' => '${{ !cancelled() && (steps.changes.outputs.' . $bundle->getNameForPath() . ' == \'true\' || github.event_name == \'schedule\' || github.event_name == \'workflow_dispatch\') }}',
'run' => implode("\n", [
'echo "::group::Download"',
'.github/scripts/download-bundled/' . $bundle->getNameForPath() . '.sh',
'echo "::endgroup::"',
'echo "::group::Verify files"',
...array_map(static fn ($v) => '.github/scripts/test-directory-unchanged.sh \'' . $v . '\'', $bundle->directories),
'echo "::endgroup::"',
]),
];
}
$content = str_replace('%steps%', $this->indentString($this->encodeYml($steps), 3, false), $content);

file_put_contents($this->getRepoDirectory() . '/.github/workflows/verify-bundled-files.yml', $content);
}

protected function makeDornyPathsFilterFilters(Bundle $bundle): array
{
return [
'.github/scripts/download-bundled/' . $bundle->getNameForPath() . '.*',
...array_map(fn ($v) => is_file($this->getRepoDirectory() . '/' . $v) ? $v : $v . '/**', $bundle->directories),
];
}

public function makeDownloadScriptHeaders(): void
{
foreach ($this->bundles as $bundle) {
$this->makeDownloadScriptHeader($bundle);
}
}

protected function makeDownloadScriptHeader(Bundle $bundle): void
{
$scriptPath = $this->getRepoDirectory() . '/.github/scripts/download-bundled/' . $bundle->getNameForPath() . '.sh';

$content = !file_exists($scriptPath)
? "# TODO\n"
: file_get_contents($scriptPath);

$header = <<<'EOD'
#!/bin/sh
set -ex
cd "$(dirname "$0")/../../.."

tmp_dir=%tmp_dir%
rm -rf "$tmp_dir"


EOD;

$header = str_replace('%tmp_dir%', '/tmp/php-src-download-bundled/' . $bundle->getNameForPath(), $header);

if (!str_starts_with($content, $header)) {
$content = $header . $content;
}

file_put_contents($scriptPath, $content);
}
}

$generator = new Generator($bundles);
$generator->makeWorkflowFile();
$generator->makeDownloadScriptHeaders();
12 changes: 12 additions & 0 deletions .github/scripts/download-bundled/timelib.parse_date.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
diff --git a/ext/date/lib/parse_date.re b/ext/date/lib/parse_date.re
index 2f05f03..893ce16 100644
--- a/ext/date/lib/parse_date.re
+++ b/ext/date/lib/parse_date.re
@@ -1281,7 +1281,6 @@ weekdayof = (reltextnumber|reltexttext) space (dayfulls|dayfull|dayabbr)
DEBUG_OUTPUT("firstdayof | lastdayof");
TIMELIB_INIT;
TIMELIB_HAVE_RELATIVE();
- TIMELIB_UNHAVE_TIME(); // Don't merge into PHP

/* skip "last day of" or "first day of" */
if (*ptr == 'l' || *ptr == 'L') {
32 changes: 32 additions & 0 deletions .github/scripts/download-bundled/timelib.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#!/bin/sh
set -ex
cd "$(dirname "$0")/../../.."

tmp_dir=/tmp/php-src-download-bundled/timelib
rm -rf "$tmp_dir"

revision=refs/tags/2022.16

git clone --depth 1 --revision="$revision" https://github.com/derickr/timelib.git "$tmp_dir"

rm -rf ext/date/lib
cp -R "$tmp_dir" ext/date/lib

cd ext/date/lib

# remove unneeded files
rm -r docs
rm -r tests
rm -r zones
rm .gitignore
rm gettzmapping.php
rm parse_zoneinfo.c
rm win_dirent.h

# add extra files
rm -r .git
git restore parse_date.c
git restore parse_iso_intervals.c

# patch customized files
git apply -v ../../../.github/scripts/download-bundled/timelib.parse_date.patch
19 changes: 19 additions & 0 deletions .github/scripts/download-bundled/unicode-character-database.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#!/bin/sh
set -ex
cd "$(dirname "$0")/../../.."

tmp_dir=/tmp/php-src-download-bundled/unicode-character-database
rm -rf "$tmp_dir"

version=17.0.0

mkdir -p "$tmp_dir"
curl --fail https://www.unicode.org/Public/$version/ucd/UCD.zip -o "$tmp_dir/data.zip"
unzip "$tmp_dir/data.zip" -d "$tmp_dir"

cd ext/mbstring

rm libmbfl/mbfl/eaw_table.h
rm unicode_data.h

./ucgendat/ucgendat.php "$tmp_dir"
12 changes: 12 additions & 0 deletions .github/scripts/download-bundled/xsse.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/bin/sh
set -ex
cd "$(dirname "$0")/../../.."

tmp_dir=/tmp/php-src-download-bundled/xsse
rm -rf "$tmp_dir"

revision=refs/tags/xsse-1.0.0

git clone --depth 1 --revision="$revision" https://github.com/SakiTakamachi/xsse.git "$tmp_dir"

cp -f "$tmp_dir"/src/xsse.h Zend/zend_simd.h
12 changes: 12 additions & 0 deletions .github/scripts/download-bundled/xxhash.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/bin/sh
set -ex
cd "$(dirname "$0")/../../.."

tmp_dir=/tmp/php-src-download-bundled/xxhash
rm -rf "$tmp_dir"

revision=refs/tags/v0.8.2

git clone --depth 1 --revision="$revision" https://github.com/Cyan4973/xxHash.git "$tmp_dir"

cp -f "$tmp_dir"/xxhash.h ext/hash/xxhash/xxhash.h
Loading
Loading