Skip to content

Commit 1b1bc6b

Browse files
Initial work on SBOM support for PHAR
1 parent f40f184 commit 1b1bc6b

File tree

3 files changed

+93
-3
lines changed

3 files changed

+93
-3
lines changed

build.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@
133133

134134
<exec executable="${basedir}/build/scripts/phar-manifest.php" failonerror="true">
135135
<arg path="${basedir}/build/tmp/phar/manifest.txt"/>
136+
<arg path="${basedir}/build/tmp/phar/sbom.xml"/>
136137
</exec>
137138

138139
<copy file="${basedir}/vendor/phpunit/php-code-coverage/LICENSE" tofile="${basedir}/build/tmp/phar/php-code-coverage/LICENSE"/>

build/scripts/phar-manifest.php

Lines changed: 83 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
#!/usr/bin/env php
22
<?php declare(strict_types=1);
3-
if ($argc !== 2) {
3+
if ($argc !== 3) {
44
fwrite(
55
STDERR,
66
sprintf(
7-
'%s /path/to/manifest.txt' . PHP_EOL,
7+
'%s /path/to/manifest.txt /path/to/sbom.xml' . PHP_EOL,
88
$argv[0]
99
)
1010
);
@@ -16,6 +16,7 @@
1616
$version = version();
1717

1818
manifest($argv[1], $version, $dependencies);
19+
sbom($argv[2], $version, $dependencies);
1920

2021
function manifest(string $outputFilename, string $version, array $dependencies): void
2122
{
@@ -34,6 +35,53 @@ function manifest(string $outputFilename, string $version, array $dependencies):
3435
file_put_contents($outputFilename, $buffer);
3536
}
3637

38+
function sbom(string $outputFilename, string $version, array $dependencies): void
39+
{
40+
$writer = new XMLWriter;
41+
42+
$writer->openMemory();
43+
$writer->setIndent(true);
44+
$writer->startDocument();
45+
46+
$writer->startElement('bom');
47+
$writer->writeAttribute('xmlns', 'https://cyclonedx.org/schema/bom/1.4');
48+
49+
$writer->startElement('components');
50+
51+
writeComponent(
52+
$writer,
53+
'phpunit',
54+
'phpunit',
55+
$version,
56+
'The PHP Unit Testing framework',
57+
['BSD-3-Clause']
58+
);
59+
60+
foreach ($dependencies as $dependency) {
61+
[$group, $name] = explode('/', $dependency['name']);
62+
$dependencyVersion = $dependency['version'];
63+
64+
if (!preg_match('/^[v= ]*(([0-9]+)(\\.([0-9]+)(\\.([0-9]+)(-([0-9]+))?(-?([a-zA-Z-+][a-zA-Z0-9.\\-:]*)?)?)?)?)$/', $dependencyVersion)) {
65+
$dependencyVersion .= '@' . $dependency['source']['reference'];
66+
}
67+
68+
writeComponent(
69+
$writer,
70+
$group,
71+
$name,
72+
$dependencyVersion,
73+
$dependency['description'],
74+
$dependency['license']
75+
);
76+
}
77+
78+
$writer->endElement();
79+
$writer->endElement();
80+
$writer->endDocument();
81+
82+
file_put_contents($outputFilename, $writer->outputMemory());
83+
}
84+
3785
function dependencies(): array
3886
{
3987
return json_decode(
@@ -57,3 +105,36 @@ function version(): string
57105

58106
return $branch . '@' . $hash;
59107
}
108+
109+
function writeComponent(XMLWriter $writer, string $group, string $name, string $version, string $description, array $licenses): void
110+
{
111+
$writer->startElement('component');
112+
$writer->writeAttribute('type', 'library');
113+
114+
$writer->writeElement('group', $group);
115+
$writer->writeElement('name', $name);
116+
$writer->writeElement('version', $version);
117+
$writer->writeElement('description', $description);
118+
119+
$writer->startElement('licenses');
120+
121+
foreach ($licenses as $license) {
122+
$writer->startElement('license');
123+
$writer->writeElement('id', $license);
124+
$writer->endElement();
125+
}
126+
127+
$writer->endElement();
128+
129+
$writer->writeElement(
130+
'purl',
131+
sprintf(
132+
'pkg:composer/%s/%s@%s',
133+
$group,
134+
$name,
135+
$version
136+
)
137+
);
138+
139+
$writer->endElement();
140+
}

build/templates/binary-phar-autoload.php.in

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,14 +52,16 @@ if (__FILE__ === realpath($_SERVER['SCRIPT_NAME'])) {
5252
$execute = false;
5353
}
5454

55-
$options = getopt('', array('prepend:', 'manifest'));
55+
$options = getopt('', array('prepend:', 'manifest', 'sbom'));
5656

5757
if (isset($options['prepend'])) {
5858
require $options['prepend'];
5959
}
6060

6161
if (isset($options['manifest'])) {
6262
$printManifest = true;
63+
} elseif (isset($options['sbom'])) {
64+
$printSbom = true;
6365
}
6466

6567
unset($options);
@@ -96,6 +98,12 @@ if ($execute) {
9698
exit;
9799
}
98100

101+
if (isset($printSbom)) {
102+
print file_get_contents(__PHPUNIT_PHAR_ROOT__ . '/sbom.xml');
103+
104+
exit;
105+
}
106+
99107
unset($execute);
100108

101109
PHPUnit\TextUI\Command::main();

0 commit comments

Comments
 (0)