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

Composer #3

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
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
42 changes: 31 additions & 11 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,21 +1,41 @@
FROM pmmp/pocketmine-mp:latest
FROM ubuntu:18.04 as phpBuild
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

18.04 is obsolete


USER root
RUN apt-get update && apt-get install -y --no-install-recommends git

RUN mkdir /php
RUN apt-get update && apt-get install --no-install-recommends -y ca-certificates wget make autoconf automake libtool-bin m4 gzip bzip2 bison g++ git cmake pkg-config re2c
WORKDIR /php
RUN wget -q https://raw.githubusercontent.com/pmmp/php-build-scripts/stable/compile.sh
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This won't work for PM5.

RUN bash compile.sh -t linux64 -f -u -g -l -j
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These flags will need updating - -u is no longer used and -l now has a different purpose

also, -j expects a value for number of compile threads


# New slate to lose all unwanted libs (~300mb lost here)
FROM ubuntu:18.04
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same again here


RUN apt-get update && apt-get install --no-install-recommends -y ca-certificates wget

COPY --from=phpBuild /php/bin/php7 /usr/php
RUN grep -q '^extension_dir' /usr/php/bin/php.ini && \
sed -ibak "s{^extension_dir=.*{extension_dir=\"$(find /usr/php -name *debug-zts*)\"{" /usr/php/bin/php.ini || echo "extension_dir=\"$(find /usr/php -name *debug-zts*)\"" >> /usr/php/bin/php.ini
RUN ln -s /usr/php/bin/php /usr/bin/php

RUN wget -qO - https://getcomposer.org/installer | php
RUN mv composer.phar /usr/bin/composer
RUN wget -qO /usr/bin/phpstan https://github.com/phpstan/phpstan/releases/download/0.12.38/phpstan.phar
RUN chmod o+x /usr/bin/phpstan
ADD entry.php /usr/bin/entry
ADD default.phpstan.neon /pocketmine/default.phpstan.neon
RUN mkdir /deps

RUN mkdir /source
RUN chown 1000:1000 /pocketmine/default.phpstan.neon /deps /source -R
RUN mkdir /source/poggit_deps

# Default files:
ADD entry.php /usr/bin/entry
ADD default.phpstan.neon /source/default.phpstan.neon

# Permissions:
RUN groupadd -g 1000 client
RUN useradd -r -m -u 1000 -g client client

RUN chown 1000:1000 /source -R

USER pocketmine
USER client
WORKDIR /source

ENV PLUGIN_PATH /
ENV PHPSTAN_CONFIG /pocketmine/default.phpstan.neon
ENTRYPOINT ["entry"]
CMD []
12 changes: 5 additions & 7 deletions default.phpstan.neon
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
parameters:
level: 4
level: 5
paths:
- /source/src
autoload_directories:
- /source/src
- /deps
autoload_files:
- phar:///pocketmine/PocketMine-MP.phar/vendor/autoload.php
- src
excludePaths:
analyse:
- poggit_deps
202 changes: 131 additions & 71 deletions entry.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,97 +21,157 @@

declare(strict_types=1);

echo "[Info] -> Extracting plugin from plugin.zip, pluginPath: {$_ENV["PLUGIN_PATH"]}...\n";
//WorkingDir = /source/

echo "[Info] -> Getting ENV Variables...\n";

$PLUGIN_PATH = $_ENV["PLUGIN_PATH"] ?? "/";
$PHPSTAN_CONFIG = $_ENV["PHPSTAN_CONFIG"] ?? "default.phpstan.neon";
$DEFAULT_PHPSTAN_VERSION = $_ENV["DEFAULT_PHPSTAN_VERSION"] ?? "0.12.76";
$DEFAULT_POCKETMINE_VERSION = $_ENV["DEFAULT_POCKETMINE_VERSION"] ?? "3.17.0";

echo "[Info] -> Extracting plugin from plugin.zip, pluginPath: {$PLUGIN_PATH}...\n";

try {
@mkdir("/source/tmpExtractionDir");
$zip = new ZipArchive();
$zip->open("/source/plugin.zip");
$zip->extractTo("/source/tmpExtractionDir");
$zip->close();
@unlink("/source/plugin.zip");
$folder = (scandir("/source/tmpExtractionDir/"))[2]; //Thanks github.
passthru("mv /source/tmpExtractionDir/${folder}{$_ENV["PLUGIN_PATH"]}* /source/");
rrmdir("/source/tmpExtractionDir");
@mkdir("tmpExtractionDir");
$zip = new ZipArchive();
$zip->open("plugin.zip");
$zip->extractTo("tmpExtractionDir");
$zip->close();
@unlink("plugin.zip");
$folder = (scandir("tmpExtractionDir/"))[2]; //Thanks github.
passthru("mv tmpExtractionDir/${folder}{$PLUGIN_PATH}* .");
rrmdir("tmpExtractionDir");
} catch (Throwable $e){
fwrite(STDERR,$e->getMessage().PHP_EOL);
exit(3);
fwrite(STDERR,$e->getMessage().PHP_EOL);
exit(3);
}

