Skip to content

Commit

Permalink
Added missing handling of Dependency when environment variable `BOM…
Browse files Browse the repository at this point in the history
…_REPRODUCIBLE` is present.

Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
  • Loading branch information
jkowalleck committed May 5, 2022
1 parent facbecf commit 9cb9187
Show file tree
Hide file tree
Showing 5 changed files with 198 additions and 14 deletions.
4 changes: 4 additions & 0 deletions HISTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,14 @@ All notable changes to this project will be documented in this file.

## unreleased

* Fixed
* Added missing handling of `Dependency` when environment variable `BOM_REPRODUCIBLE` is present. (via [#])
* Misc:
* Worked packaging from whitelist to blacklist to add files, like `NOTICE`. (via [#289])

[#289]: https://github.com/CycloneDX/cyclonedx-node-module/pull/289
[#]: https://github.com/CycloneDX/cyclonedx-node-module/pull/


## 3.8.0 - 2022-04-24

Expand Down
15 changes: 9 additions & 6 deletions model/Bom.js
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,9 @@ class Bom extends CycloneDXObject {
components: this._components && this._components.length > 0 && process.env.BOM_REPRODUCIBLE
? Array.from(this._components).sort((a, b) => a.compare(b))
: this._components,
dependencies: this._dependencies
dependencies: this._dependencies && this._dependencies.length > 0 && process.env.BOM_REPRODUCIBLE
? Array.from(this._dependencies).sort((a, b) => a.compare(b))
: this._dependencies
}
return JSON.stringify(json, null, 2)
}
Expand Down Expand Up @@ -216,11 +218,12 @@ class Bom extends CycloneDXObject {

if (this._dependencies && this._dependencies.length > 0) {
const dependenciesNode = bom.ele('dependencies')
const value = []
for (const dependency of this._dependencies) {
value.push(dependency.toXML())
}
dependenciesNode.ele(value)
dependenciesNode.ele(
(process.env.BOM_REPRODUCIBLE
? Array.from(this._dependencies).sort((a, b) => a.compare(b))
: this._dependencies
).map(d => d.toXML())
)
}

return bom.end({
Expand Down
48 changes: 40 additions & 8 deletions model/Dependency.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,28 +20,47 @@
const CycloneDXObject = require('./CycloneDXObject')

class Dependency extends CycloneDXObject {
/**
* @param {string} ref
* @param {(Array<Dependency>|undefined)} [dependencies]
*/
constructor (ref, dependencies) {
super()
this._ref = ref
this._dependencies = dependencies
}

/**
* @type {string}
*/
get ref () {
return this._ref
}

/**
* @param {string} value
*/
set ref (value) {
this._ref = value
}

/**
* @type {(Array<Dependency>|undefined)}
*/
get dependencies () {
return this._dependencies
}

/**
* @param {(Array<Dependency>|undefined)} value
*/
set dependencies (value) {
this._dependencies = value
}

/**
* @param {Dependency} dependency
*/
addDependency (dependency) {
if (!this._dependencies) this._dependencies = []
this._dependencies.push(dependency)
Expand All @@ -50,10 +69,11 @@ class Dependency extends CycloneDXObject {
toJSON () {
let dependencyArray
if (this._dependencies && this._dependencies.length > 0) {
dependencyArray = []
for (const d of this._dependencies) {
dependencyArray.push(d.ref)
}
dependencyArray = (
process.env.BOM_REPRODUCIBLE
? Array.from(this._dependencies).sort((a, b) => a.compare(b))
: this._dependencies
).map(d => d.ref)
}
return {
ref: this._ref,
Expand All @@ -64,10 +84,11 @@ class Dependency extends CycloneDXObject {
toXML () {
let dependencyArray
if (this._dependencies && this._dependencies.length > 0) {
dependencyArray = []
for (const d of this._dependencies) {
dependencyArray.push({ dependency: { '@ref': d.ref } })
}
dependencyArray = (
process.env.BOM_REPRODUCIBLE
? Array.from(this._dependencies).sort((a, b) => a.compare(b))
: this._dependencies
).map(d => ({ dependency: { '@ref': d.ref } }))
}
return {
dependency: {
Expand All @@ -76,6 +97,17 @@ class Dependency extends CycloneDXObject {
}
}
}

/**
* Compare with another Dependency.
*
* @param {Dependency} other
* @return {number}
*/
compare (other) {
if (!(other instanceof Dependency)) { return 0 }
return this.ref.localeCompare(other.ref)
}
}

module.exports = Dependency
82 changes: 82 additions & 0 deletions tests/integration/__snapshots__/complex.test.js.snap

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

63 changes: 63 additions & 0 deletions tests/integration/complex.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/* eslint-env jest */

/*
* This file is part of CycloneDX Node Module.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
* Copyright (c) OWASP Foundation. All Rights Reserved.
*/

const Bom = require('../../model/Bom')
const Tool = require('../../model/Tool')
const Metadata = require('../../model/Metadata')
const Dependency = require('../../model/Dependency')
const Component = require('../../model/Component')

describe('integration of complex', () => {
const complex = new Bom()
complex.metadata = new Metadata()
complex.metadata.timestamp = new Date(0)
complex.metadata.tools.push(new Tool('foo', 'bar', '0.0.0-testing'))
complex.metadata.component = new Component()
complex.metadata.component.name = 'RootComponent'
complex.metadata.component.version = '1.33.7'
complex.metadata.component.bomRef = 'myRootComponent'
const c1 = new Component()
c1.name = 'SomeComponent'
c1.version = '23.42'
c1.bomRef = 'some-component-2342'
complex.components.push(c1)
const c2 = new Component()
c2.name = 'SomeComponent'
c2.version = '0.8.15'
c2.bomRef = 'some-component-0815'
complex.components.push(c2)
complex.addDependency(new Dependency(complex.metadata.component.bomRef, [
new Dependency(c1.bomRef),
new Dependency(c2.bomRef)
]))

test.each(
[
'XML',
'JSON'
]
)('as %s', (target, done) => {
process.env.BOM_REPRODUCIBLE = '1'
const result = complex[`to${target}`]()
expect(result).toMatchSnapshot()
done()
})
})

0 comments on commit 9cb9187

Please sign in to comment.