قرینه از
https://github.com/matomo-org/matomo.git
synced 2025-08-21 22:47:43 +00:00

* [Coding Style] Enable rule PSR12.Files.FileHeader * Apply CS * Replace Piwik with Matomo in file headers * Unify file headers (position, no. of lines, https links) * Rebuild dist files * Apply CS * Fix system test that relies on line numbers in a file that had the file header updated --------- Co-authored-by: Stefan Giehl <stefan@matomo.org>
252 خطوط
8.1 KiB
PHP
252 خطوط
8.1 KiB
PHP
<?php
|
|
|
|
/**
|
|
* Matomo - free/libre analytics platform
|
|
*
|
|
* @link https://matomo.org
|
|
* @license https://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
|
*/
|
|
|
|
namespace Piwik\Plugins\TestRunner\Commands;
|
|
|
|
use Piwik\Container\StaticContainer;
|
|
use Piwik\Development;
|
|
use Piwik\Filesystem;
|
|
use Piwik\Http;
|
|
use Piwik\Plugin\ConsoleCommand;
|
|
use Piwik\Log\LoggerInterface;
|
|
|
|
/**
|
|
* Downloads the UI tests screenshots from artifacts server into the local repository.
|
|
*
|
|
* This command helps to synchronize the screenshots after they have changed.
|
|
*/
|
|
class SyncScreenshots extends ConsoleCommand
|
|
{
|
|
/**
|
|
* @var LoggerInterface
|
|
*/
|
|
private $logger;
|
|
|
|
public const BUILDURL = "https://builds-artifacts.matomo.org";
|
|
|
|
public function __construct()
|
|
{
|
|
$this->logger = StaticContainer::get(LoggerInterface::class);
|
|
|
|
parent::__construct();
|
|
}
|
|
|
|
public function isEnabled()
|
|
{
|
|
return Development::isEnabled();
|
|
}
|
|
|
|
protected function configure()
|
|
{
|
|
$this->setName('tests:sync-ui-screenshots');
|
|
$this->setAliases(['development:sync-ui-test-screenshots']);
|
|
$this->setDescription(
|
|
'For Piwik core devs. Copies screenshots from github artifacts to the tests/UI/expected-screenshots/ folder'
|
|
);
|
|
$this->addRequiredArgument(
|
|
'buildnumber',
|
|
'Travis build number you want to sync.'
|
|
);
|
|
$this->addOptionalArgument(
|
|
'screenshotsRegex',
|
|
'A regex to use when selecting screenshots to copy. If not supplied all screenshots are copied.',
|
|
['.*'],
|
|
true
|
|
);
|
|
$this->addOptionalValueOption(
|
|
'repository',
|
|
'r',
|
|
'Repository name you want to sync screenshots for.',
|
|
'matomo-org/matomo'
|
|
);
|
|
$this->addOptionalValueOption(
|
|
'http-user',
|
|
'',
|
|
'the HTTP AUTH username (for premium plugins where artifacts are protected)'
|
|
);
|
|
$this->addOptionalValueOption(
|
|
'http-password',
|
|
'',
|
|
'the HTTP AUTH password (for premium plugins where artifacts are protected)'
|
|
);
|
|
}
|
|
|
|
protected function doExecute(): int
|
|
{
|
|
$input = $this->getInput();
|
|
$output = $this->getOutput();
|
|
$buildNumber = $input->getArgument('buildnumber');
|
|
$screenshotsRegex = $input->getArgument('screenshotsRegex');
|
|
$repository = $input->getOption('repository');
|
|
$httpUser = $input->getOption('http-user');
|
|
$httpPassword = $input->getOption('http-password');
|
|
|
|
$screenshots = $this->getScreenshotList($repository, $buildNumber, $httpUser, $httpPassword);
|
|
|
|
$this->logger->notice('Downloading {number} screenshots', ['number' => count($screenshots)]);
|
|
foreach ($screenshots as $name => $url) {
|
|
if (empty($name)) {
|
|
continue;
|
|
}
|
|
|
|
if (is_array($screenshotsRegex)) {
|
|
foreach ($screenshotsRegex as $regex) {
|
|
if (preg_match('/' . $regex . '/', $name)) {
|
|
$this->logger->info('Downloading {name}', ['name' => $name]);
|
|
$this->downloadScreenshot($url, $repository, $name, $httpUser, $httpPassword);
|
|
break;
|
|
}
|
|
}
|
|
} elseif (preg_match('/' . $screenshotsRegex . '/', $name)) {
|
|
$this->logger->info('Downloading {name}', ['name' => $name]);
|
|
$this->downloadScreenshot($url, $repository, $name, $httpUser, $httpPassword);
|
|
}
|
|
}
|
|
|
|
$this->displayGitInstructions($repository);
|
|
|
|
return self::SUCCESS;
|
|
}
|
|
|
|
private function getScreenshotList($repository, $buildNumber, $httpUser = null, $httpPassword = null)
|
|
{
|
|
$url = sprintf('%s/api/%s/%s', self::BUILDURL, $repository, $buildNumber);
|
|
|
|
$this->logger->debug('Fetching {url}', ['url' => $url]);
|
|
|
|
$response = Http::sendHttpRequest(
|
|
$url,
|
|
$timeout = 160,
|
|
$userAgent = null,
|
|
$destinationPath = null,
|
|
$followDepth = 0,
|
|
$acceptLanguage = false,
|
|
$byteRange = false,
|
|
$getExtendedInfo = true,
|
|
$httpMethod = 'GET',
|
|
$httpUser,
|
|
$httpPassword
|
|
);
|
|
$httpStatus = $response['status'];
|
|
if ($httpStatus == '200') {
|
|
return json_decode($response['data'], true);
|
|
}
|
|
if ($httpStatus == '401') {
|
|
throw new \Exception('HTTP 401 - Auth username and password are invalid');
|
|
}
|
|
$this->logger->debug('Response content: {content}', ['content' => $response['data']]);
|
|
throw new \Exception("Failed downloading diffviewer from $url - Got HTTP status $httpStatus");
|
|
}
|
|
|
|
private function downloadScreenshot($url, $repository, $screenshot, $httpUser, $httpPassword)
|
|
{
|
|
$downloadTo = $this->getDownloadToPath($repository, $screenshot) . $screenshot;
|
|
|
|
$url = self::BUILDURL . $url;
|
|
|
|
$this->logger->debug("Downloading {url} to {destination}", ['url' => $url, 'destination' => $downloadTo]);
|
|
|
|
Http::sendHttpRequest(
|
|
$url,
|
|
$timeout = 160,
|
|
$userAgent = null,
|
|
$downloadTo,
|
|
$followDepth = 0,
|
|
$acceptLanguage = false,
|
|
$byteRange = false,
|
|
$getExtendedInfo = true,
|
|
$httpMethod = 'GET',
|
|
$httpUser,
|
|
$httpPassword
|
|
);
|
|
}
|
|
|
|
private function displayGitInstructions($repository)
|
|
{
|
|
$this->getOutput()->writeln(
|
|
'<comment>If all downloaded screenshots are valid you may push them with these commands:</comment>'
|
|
);
|
|
$downloadToPath = $this->getDownloadToPath($repository);
|
|
$commands = "
|
|
|
|
# Starts here
|
|
cd $downloadToPath
|
|
git pull
|
|
git add .
|
|
git status
|
|
git commit -m 'UI tests: ...' # Write a good commit message, eg. 'Fixed UI test failure caused by change introduced in X which caused failure by Y'
|
|
echo -e \"\n--> Check the commit above is correct... <---\n\"
|
|
sleep 7
|
|
git push";
|
|
|
|
if ($repository === 'matomo-org/matomo') {
|
|
$commands .= "
|
|
cd ../../../";
|
|
} else {
|
|
$commands .= "
|
|
cd ../../../../../";
|
|
}
|
|
|
|
$this->getOutput()->writeln($commands);
|
|
}
|
|
|
|
private function getDownloadToPath($repository, $fileName = false)
|
|
{
|
|
$plugin = $this->getPluginName($repository, $fileName);
|
|
|
|
if (empty($plugin)) {
|
|
return PIWIK_DOCUMENT_ROOT . "/tests/UI/expected-screenshots/";
|
|
}
|
|
|
|
$possibleSubDirs = [
|
|
'expected-screenshots',
|
|
'expected-ui-screenshots',
|
|
];
|
|
|
|
foreach ($possibleSubDirs as $subDir) {
|
|
$downloadTo = PIWIK_DOCUMENT_ROOT . "/plugins/$plugin/tests/UI/$subDir/";
|
|
if (is_dir($downloadTo)) {
|
|
return $downloadTo;
|
|
}
|
|
|
|
// Maybe the plugin is using folder "Test/" instead of "tests/"
|
|
$downloadTo = str_replace("tests/", "Test/", $downloadTo);
|
|
if (is_dir($downloadTo)) {
|
|
return $downloadTo;
|
|
}
|
|
}
|
|
throw new \Exception("Download to path could not be found: $downloadTo");
|
|
}
|
|
|
|
private function getPluginName($repository, $fileName)
|
|
{
|
|
[$org, $repository] = explode('/', $repository, 2);
|
|
|
|
if (strpos($repository, 'plugin-') === 0) {
|
|
return substr($repository, strlen('plugin-'));
|
|
}
|
|
|
|
// determine plugin based on the test name
|
|
if (!empty($fileName)) {
|
|
[$testName, $_null] = explode('_', $fileName, 2);
|
|
$foundExistingFiles = Filesystem::globr(PIWIK_DOCUMENT_ROOT, $fileName);
|
|
$foundTestSpecs = Filesystem::globr(PIWIK_DOCUMENT_ROOT, $testName . '_spec.js');
|
|
$filesToCheck = $foundExistingFiles + $foundTestSpecs;
|
|
|
|
foreach ($filesToCheck as $file) {
|
|
if (preg_match('/plugins\/([^\/]+)\//i', $file, $plugin)) {
|
|
return $plugin[1];
|
|
}
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
}
|