echo "[Info] -> Extracting dependency's...\n";

try {
$folder = array_slice(scandir("/deps/"), 2);
foreach($folder as $file) {
$phar = new Phar("/deps/${file}");
$phar2 = $phar->convertToExecutable(Phar::TAR, Phar::NONE); // Create uncompressed archive
$phar2->extractTo("/deps/", null, true);
unlink("/deps/${file}");
unlink($phar2->getPath());
}
$folder = array_slice(scandir("poggit_deps/"), 2);
foreach($folder as $file) {
$phar = new Phar("poggit_deps/${file}");
$phar2 = $phar->convertToExecutable(Phar::TAR, Phar::NONE); // Create uncompressed archive
$phar2->extractTo("poggit_deps/", null, true);
unlink("poggit_deps/${file}");
unlink($phar2->getPath());
}
} catch(Throwable $e){
fwrite(STDERR,$e->getMessage().PHP_EOL);
exit(4);
fwrite(STDERR,$e->getMessage().PHP_EOL);
exit(4);
}

echo "[Info] -> Starting prerequisite checks...\n";

if(is_file("/source/phpstan.neon.dist")) $_ENV["PHPSTAN_CONFIG"] = "/source/phpstan.neon.dist";
if(is_file("/source/phpstan.neon")) $_ENV["PHPSTAN_CONFIG"] = "/source/phpstan.neon";

