Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Automated Release Builds #4114

Merged
merged 35 commits into from
Mar 28, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
ab3444a
.editorconfig for IntelliJ mostly fitting the existing code style
Deltik Mar 22, 2020
554baf0
Imported e107_make.php and make.ini to begin release builds
Deltik Feb 11, 2020
39c0979
Updated make.ini for #4099
Deltik Feb 26, 2020
a9d8344
Reformatted e107_make.php
Deltik Feb 11, 2020
537106c
Code warning cleanup of e107_make.php
Deltik Feb 26, 2020
0d80b82
Bare minimum to build releases in GitHub Actions
Deltik Feb 28, 2020
0cf9483
Defensive cleanup of e107_make.php
Deltik Feb 29, 2020
e8a68f1
Reimplemented core_image.php deprecated checksums
Deltik Feb 29, 2020
6aeee58
JSON reimplementation of CoreImage
Deltik Mar 14, 2020
20dbdef
Began work on the core_image.php reader
Deltik Mar 15, 2020
caa0826
CoreImage: Replaced JSON with SQLite
Deltik Mar 20, 2020
6a9bfee
CoreImage: Performance optimization for removed files
Deltik Mar 20, 2020
d3539cd
CoreImage: Table for versions, slight space savings
Deltik Mar 20, 2020
84081c3
CoreImage: Pack SQLite into phar
Deltik Mar 21, 2020
0e7ad8a
Rewrite e_file_inspector implementation: Use SQLite phar
Deltik Mar 22, 2020
e828d61
Add bzip2 support to workflow test-unit.yml
Deltik Mar 22, 2020
6957745
Add old e107 releases to workflow build-release.yml
Deltik Mar 22, 2020
0494000
Rewrote e_file_inspector validation constants
Deltik Mar 23, 2020
bb1c324
Add a version filter to e_file_inspector::getPathIterator()
Deltik Mar 23, 2020
e10c323
Bugfixes and performance optimization for e_file_inspector
Deltik Mar 23, 2020
90bdc88
Performance of e_file_inspector_sqlphar::pathToDefaultPath()
Deltik Mar 23, 2020
b8ed706
Restored JSON core image generator for performance
Deltik Mar 23, 2020
76bb9f6
Extra performance in e_file_inspector_json
Deltik Mar 23, 2020
b425b4e
CoreImage: API rework
Deltik Mar 24, 2020
6f65561
e_file_inspector_json_phar: Smaller core image
Deltik Mar 24, 2020
6095c94
Minimum viable rewrite of File Inspector frontend
Deltik Mar 27, 2020
00d1714
Validation bits improvement for e_file_inspector
Deltik Mar 27, 2020
e9e080a
Reintroduced filters in File Inspector
Deltik Mar 27, 2020
f73d491
Removed support for "Check Integrity Of Core Files"
Deltik Mar 27, 2020
09d3d2b
Reimplemented File Inspector "Display results as"
Deltik Mar 27, 2020
b4f5504
File Inspector now shows the old e107 version of core files
Deltik Mar 27, 2020
aca78c0
fileinspector.php: Corrected a typo: </dit> → </div>
Deltik Mar 27, 2020
03dfb5c
Implemented insecure file check in File Inspector
Deltik Mar 27, 2020
5eb1161
File Inspector: Added missing glyph "folder_uncalc"
Deltik Mar 27, 2020
07f5beb
Code cleanup for automated release builds
Deltik Mar 28, 2020
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
803 changes: 797 additions & 6 deletions .editorconfig

Large diffs are not rendered by default.

42 changes: 42 additions & 0 deletions .github/workflows/build-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
name: Build Release

on:
push:
pull_request:


jobs:
build:
strategy:
fail-fast: false
runs-on: ubuntu-latest

steps:
- name: Update operating system software repository
run: sudo apt-get update

- name: Install operating system dependencies
run: sudo apt-get install -y git tar gzip xz-utils zip php-cli

- uses: actions/checkout@v2
with:
fetch-depth: 0

- name: Fetch version information
run: git fetch origin +refs/tags/*:refs/tags/* +refs/heads/*:refs/remotes/origin/*

# Remove this step if the old version tags make it to the official repository.
- name: Fetch version information from really old releases
run: |
git remote add deltik https://github.com/Deltik/e107.git
git fetch deltik +refs/tags/*:refs/tags/* +refs/heads/*:refs/remotes/origin/*

- name: Run build script
run: php -dphar.readonly=0 e107_make.php
working-directory: ./.github/workflows/build-release/

- name: Upload build artifacts
uses: actions/upload-artifact@v1
with:
name: release_files
path: ./.github/workflows/build-release/target/e107/release/
1 change: 1 addition & 0 deletions .github/workflows/build-release/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
target/
160 changes: 160 additions & 0 deletions .github/workflows/build-release/CoreImage.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
<?php
/**
* e107 website system
*
* Copyright (C) 2008-2020 e107 Inc (e107.org)
* Released under the terms and conditions of the
* GNU General Public License (http://www.gnu.org/licenses/gpl.txt)
*/

