Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ This package ensures that your application doesn't have installed dependencies w

## Installation

### Drupal 8 ([composer.json](https://github.com/drupal-composer/drupal-security-advisories/blob/8.x/composer.json))
### Drupal 8/9 ([composer.json](https://github.com/drupal-composer/drupal-security-advisories/blob/8.x/composer.json))

```sh
~$ composer require drupal-composer/drupal-security-advisories:8.x-dev
Expand Down
48 changes: 35 additions & 13 deletions build/build-composer-json.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,9 @@ function fetchAllData($url, Client $client) {
$results = fetchAllData('https://www.drupal.org/api-d7/node.json?type=project_release&taxonomy_vocabulary_7=100&field_release_build_type=static', $client);
foreach ($results as $result) {
$nid = $result->field_release_project->id;
$core = (int) substr($result->field_release_version, 0, 1);
$core_compat = getCoreCompat($result);

// Skip D6 and older.
if ($core < 7) {
if ($core_compat < 7) {
continue;
}

Expand All @@ -73,12 +72,12 @@ function fetchAllData($url, Client $client) {
}

try {
$is_core = ($project->field_project_machine_name == 'drupal') ? TRUE : FALSE;
$constraint = VersionParser::generateRangeConstraint($result->field_release_version, $is_core);
$is_core = $project->field_project_machine_name == 'drupal';
$constraint = VersionParser::generateRangeConstraint($result->field_release_version, $is_core, $result);
if (!$constraint) {
throw new InvalidArgumentException('Invalid version number.');
}
$conflict[$core]['drupal/' . $project->field_project_machine_name][] = $constraint;
$conflict[$core_compat]['drupal/' . $project->field_project_machine_name][] = $constraint;
} catch (\Exception $e) {
// @todo: log exception
continue;
Expand All @@ -89,10 +88,10 @@ function fetchAllData($url, Client $client) {
$results = fetchAllData('https://www.drupal.org/api-d7/node.json?type=project_release&taxonomy_vocabulary_7=188131&field_release_build_type=static', $client);
foreach ($results as $result) {
$nid = $result->field_release_project->id;
$core = (int) substr($result->field_release_version, 0, 1);
$core_compat = getCoreCompat($result);

// Skip D6 and older.
if ($core < 7) {
if ($core_compat < 7) {
continue;
}

Expand All @@ -104,12 +103,12 @@ function fetchAllData($url, Client $client) {
}

try {
$is_core = ($project->field_project_machine_name == 'drupal') ? TRUE : FALSE;
$constraint = VersionParser::generateExplicitConstraint($result->field_release_version, $is_core);
$is_core = $project->field_project_machine_name == 'drupal';
$constraint = VersionParser::generateExplicitConstraint($result->field_release_version, $is_core, $result);
if (!$constraint) {
throw new InvalidArgumentException('Invalid version number.');
}
$conflict[$core]['drupal/' . $project->field_project_machine_name][] = $constraint;
$conflict[$core_compat]['drupal/' . $project->field_project_machine_name][] = $constraint;
} catch (\Exception $e) {
// @todo: log exception
continue;
Expand All @@ -121,7 +120,7 @@ function fetchAllData($url, Client $client) {
8 => 'build-8.x',
];

foreach ($conflict as $core => $packages) {
foreach ($conflict as $core_compat => $packages) {
$composer = [
'name' => 'drupal-composer/drupal-security-advisories',
'description' => 'Prevents installation of composer packages with known security vulnerabilities',
Expand All @@ -142,5 +141,28 @@ function fetchAllData($url, Client $client) {
}

ksort($composer['conflict']);
file_put_contents(__DIR__ . '/' . $target[$core] . '/composer.json', json_encode($composer, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE) . "\n");
file_put_contents(__DIR__ . '/' . $target[$core_compat] . '/composer.json', json_encode($composer, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE) . "\n");
}

/**
* @param $result
*
* @return int
*/
function getCoreCompat($result) {
switch ($result->field_release_category) {
case 'obsolete':
$core_compat = -1;
break;
case 'legacy':
$core_compat = 7;
break;
case 'current':
// Drupal's module API goes no higher than 8. Drupal 9 core advisories are published in this project's 8.x branch.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
// Drupal's module API goes no higher than 8. Drupal 9 core advisories are published in this project's 8.x branch.
// packages.drupal.org/8 is used for 8.x-* versions and all future semantically-versioned releases, which might be compatible with 8 and/or 9 & later.

"Core compatibility" is much more complex than 7, 8, or 9 nowadays. I think this really means which packages.drupal.org composer endpoint this corresponds with.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes exactly. We need a word for that.

$core_compat = 8;
break;
default:
throw new InvalidArgumentException('Unrecognized field_release_category.');
}
return $core_compat;
}
16 changes: 10 additions & 6 deletions build/src/VersionParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,24 @@

class VersionParser {

public static function generateRangeConstraint($version, $isCore) {
public static function generateRangeConstraint($version, $isCore, $result) {
if (!static::isValid($version)) {
return FALSE;
}
return $isCore ? static::handleCore($version) : static::handleContrib($version);
return $isCore ? static::handleCore($version) : static::handleContrib($version, $result);
}

public static function generateExplicitConstraint($version, $isCore) {
public static function generateExplicitConstraint($version, $isCore, $result) {
if (!static::isValid($version)) {
return FALSE;
}
if ($isCore) {
return $version;
}
else {
list($core, $version) = explode('-', $version, 2);
// $result->taxonomy_vocabulary_6 is usually a term like 8.x (https://www.drupal.org/taxonomy/term/7234).
// Its absence indicates a semver release (or a core release).
list($core, $version) = empty($result->taxonomy_vocabulary_6) ? [NULL, $version] : explode('-', $version, 2);
}
return $version;
}
Expand All @@ -29,8 +31,10 @@ public static function handleCore($version) {
return ">=$major.$minor,<$version";
}

public static function handleContrib($version) {
list($core, $version) = explode('-', $version, 2);
public static function handleContrib($version, $result) {
// $result->taxonomy_vocabulary_6 is usually a term like 8.x (https://www.drupal.org/taxonomy/term/7234).
// Its absence indicates a semver release (or a core release).
list($core, $version) = empty($result->taxonomy_vocabulary_6) ? [NULL, $version] : explode('-', $version, 2);
list($major) = explode('.', $version);
return ">=$major,<$version";
Copy link
Contributor

Choose a reason for hiding this comment

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

Like core, this should probably also be ">=$major.$minor,<$version" for semver contrib versions.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I wonder why that wasnt there before. @webflo?

Copy link
Contributor

Choose a reason for hiding this comment

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

This is also new for semantic versioning, since the API-compatibility-prefixed version numbers can only be 8.x-1.2, not 8.x-1.2.3.

}
Expand Down