if(is_file("/source/plugin.yml")) {
if(!is_dir("/source/src")) {
fwrite(STDERR, "[Error] -> src directory not found. Did the container setup correctly ?".PHP_EOL);
exit(3);
}
} else {
fwrite(STDERR, "[Error] -> plugin.yml not found. Did the container setup correctly ?".PHP_EOL);
exit(3);
if(!is_file("plugin.yml")) {
fwrite(STDERR, "[Error] -> plugin.yml not found. Did the container setup correctly ?".PHP_EOL);
exit(3);
}
if(!is_dir("src")) {
fwrite(STDERR, "[Error] -> src directory not found. Did the container setup correctly ?".PHP_EOL);
exit(3);
}

if(is_file("phpstan.neon")) $PHPSTAN_CONFIG = "phpstan.neon";
if(is_file("phpstan.neon.dist")) $PHPSTAN_CONFIG = "phpstan.neon.dist";
if(is_file("poggit.phpstan.neon")) $PHPSTAN_CONFIG = "poggit.phpstan.neon";
if(is_file("poggit.phpstan.neon.dist")) $PHPSTAN_CONFIG = "poggit.phpstan.neon.dist";

echo "[Info] -> Checking for composer deps...\n";

//Priority goes to poggit.composer.json then composer.json
if(is_file("poggit.composer.json")){
echo "[Info] -> Using 'poggit.composer.json'\n";
if(is_file("composer.json")) unlink("composer.json");
rename("poggit.composer.json", "composer.json");
}
if(is_file("composer.json")){
echo "[Info] -> Installing dependencies from plugin...\n";
myShellExec("composer install --no-progress", $stdout, $stderr, $code);
if($code !== 0){
fwrite(STDERR, "[Error] -> Failed to install dependencies from plugin composer file.".PHP_EOL);
fwrite(STDOUT, $stdout);
fwrite(STDERR, $stderr);
exit(5);
}
}
$pmmp = false;
$phpstan = false;
if(is_file("vendor/composer/InstalledVersions.php")){
include "/source/vendor/composer/InstalledVersions.php";
$pmmp = \Composer\InstalledVersions::isInstalled("pocketmine/pocketmine-mp");
$phpstan = \Composer\InstalledVersions::isInstalled("phpstan/phpstan");
}
if(!$pmmp){
echo "[Info] -> Installing default pocketmine/pocketmine-mp v{$DEFAULT_POCKETMINE_VERSION}\n";
passthru("composer require pocketmine/pocketmine-mp:{$DEFAULT_POCKETMINE_VERSION} --no-progress -q");
}
if(!$phpstan){
echo "[Info] -> Installing default phpstan/phpstan v{$DEFAULT_PHPSTAN_VERSION}\n";
passthru("composer require phpstan/phpstan:{$DEFAULT_PHPSTAN_VERSION} --no-progress -q");
}

//Last check if not installed bail.
include_once "/source/vendor/composer/InstalledVersions.php";
$data = include '/source/vendor/composer/installed.php';
\Composer\InstalledVersions::reload($data);

if(is_file("/source/composer.json")) {
passthru("composer install --no-suggest --no-progress -n -o", $result);
if($result !== 0) {
fwrite(STDERR, "[Error] -> Failed to install composer dependencies !\n".PHP_EOL);
exit(5);
}
if(!\Composer\InstalledVersions::isInstalled("pocketmine/pocketmine-mp")){
echo "[Error] -> Failed to install pocketmine/pocketmine-mp\n";
exit(5);
}
if(!\Composer\InstalledVersions::isInstalled("phpstan/phpstan")){
echo "[Error] -> Failed to install phpstan/phpstan\n";
exit(5);
}

echo "[Info] -> Using pocketmine-mp v".\Composer\InstalledVersions::getVersion("pocketmine/pocketmine-mp")."\n";
echo "[Info] -> Using phpstan v".\Composer\InstalledVersions::getVersion("phpstan/phpstan")."\n";

echo "[Info] -> Starting phpstan...\n";

$proc = proc_open("phpstan analyze --error-format=json --no-progress --memory-limit=2G -c {$_ENV["PHPSTAN_CONFIG"]} > /source/phpstan-results.json", [0 => ["file", "/dev/null", "r"], 1 => ["pipe", "w"], 2 => ["pipe", "w"]], $pipes);
if(is_resource($proc)) {
$stdout = stream_get_contents($pipes[1]);
fclose($pipes[1]);
fwrite(STDOUT, $stdout);
$stderr = stream_get_contents($pipes[2]); // Go through another pipe so we can catch the data.
fclose($pipes[2]);
fwrite(STDERR, $stderr); //Pass on back to poggit.
$code = proc_close($proc);
if($code === 1){
if($stderr !== "") exit(8);
echo "[Warning] -> Analysis failed/found problems.";
exit(6);
}
if($code === 255){
//Phpstan unable to parse, shouldn't happen...
fwrite(STDERR, "[Error] -> PHPStan (255) - Unable to parse.".PHP_EOL);
exit(7);
}
if($code !== 0) {
fwrite(STDERR, "[Error] -> Unhandled exit status: $code.".PHP_EOL);
exit(9);
}
echo "[Info] -> No problems found !";
exit(0);
myShellExec("php vendor/bin/phpstan.phar analyze --error-format=json --no-progress --memory-limit=2G -c {$PHPSTAN_CONFIG} > phpstan-results.json", $stdout, $stderr, $exitCode);
fwrite(STDOUT, $stdout);
fwrite(STDERR, $stderr); //Pass on back to poggit.
if($exitCode === 1){
if($stderr !== "") exit(8);
echo "[Warning] -> Analysis failed/found problems.";
exit(6);
}
if($exitCode === 255){
//Phpstan unable to parse
fwrite(STDERR, "[Error] -> PHPStan (255) - Unable to parse.".PHP_EOL);
exit(7);
}
if($exitCode !== 0) {
//OOM Etc
fwrite(STDERR, "[Error] -> Unhandled exit status: $exitCode.".PHP_EOL);
exit(9);
}
echo "[Info] -> No problems found !";
exit(0);


function myShellExec(string $cmd, &$stdout, &$stderr = null, &$exitCode = null) {
$proc = proc_open($cmd, [
1 => ["pipe", "w"],
2 => ["pipe", "w"]
], $pipes, getcwd());
$stdout = stream_get_contents($pipes[1]);
fclose($pipes[1]);
$stderr = stream_get_contents($pipes[2]);
fclose($pipes[2]);
$exitCode = (int) proc_close($proc);
}

function rrmdir($dir) {
if (is_dir($dir)) {
$files = scandir($dir);
foreach ($files as $file)
if ($file != "." && $file != "..") rrmdir("$dir/$file");
rmdir($dir);
}
else if (file_exists($dir)) unlink($dir);
if (is_dir($dir)) {
$files = scandir($dir);
foreach ($files as $file)
if ($file != "." && $file != "..") rrmdir("$dir/$file");
rmdir($dir);
}
else if (file_exists($dir)) unlink($dir);
}