abstract class CoreImage
{
protected function create_image($exportFolder, $tempFolder, $currentVersion)
{
echo("[Core-Image] Scanning Dir: " . $exportFolder . "\n");
$this->generateCurrentChecksums($exportFolder, $currentVersion);

echo("[Core-Image] Scanning Removed Files from Git" . "\n");
$this->generateRemovedChecksums($tempFolder);
}

protected function generateCurrentChecksums($exportFolder, $currentVersion)
{
$absoluteBase = realpath($exportFolder);
$iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($exportFolder));

/**
* @var $file DirectoryIterator
*/
foreach ($iterator as $file)
{
if ($file->isDir()) continue;

$absolutePath = $file->getRealPath();
$relativePath = preg_replace("/^" . preg_quote($absoluteBase . "/", "/") . "/", "", $absolutePath);

if (empty($relativePath) || $relativePath == $absolutePath) continue;

$checksum = $this->checksumPath($absolutePath);
$this->insertChecksumIntoDatabase($relativePath, $checksum, $currentVersion);
}
}

protected function checksumPath($filename)
{
return $this->checksum(file_get_contents($filename));
}

protected function checksum($body)
{
return md5(str_replace(array(chr(13), chr(10)), '', $body));
}

abstract protected function insertChecksumIntoDatabase(&$relativePath, &$checksum, &$releaseVersion);

protected function generateRemovedChecksums($tempFolder)
{
$tags = $this->getGitTags();
$timeMachineFolder = $this->prepTimeMachine($tempFolder);
$this->generateRemovedChecksumsFromTags($tags, $timeMachineFolder);
}

/**
* @return array
*/
protected function getGitTags()
{
$stdout = '';
OsHelper::runValidated('git tag --list ' . escapeshellarg("v*"), $stdout);
$tags = explode("\n", trim($stdout));
$versions = [];
foreach ($tags as $tag)
{
$versions[] = preg_replace("/^v/", "", $tag);
}
$tags = array_combine($tags, $versions);
unset($versions);
uasort($tags, function ($a, $b)
{
return -version_compare($a, $b);
});
$tags = array_filter($tags, function ($version)
{
return !preg_match("/[a-z]/i", $version);
});
return $tags;
}

/**
* @param $tempFolder
* @param $repoFolder
* @return string
*/
protected function prepTimeMachine($tempFolder)
{
$timeMachineFolder = $tempFolder . "/git_time_machine/";
OsHelper::runValidated('mkdir -p ' . escapeshellarg($timeMachineFolder));
OsHelper::runValidated('git rev-parse --show-toplevel', $repoFolder);
$repoFolder = realpath(trim($repoFolder) . "/.git");
OsHelper::runValidated(
'cp -a ' .
escapeshellarg($repoFolder) .
' ' .
escapeshellarg($timeMachineFolder)
);
return $timeMachineFolder;
}

/**
* @param array $tags
* @param $timeMachineFolder
* @return mixed
*/
protected function generateRemovedChecksumsFromTags($tags, $timeMachineFolder)
{
foreach ($tags as $tag => $version)
{
$stdout = '';
OsHelper::runValidated(
'git --no-pager diff --no-renames --name-only --diff-filter D ' . escapeshellarg($tag),
$stdout
);
$removedFiles = explode("\n", trim($stdout));
OsHelper::runValidated(
'git -C ' . escapeshellarg($timeMachineFolder) . ' ' .
'checkout ' . escapeshellarg($tag)
);
foreach ($removedFiles as $removedFilePath)
{
$checksum = $this->checksumPath($timeMachineFolder . '/' . $removedFilePath);
$this->insertChecksumIntoDatabase($removedFilePath, $checksum, $version);
}
}

OsHelper::runValidated('rm -rf ' . escapeshellarg($timeMachineFolder));
}


