forked from tractorcow/silverstripe-supported-modules
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
NEW Migrate logic from workflows for reasoning about repository metadata
- Loading branch information
1 parent
ea552a5
commit cf821f6
Showing
4 changed files
with
171 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
/vendor/ | ||
composer.lock |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
{ | ||
"name": "silverstripe/supported-modules", | ||
"description": "Metadata about Silverstripe CMS supported modules and other repositories maintained by Silverstripe", | ||
"autoload": { | ||
"psr-4": { | ||
"SilverStripe\\SupportedModules\\": "src/" | ||
} | ||
}, | ||
"require": { | ||
"composer/semver": "^3.4" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
<?php | ||
|
||
namespace SilverStripe\SupportedModules; | ||
|
||
use Composer\Semver\VersionParser; | ||
use stdClass; | ||
|
||
final class BranchLogic | ||
{ | ||
public static function getCmsMajor(array $repoMetaData, string $branch, ?stdClass $composerJsonContent = null): string | ||
{ | ||
$cmsMajor = self::getCmsMajorFromBranch($repoMetaData, $branch); | ||
if ($cmsMajor == '') { | ||
$cmsMajor = self::getCmsMajorFromComposerJson($composerJsonContent); | ||
} | ||
return $cmsMajor ?: MetaData::LOWEST_SUPPORTED_CMS_MAJOR; | ||
} | ||
|
||
private static function getCmsMajorFromBranch(array $repoMetaData, string $branch): string | ||
{ | ||
$branchMajor = ''; | ||
if (preg_match('#^[1-9]+$#', $branch)) { | ||
$branchMajor = $branch; | ||
} elseif (preg_match('#^([1-9]+)\.[0-9]+$#', $branch, $matches)) { | ||
$branchMajor = $matches[1]; | ||
} | ||
foreach ($repoMetaData['majorVersionMapping'] ?? [] as $cmsMajor => $repoBranches) { | ||
if (is_numeric($cmsMajor) && in_array($branchMajor, $repoBranches)) { | ||
return $cmsMajor; | ||
} | ||
} | ||
return ''; | ||
} | ||
|
||
private static function getCmsMajorFromComposerJson(?stdClass $composerJsonContent = null): string | ||
{ | ||
if ($composerJsonContent === null) { | ||
return ''; | ||
} | ||
foreach (MetaData::getAllRepositoryMetaData() as $categoryData) { | ||
foreach ($categoryData as $repoData) { | ||
$composerName = $repoData['packagist'] ?? null; | ||
if ($composerName === null || !isset($composerJsonContent->require->$composerName)) { | ||
continue; | ||
} | ||
$parser = new VersionParser(); | ||
$constraint = $parser->parseConstraints($composerJsonContent->require->$composerName); | ||
$boundedVersion = explode('.', $constraint->getLowerBound()->getVersion()); | ||
$composerVersionMajor = $boundedVersion[0]; | ||
// If it's a non-numeric branch constraint or something unstable, don't use it | ||
if ($composerVersionMajor === 0) { | ||
continue; | ||
} | ||
foreach ($repoData['majorVersionMapping'] as $cmsMajor => $repoBranches) { | ||
if (is_numeric($cmsMajor) && in_array($composerVersionMajor, $repoBranches)) { | ||
return $cmsMajor; | ||
} | ||
} | ||
} | ||
} | ||
return ''; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
<?php | ||
|
||
namespace SilverStripe\SupportedModules; | ||
|
||
use RuntimeException; | ||
|
||
final class MetaData | ||
{ | ||
public const CATEGORY_SUPPORTED = 'supportedModules'; | ||
|
||
public const CATEGORY_WORKFLOW = 'workflow'; | ||
|
||
public const CATEGORY_TOOLING = 'tooling'; | ||
|
||
public const CATEGORY_MISC = 'misc'; | ||
|
||
public const LOWEST_SUPPORTED_CMS_MAJOR = '4'; | ||
|
||
public const HIGHEST_STABLE_CMS_MAJOR = '5'; | ||
|
||
private static array $repositoryMetaData = []; | ||
|
||
/** | ||
* Get metadata for a given repository, if we have any. | ||
* | ||
* @param string $gitHubReference The full GitHub reference for the repository | ||
* e.g. `silverstripe/silverstripe-framework`. | ||
* @param boolean $allowPartialMatch If no data is found for the full repository reference, | ||
* check for repositories with the same name but a different organisation. | ||
*/ | ||
public static function getMetaDataForRepository( | ||
string $gitHubReference, | ||
bool $allowPartialMatch = false | ||
): array { | ||
$parts = explode('/', $gitHubReference); | ||
if (count($parts) !== 2) { | ||
throw new RuntimeException('$gitHubReference must be a valid org/repo reference.'); | ||
} | ||
$candidate = null; | ||
foreach (self::getAllRepositoryMetaData() as $categoryData) { | ||
foreach ($categoryData as $repoData) { | ||
// Get data for the current repository | ||
if ($repoData['github'] === $gitHubReference) { | ||
// Exact match of org and repo name | ||
return $repoData; | ||
} elseif ($parts[1] === explode('/', $repoData['github'])[1]) { | ||
// Partial match - repo name only | ||
$candidate = $repoData; | ||
} | ||
} | ||
} | ||
if ($allowPartialMatch && $candidate !== null) { | ||
return $candidate; | ||
} | ||
return []; | ||
} | ||
|
||
/** | ||
* Get metadata for repositories that are released in lock-step with Silverstripe CMS minor releases. | ||
*/ | ||
public static function getMetaDataForLocksteppedRepos(): array | ||
{ | ||
$repos = []; | ||
foreach (self::getAllRepositoryMetaData() as $category => $categoryData) { | ||
// Skip anything that can't be lockstepped | ||
if ($category !== self::CATEGORY_SUPPORTED) { | ||
continue; | ||
} | ||
// Find lockstepped repos | ||
foreach ($categoryData as $repoData) { | ||
if (isset($repoData['lockstepped']) && $repoData['lockstepped'] && !empty($repoData['packagist'])) { | ||
$repos[$repoData['packagist']] = $repoData['majorVersionMapping']; | ||
} | ||
} | ||
} | ||
return $repos; | ||
} | ||
|
||
/** | ||
* Get all metadata about all repositories we have information about | ||
*/ | ||
public static function getAllRepositoryMetaData(): array | ||
{ | ||
if (empty(self::$repositoryMetaData)) { | ||
$rawJson = file_get_contents(__DIR__ . '/../repositories.json'); | ||
$decodedJson = json_decode($rawJson, true); | ||
if ($decodedJson === null) { | ||
throw new RuntimeException('Could not parse repositories.json data: ' . json_last_error_msg()); | ||
} | ||
self::$repositoryMetaData = $decodedJson; | ||
} | ||
return self::$repositoryMetaData; | ||
} | ||
} |