protected function generateStub()
{
$data = "<?php\n";
$data .= "/*\n";
$data .= "+ ----------------------------------------------------------------------------+\n";
$data .= "| e107 website system\n";
$data .= "|\n";
$data .= "| Copyright (C) 2008-" . date("Y") . " e107 Inc. \n";
$data .= "| http://e107.org\n";
// $data .= "| jalist@e107.org\n";
$data .= "|\n";
$data .= "| Released under the terms and conditions of the\n";
$data .= "| GNU General Public License (http://gnu.org).\n";
$data .= "|\n";
$data .= "| \$URL$\n";
$data .= "| \$Id$\n";
$data .= "+----------------------------------------------------------------------------+\n";
$data .= "*/\n\n";
$data .= "if (!defined('e107_INIT')) { exit; }\n\n";

return $data;
}
}
134 changes: 134 additions & 0 deletions .github/workflows/build-release/JsonCoreImage.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
<?php
/**
* e107 website system
*
* Copyright (C) 2008-2020 e107 Inc (e107.org)
* Released under the terms and conditions of the
* GNU General Public License (http://www.gnu.org/licenses/gpl.txt)
*
*/

require_once("OsHelper.php");
require_once("CoreImage.php");

class JsonCoreImage extends CoreImage
{
protected $checksums = [];

public function __construct($exportFolder, $tempFolder, $currentVersion, $imageFile)
{
$this->create_image($exportFolder, $tempFolder, $currentVersion);

$this->saveImage($imageFile);
}

/**
* @param $imageFile
*/
protected function saveImage($imageFile)
{
$json_result = json_encode($this->checksums, JSON_PRETTY_PRINT);
$json_string_result = var_export($json_result, true);
$data = $this->generateStub();
$data .= '$core_image = ' . $json_string_result . ';';

$fp = fopen($imageFile, 'w');
fwrite($fp, $data);
}

protected function generateCurrentChecksums($exportFolder, $currentVersion)
{
parent::generateCurrentChecksums($exportFolder, $currentVersion);
ksort($this->checksums);
}

protected function generateRemovedChecksums($tempFolder)
{
parent::generateRemovedChecksums($tempFolder);
ksort($this->checksums);
}

/**
* @inheritDoc
*/
protected function insertChecksumIntoDatabase(&$relativePath, &$checksum, &$version)
{
$item = self::array_get($this->checksums, $relativePath, []);
if (!in_array($checksum, $item)) $item["v{$version}"] = $checksum;
self::array_set($this->checksums, $relativePath, $item);
}

/**
* Get an item from an array using "slash" notation.
*
* Based on Illuminate\Support\Arr::get()
*
* @param array $array
* @param string $key
* @param mixed $default
* @return mixed
* @copyright Copyright (c) Taylor Otwell
* @license https://github.com/illuminate/support/blob/master/LICENSE.md MIT License
*/
private static function array_get($array, $key, $default = null)
{
if (is_null($key)) return $array;

if (isset($array[$key])) return $array[$key];

foreach (explode('/', $key) as $segment)
{
if (!is_array($array) || !array_key_exists($segment, $array))
{
return $default;
}

$array = $array[$segment];
}

return $array;
}

/**
* Set an array item to a given value using "slash" notation.
*
* If no key is given to the method, the entire array will be replaced.
*
* Based on Illuminate\Support\Arr::set()
*
* @param array $array
* @param string|null $key
* @param mixed $value
* @return array
* @copyright Copyright (c) Taylor Otwell
* @license https://github.com/illuminate/support/blob/master/LICENSE.md MIT License
*/
private static function array_set(&$array, $key, $value)
{
if (is_null($key))
{
return $array = $value;
}

$keys = explode('/', $key);

while (count($keys) > 1)
{
$key = array_shift($keys);

// If the key doesn't exist at this depth, we will just create an empty array
// to hold the next value, allowing us to create the arrays to hold final
// values at the correct depth. Then we'll keep digging into the array.
if (!isset($array[$key]) || !is_array($array[$key]))
{
$array[$key] = [];
}

$array = &$array[$key];
}

$array[array_shift($keys)] = $value;

return $array;
}
}
41 changes: 41 additions & 0 deletions .github/workflows/build-release/JsonPharCoreImage.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php
/**
* e107 website system
*
* Copyright (C) 2008-2020 e107 Inc (e107.org)
* Released under the terms and conditions of the
* GNU General Public License (http://www.gnu.org/licenses/gpl.txt)
*/

require_once("JsonCoreImage.php");

class JsonPharCoreImage extends JsonCoreImage
{
protected function saveImage($imageFile)
{
$imagePharFile = "$imageFile.phar";
$phar = new Phar($imagePharFile);

$json_result = json_encode($this->checksums);

$imageJsonFile = "$imageFile.json";
$fp = fopen($imageJsonFile, 'w');
fwrite($fp, $json_result);
fclose($fp);

$phar->startBuffering();
$phar->setStub($this->generateStub());
$phar->addFile($imageJsonFile, "core_image.json");
$phar->compressFiles(Phar::GZ);
$phar->stopBuffering();
rename($imagePharFile, $imageFile);
}

protected function generateStub()
{
$data = parent::generateStub();
$data .= "__HALT_COMPILER();";

return $data;
}
}
Loading