Merge pull request #110 from advanced-security/juxtin/file-centric-manifests
Stop aggregating manifests in multi-module projects
This commit is contained in:
@@ -2,12 +2,12 @@
|
|||||||
|
|
||||||
This is a GitHub Action that will generate a complete dependency graph for a Maven project and submit the graph to the GitHub repository so that the graph is complete and includes all the transitive dependencies.
|
This is a GitHub Action that will generate a complete dependency graph for a Maven project and submit the graph to the GitHub repository so that the graph is complete and includes all the transitive dependencies.
|
||||||
|
|
||||||
The action will invoke maven using the `com.github.ferstl:depgraph-maven-plugin:4.0.2` plugin to generate JSON output of the complete dependency graph, which is then processed and submitted using the [Dependency Submission Toolkit](https://github.com/github/dependency-submission-toolkit) to the GitHub repository.
|
The action will invoke maven using the `com.github.ferstl:depgraph-maven-plugin:4.0.3` plugin to generate JSON output of the complete dependency graph, which is then processed and submitted using the [Dependency Submission Toolkit](https://github.com/github/dependency-submission-toolkit) to the GitHub repository.
|
||||||
|
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
As of version `3.0.0` this action now support Maven multi-module projects as well as additional Maven configuration parameters.
|
As of version `3.0.0` this action now supports Maven multi-module projects as well as additional Maven configuration parameters. As of version `5.0.0`, multi-module projects report dependencies as coming from their respective `pom.xml` files.
|
||||||
|
|
||||||
|
|
||||||
### Pre-requisites
|
### Pre-requisites
|
||||||
@@ -15,7 +15,7 @@ For this action to work properly, you must have the Maven available on PATH (`mv
|
|||||||
|
|
||||||
Custom maven `settings.xml` can now be specified as an input parameter to the action.
|
Custom maven `settings.xml` can now be specified as an input parameter to the action.
|
||||||
|
|
||||||
This action writes informations in the repository dependency graph, so if you are using the default token, you need to set the `contents: write` permission to the workflow or job. If you are using a personal access token, this token must have the `repo` scope. ([API used by this action](https://docs.github.com/en/rest/dependency-graph/dependency-submission#create-a-snapshot-of-dependencies-for-a-repository))
|
This action writes information in the repository dependency graph, so if you are using the default token, you need to set the `contents: write` permission to the workflow or job. If you are using a personal access token, this token must have the `repo` scope. ([API used by this action](https://docs.github.com/en/rest/dependency-graph/dependency-submission#create-a-snapshot-of-dependencies-for-a-repository))
|
||||||
|
|
||||||
### Inputs
|
### Inputs
|
||||||
|
|
||||||
@@ -29,10 +29,6 @@ This action writes informations in the repository dependency graph, so if you ar
|
|||||||
|
|
||||||
* `maven-args` - An optional string value (space separated) options to pass to the maven command line when generating the dependency snapshot. This is empty by default.
|
* `maven-args` - An optional string value (space separated) options to pass to the maven command line when generating the dependency snapshot. This is empty by default.
|
||||||
|
|
||||||
* `snapshot-include-file-name`: Optional flag to control whether or no the path and file name of the pom.xml is provided with the snapshot submission. Defaults to `true` so as to create a link to the repository file from the dependency tree view, but at the cost of losing the POM `artifactId` when it renders.
|
|
||||||
|
|
||||||
* `snapshot-dependency-file-name`: An optional user control file path to the POM file, requires `snapshot-include-file-name` to be `true` for the value to be submitted.
|
|
||||||
|
|
||||||
* `correlator`: An optional identifier to distinguish between multiple dependency snapshots of the same type. Defaults to the [job_id](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_id) of the current job.
|
* `correlator`: An optional identifier to distinguish between multiple dependency snapshots of the same type. Defaults to the [job_id](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_id) of the current job.
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
@@ -41,7 +37,7 @@ Generating and submitting a dependency snapshot using the defaults:
|
|||||||
|
|
||||||
```
|
```
|
||||||
- name: Submit Dependency Snapshot
|
- name: Submit Dependency Snapshot
|
||||||
uses: advanced-security/maven-dependency-submission-action@v4
|
uses: advanced-security/maven-dependency-submission-action@v5
|
||||||
```
|
```
|
||||||
|
|
||||||
Upon success it will generate a snapshot captured from Maven POM like;
|
Upon success it will generate a snapshot captured from Maven POM like;
|
||||||
|
|||||||
-10
@@ -25,16 +25,6 @@ inputs:
|
|||||||
type: string
|
type: string
|
||||||
default: ''
|
default: ''
|
||||||
|
|
||||||
snapshot-include-file-name:
|
|
||||||
description: Optionally include the file name in the dependency snapshot report to GitHub. This is required to be true if you want the results in the dependency tree to have a working link.
|
|
||||||
type: boolean
|
|
||||||
default: true
|
|
||||||
|
|
||||||
snapshot-dependency-file-name:
|
|
||||||
description: An optional override to specify the path to the file in the repository that the snapshot should be associated with.
|
|
||||||
type: string
|
|
||||||
required: false
|
|
||||||
|
|
||||||
token:
|
token:
|
||||||
description: The GitHub token to use to submit the depedency snapshot to the repository
|
description: The GitHub token to use to submit the depedency snapshot to the repository
|
||||||
type: string
|
type: string
|
||||||
|
|||||||
Vendored
+76
-90
@@ -7,10 +7,11 @@ require('./sourcemap-register.js');/******/ (() => { // webpackBootstrap
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||||
exports.artifactToPackageURL = exports.parseDependencyJson = exports.MavenDependencyGraph = void 0;
|
exports.artifactToPackageURL = exports.parseDependencyJson = exports.MavenDependencyGraph = exports.depgraphfilename = void 0;
|
||||||
const packageurl_js_1 = __nccwpck_require__(8915);
|
const packageurl_js_1 = __nccwpck_require__(8915);
|
||||||
const dependency_submission_toolkit_1 = __nccwpck_require__(3415);
|
const dependency_submission_toolkit_1 = __nccwpck_require__(3415);
|
||||||
const file_utils_1 = __nccwpck_require__(799);
|
const file_utils_1 = __nccwpck_require__(799);
|
||||||
|
exports.depgraphfilename = 'maven-dependency-submission-action-depgraph.json';
|
||||||
class MavenDependencyGraph {
|
class MavenDependencyGraph {
|
||||||
constructor(graph) {
|
constructor(graph) {
|
||||||
this.depGraph = graph;
|
this.depGraph = graph;
|
||||||
@@ -119,20 +120,20 @@ class MavenDependencyGraph {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.MavenDependencyGraph = MavenDependencyGraph;
|
exports.MavenDependencyGraph = MavenDependencyGraph;
|
||||||
function parseDependencyJson(file, isMultiModule = false) {
|
function parseDependencyJson(file) {
|
||||||
const data = (0, file_utils_1.loadFileContents)(file);
|
const data = (0, file_utils_1.loadFileContents)(file);
|
||||||
|
const pomXmlFilepath = file.replace(`target/${exports.depgraphfilename}`, 'pom.xml');
|
||||||
if (!data) {
|
if (!data) {
|
||||||
return {
|
return {
|
||||||
|
filePath: pomXmlFilepath,
|
||||||
graphName: 'empty',
|
graphName: 'empty',
|
||||||
artifacts: [],
|
artifacts: [],
|
||||||
dependencies: [],
|
dependencies: [],
|
||||||
isMultiModule: isMultiModule
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const depGraph = JSON.parse(data);
|
const depGraph = JSON.parse(data);
|
||||||
depGraph.isMultiModule = isMultiModule;
|
return Object.assign(Object.assign({}, depGraph), { filePath: pomXmlFilepath });
|
||||||
return depGraph;
|
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
throw new Error(`Failed to parse JSON dependency data: ${err.message}`);
|
throw new Error(`Failed to parse JSON dependency data: ${err.message}`);
|
||||||
@@ -252,8 +253,6 @@ function run() {
|
|||||||
mavenArgs: core.getInput('maven-args') || '',
|
mavenArgs: core.getInput('maven-args') || '',
|
||||||
};
|
};
|
||||||
const snapshotConfig = {
|
const snapshotConfig = {
|
||||||
includeManifestFile: core.getBooleanInput('snapshot-include-file-name'),
|
|
||||||
manifestFile: core.getInput('snapshot-dependency-file-name'),
|
|
||||||
sha: core.getInput('snapshot-sha'),
|
sha: core.getInput('snapshot-sha'),
|
||||||
ref: core.getInput('snapshot-ref'),
|
ref: core.getInput('snapshot-ref'),
|
||||||
};
|
};
|
||||||
@@ -482,56 +481,45 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||||
exports.generateDependencyGraph = exports.generateSnapshot = void 0;
|
exports.generateDependencyGraphs = exports.generateSnapshot = void 0;
|
||||||
const core = __importStar(__nccwpck_require__(2186));
|
const core = __importStar(__nccwpck_require__(2186));
|
||||||
const path = __importStar(__nccwpck_require__(1017));
|
const path = __importStar(__nccwpck_require__(1017));
|
||||||
const dependency_submission_toolkit_1 = __nccwpck_require__(3415);
|
const dependency_submission_toolkit_1 = __nccwpck_require__(3415);
|
||||||
const depgraph_1 = __nccwpck_require__(8047);
|
const depgraph_1 = __nccwpck_require__(8047);
|
||||||
const maven_runner_1 = __nccwpck_require__(7433);
|
const maven_runner_1 = __nccwpck_require__(7433);
|
||||||
const file_utils_1 = __nccwpck_require__(799);
|
const fs_1 = __nccwpck_require__(7147);
|
||||||
const packageData = __nccwpck_require__(2876);
|
const packageData = __nccwpck_require__(2876);
|
||||||
const DEPGRAPH_MAVEN_PLUGIN_VERSION = '4.0.3';
|
const DEPGRAPH_MAVEN_PLUGIN_VERSION = '4.0.3';
|
||||||
function generateSnapshot(directory, mvnConfig, snapshotConfig) {
|
function generateSnapshot(directory, mvnConfig, snapshotConfig) {
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
var _a, _b;
|
var _a, _b;
|
||||||
const depgraph = yield generateDependencyGraph(directory, mvnConfig);
|
const depgraphs = yield generateDependencyGraphs(directory, mvnConfig);
|
||||||
|
const detector = (_a = snapshotConfig === null || snapshotConfig === void 0 ? void 0 : snapshotConfig.detector) !== null && _a !== void 0 ? _a : getDetector();
|
||||||
|
let snapshot = new dependency_submission_toolkit_1.Snapshot(detector, snapshotConfig === null || snapshotConfig === void 0 ? void 0 : snapshotConfig.context, snapshotConfig === null || snapshotConfig === void 0 ? void 0 : snapshotConfig.job);
|
||||||
|
snapshot.job.correlator = (snapshotConfig === null || snapshotConfig === void 0 ? void 0 : snapshotConfig.correlator)
|
||||||
|
? snapshotConfig.correlator
|
||||||
|
: (_b = snapshot.job) === null || _b === void 0 ? void 0 : _b.correlator;
|
||||||
|
const specifiedRef = getNonEmptyValue(snapshotConfig === null || snapshotConfig === void 0 ? void 0 : snapshotConfig.ref);
|
||||||
|
if (specifiedRef) {
|
||||||
|
snapshot.ref = specifiedRef;
|
||||||
|
}
|
||||||
|
const specifiedSha = getNonEmptyValue(snapshot === null || snapshot === void 0 ? void 0 : snapshot.sha);
|
||||||
|
if (specifiedSha) {
|
||||||
|
snapshot.sha = specifiedSha;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
const mavenDependencies = new depgraph_1.MavenDependencyGraph(depgraph);
|
for (const depgraph of depgraphs) {
|
||||||
let manifest;
|
const mavenDependencies = new depgraph_1.MavenDependencyGraph(depgraph);
|
||||||
if (snapshotConfig === null || snapshotConfig === void 0 ? void 0 : snapshotConfig.includeManifestFile) {
|
const pomFile = getRepositoryRelativePath(depgraph.filePath);
|
||||||
let pomFile;
|
const manifest = mavenDependencies.createManifest(pomFile);
|
||||||
if (snapshotConfig === null || snapshotConfig === void 0 ? void 0 : snapshotConfig.manifestFile) {
|
snapshot.addManifest(manifest);
|
||||||
pomFile = snapshotConfig.manifestFile;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// The filepath to the POM needs to be relative to the root of the GitHub repository for the links to work once uploaded
|
|
||||||
pomFile = getRepositoryRelativePath(path.join(directory, 'pom.xml'));
|
|
||||||
}
|
|
||||||
manifest = mavenDependencies.createManifest(pomFile);
|
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
manifest = mavenDependencies.createManifest();
|
|
||||||
}
|
|
||||||
const detector = (_a = snapshotConfig === null || snapshotConfig === void 0 ? void 0 : snapshotConfig.detector) !== null && _a !== void 0 ? _a : getDetector();
|
|
||||||
const snapshot = new dependency_submission_toolkit_1.Snapshot(detector, snapshotConfig === null || snapshotConfig === void 0 ? void 0 : snapshotConfig.context, snapshotConfig === null || snapshotConfig === void 0 ? void 0 : snapshotConfig.job);
|
|
||||||
snapshot.addManifest(manifest);
|
|
||||||
snapshot.job.correlator = (snapshotConfig === null || snapshotConfig === void 0 ? void 0 : snapshotConfig.correlator)
|
|
||||||
? snapshotConfig.correlator
|
|
||||||
: (_b = snapshot.job) === null || _b === void 0 ? void 0 : _b.correlator;
|
|
||||||
const specifiedRef = getNonEmptyValue(snapshotConfig === null || snapshotConfig === void 0 ? void 0 : snapshotConfig.ref);
|
|
||||||
if (specifiedRef) {
|
|
||||||
snapshot.ref = specifiedRef;
|
|
||||||
}
|
|
||||||
const specifiedSha = getNonEmptyValue(snapshot === null || snapshot === void 0 ? void 0 : snapshot.sha);
|
|
||||||
if (specifiedSha) {
|
|
||||||
snapshot.sha = specifiedSha;
|
|
||||||
}
|
|
||||||
return snapshot;
|
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
core.error(err);
|
core.error(err);
|
||||||
throw new Error(`Could not generate a snapshot of the dependencies; ${err.message}`);
|
throw new Error(`Could not generate a snapshot of the dependencies; ${err.message}`);
|
||||||
}
|
}
|
||||||
|
return snapshot;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
exports.generateSnapshot = generateSnapshot;
|
exports.generateSnapshot = generateSnapshot;
|
||||||
@@ -542,71 +530,44 @@ function getDetector() {
|
|||||||
version: packageData.version
|
version: packageData.version
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
function generateDependencyGraph(directory, config) {
|
function generateDependencyGraphs(directory, config) {
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
try {
|
try {
|
||||||
const mvn = new maven_runner_1.MavenRunner(directory, config === null || config === void 0 ? void 0 : config.settingsFile, config === null || config === void 0 ? void 0 : config.ignoreMavenWrapper, config === null || config === void 0 ? void 0 : config.mavenArgs);
|
const mvn = new maven_runner_1.MavenRunner(directory, config === null || config === void 0 ? void 0 : config.settingsFile, config === null || config === void 0 ? void 0 : config.ignoreMavenWrapper, config === null || config === void 0 ? void 0 : config.mavenArgs);
|
||||||
core.startGroup('depgraph-maven-plugin:reactor');
|
|
||||||
const mavenReactorArguments = [
|
|
||||||
`com.github.ferstl:depgraph-maven-plugin:${DEPGRAPH_MAVEN_PLUGIN_VERSION}:reactor`,
|
|
||||||
'-DgraphFormat=json',
|
|
||||||
'-DoutputFileName=reactor.json'
|
|
||||||
];
|
|
||||||
const reactorResults = yield mvn.exec(directory, mavenReactorArguments);
|
|
||||||
core.info(reactorResults.stdout);
|
|
||||||
core.info(reactorResults.stderr);
|
|
||||||
core.endGroup();
|
|
||||||
if (reactorResults.exitCode !== 0) {
|
|
||||||
throw new Error(`Failed to successfully generate reactor results with Maven, exit code: ${reactorResults.exitCode}`);
|
|
||||||
}
|
|
||||||
core.startGroup('depgraph-maven-plugin:aggregate');
|
core.startGroup('depgraph-maven-plugin:aggregate');
|
||||||
const mavenAggregateArguments = [
|
const mavenGraphArguments = [
|
||||||
`com.github.ferstl:depgraph-maven-plugin:${DEPGRAPH_MAVEN_PLUGIN_VERSION}:aggregate`,
|
`com.github.ferstl:depgraph-maven-plugin:${DEPGRAPH_MAVEN_PLUGIN_VERSION}:graph`,
|
||||||
'-DgraphFormat=json',
|
'-DgraphFormat=json',
|
||||||
'-DoutputDirectory=target',
|
`-DoutputFileName=${depgraph_1.depgraphfilename}`,
|
||||||
'-DoutputFileName=aggregate-depgraph.json'
|
|
||||||
];
|
];
|
||||||
const aggregateResults = yield mvn.exec(directory, mavenAggregateArguments);
|
const graphResults = yield mvn.exec(directory, mavenGraphArguments);
|
||||||
core.info(aggregateResults.stdout);
|
core.info(graphResults.stdout);
|
||||||
core.info(aggregateResults.stderr);
|
core.info(graphResults.stderr);
|
||||||
core.endGroup();
|
core.endGroup();
|
||||||
if (aggregateResults.exitCode !== 0) {
|
if (graphResults.exitCode !== 0) {
|
||||||
throw new Error(`Failed to successfully dependency results with Maven, exit code: ${aggregateResults.exitCode}`);
|
throw new Error(`Failed to successfully dependency results with Maven, exit code: ${graphResults.exitCode}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
core.error(err);
|
core.error(err);
|
||||||
throw new Error(`A problem was encountered generating dependency files, please check execution logs for details; ${err.message}`);
|
throw new Error(`A problem was encountered generating dependency files, please check execution logs for details; ${err.message}`);
|
||||||
}
|
}
|
||||||
const targetPath = path.join(directory, 'target');
|
const graphFiles = getDepgraphFiles(directory, depgraph_1.depgraphfilename);
|
||||||
const isMultiModule = checkForMultiModule(path.join(targetPath, 'reactor.json'));
|
let results = [];
|
||||||
// Now we have the aggregate dependency graph file to process
|
for (const graphFile of graphFiles) {
|
||||||
const aggregateGraphFile = path.join(targetPath, 'aggregate-depgraph.json');
|
core.debug(`Found depgraph file: ${graphFile}`);
|
||||||
try {
|
try {
|
||||||
return (0, depgraph_1.parseDependencyJson)(aggregateGraphFile, isMultiModule);
|
const depgraph = (0, depgraph_1.parseDependencyJson)(graphFile);
|
||||||
}
|
results.push(depgraph);
|
||||||
catch (err) {
|
}
|
||||||
core.error(err);
|
catch (err) {
|
||||||
throw new Error(`Could not parse maven dependency file, '${aggregateGraphFile}': ${err.message}`);
|
core.error(`Could not parse depgraph file, '${graphFile}': ${err.message}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return results;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
exports.generateDependencyGraph = generateDependencyGraph;
|
exports.generateDependencyGraphs = generateDependencyGraphs;
|
||||||
function checkForMultiModule(reactorJsonFile) {
|
|
||||||
const data = (0, file_utils_1.loadFileContents)(reactorJsonFile);
|
|
||||||
if (data) {
|
|
||||||
try {
|
|
||||||
const reactor = JSON.parse(data);
|
|
||||||
// The reactor file will have an array of artifacts making up the parent and child modules if it is a multi module project
|
|
||||||
return reactor.artifacts && reactor.artifacts.length > 0;
|
|
||||||
}
|
|
||||||
catch (err) {
|
|
||||||
throw new Error(`Failed to parse reactor JSON payload: ${err.message}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// If no data report that it is not a multi module project
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// TODO this is assuming the checkout was made into the base path of the workspace...
|
// TODO this is assuming the checkout was made into the base path of the workspace...
|
||||||
function getRepositoryRelativePath(file) {
|
function getRepositoryRelativePath(file) {
|
||||||
const workspaceDirectory = path.resolve(process.env.GITHUB_WORKSPACE || '.');
|
const workspaceDirectory = path.resolve(process.env.GITHUB_WORKSPACE || '.');
|
||||||
@@ -631,6 +592,31 @@ function getNonEmptyValue(str) {
|
|||||||
}
|
}
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
// getDepgraphFiles recursively finds all files that match the filename within the directory
|
||||||
|
function getDepgraphFiles(directory, filename) {
|
||||||
|
let files = [];
|
||||||
|
// debug only
|
||||||
|
files = (0, fs_1.readdirSync)(directory);
|
||||||
|
try {
|
||||||
|
files = (0, fs_1.readdirSync)(directory)
|
||||||
|
.filter((f) => f === filename)
|
||||||
|
.map((f) => path.join(directory, f));
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
core.error(`Could not read depgraphs directory: ${err.message}`);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
// recursively find all files that match the filename within the directory
|
||||||
|
const subdirs = (0, fs_1.readdirSync)(directory, { withFileTypes: true })
|
||||||
|
.filter(dirent => dirent.isDirectory())
|
||||||
|
.map(dirent => dirent.name);
|
||||||
|
for (const subdir of subdirs) {
|
||||||
|
const subdirPath = path.join(directory, subdir);
|
||||||
|
const subdirFiles = getDepgraphFiles(subdirPath, filename);
|
||||||
|
files = files.concat(subdirFiles);
|
||||||
|
}
|
||||||
|
return files;
|
||||||
|
}
|
||||||
//# sourceMappingURL=snapshot-generator.js.map
|
//# sourceMappingURL=snapshot-generator.js.map
|
||||||
|
|
||||||
/***/ }),
|
/***/ }),
|
||||||
@@ -33301,7 +33287,7 @@ exports.submitSnapshot = L;
|
|||||||
/***/ ((module) => {
|
/***/ ((module) => {
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
module.exports = JSON.parse('{"name":"maven-dependency-submission-action","version":"4.1.2","description":"Submit Maven dependencies to GitHub dependency submission API","main":"index.js","scripts":{"base-build":"npm ci && tsc","build":"npm run base-build && npm exec -- @vercel/ncc build --source-map lib/src/index.js","build-exe":"npm run build && pkg package.json --compress Gzip","test":"vitest --run"},"repository":{"type":"git","url":"git+https://github.com/advanced-security/maven-dependency-submission-action.git"},"keywords":[],"author":"GitHub, Inc","license":"MIT","bugs":{"url":"https://github.com/advanced-security/maven-dependency-submission-action/issues"},"homepage":"https://github.com/advanced-security/maven-dependency-submission-action","dependencies":{"@actions/core":"^1.10.1","@actions/exec":"^1.1.1","@github/dependency-submission-toolkit":"^2.0.0","commander":"^12.0.0","packageurl-js":"^1.2.0"},"devDependencies":{"@types/chai":"^4.3.1","@vercel/ncc":"^0.38.1","chai":"^4.3.6","@yao-pkg/pkg":"^5.11.5","ts-node":"^10.9.2","typescript":"^5.3.3","vitest":"^1.6.1"},"bin":{"cli":"lib/src/executable/cli.js"},"pkg":{"targets":["node20-linux-x64","node20-win-x64","node20-macos-x64"],"assets":["package.json"],"publicPackages":"*","outputPath":"cli"}}');
|
module.exports = JSON.parse('{"name":"maven-dependency-submission-action","version":"5.0.0","description":"Submit Maven dependencies to GitHub dependency submission API","main":"index.js","scripts":{"base-build":"npm ci && tsc","build":"npm run base-build && npm exec -- @vercel/ncc build --source-map lib/src/index.js","build-exe":"npm run build && pkg package.json --compress Gzip","test":"vitest --run"},"repository":{"type":"git","url":"git+https://github.com/advanced-security/maven-dependency-submission-action.git"},"keywords":[],"author":"GitHub, Inc","license":"MIT","bugs":{"url":"https://github.com/advanced-security/maven-dependency-submission-action/issues"},"homepage":"https://github.com/advanced-security/maven-dependency-submission-action","dependencies":{"@actions/core":"^1.10.1","@actions/exec":"^1.1.1","@github/dependency-submission-toolkit":"^2.0.0","commander":"^12.0.0","packageurl-js":"^1.2.0"},"devDependencies":{"@types/chai":"^4.3.1","@vercel/ncc":"^0.38.1","chai":"^4.3.6","@yao-pkg/pkg":"^5.11.5","ts-node":"^10.9.2","typescript":"^5.3.3","vitest":"^1.6.1"},"bin":{"cli":"lib/src/executable/cli.js"},"pkg":{"targets":["node20-linux-x64","node20-win-x64","node20-macos-x64"],"assets":["package.json"],"publicPackages":"*","outputPath":"cli"}}');
|
||||||
|
|
||||||
/***/ })
|
/***/ })
|
||||||
|
|
||||||
|
|||||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Generated
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "maven-dependency-submission-action",
|
"name": "maven-dependency-submission-action",
|
||||||
"version": "4.1.3",
|
"version": "5.0.0",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "maven-dependency-submission-action",
|
"name": "maven-dependency-submission-action",
|
||||||
"version": "4.1.3",
|
"version": "5.0.0",
|
||||||
"description": "Submit Maven dependencies to GitHub dependency submission API",
|
"description": "Submit Maven dependencies to GitHub dependency submission API",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
+10
-5
@@ -4,10 +4,10 @@ import { DependencyScope } from '@github/dependency-submission-toolkit';
|
|||||||
import { loadFileContents } from './utils/file-utils';
|
import { loadFileContents } from './utils/file-utils';
|
||||||
|
|
||||||
export type Depgraph = {
|
export type Depgraph = {
|
||||||
|
filePath: string,
|
||||||
graphName: string,
|
graphName: string,
|
||||||
artifacts: DepgraphArtifact[],
|
artifacts: DepgraphArtifact[],
|
||||||
dependencies: DepgraphDependency[],
|
dependencies: DepgraphDependency[],
|
||||||
isMultiModule: boolean,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export type DepgraphArtifact = {
|
export type DepgraphArtifact = {
|
||||||
@@ -30,6 +30,8 @@ export type DepgraphDependency = {
|
|||||||
resolution: string,
|
resolution: string,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const depgraphfilename = 'maven-dependency-submission-action-depgraph.json';
|
||||||
|
|
||||||
export class MavenDependencyGraph {
|
export class MavenDependencyGraph {
|
||||||
|
|
||||||
private depGraph: Depgraph;
|
private depGraph: Depgraph;
|
||||||
@@ -171,22 +173,25 @@ export class MavenDependencyGraph {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function parseDependencyJson(file: string, isMultiModule: boolean = false): Depgraph {
|
export function parseDependencyJson(file: string): Depgraph {
|
||||||
const data = loadFileContents(file);
|
const data = loadFileContents(file);
|
||||||
|
const pomXmlFilepath = file.replace(`target/${depgraphfilename}`, 'pom.xml');
|
||||||
|
|
||||||
if (!data) {
|
if (!data) {
|
||||||
return {
|
return {
|
||||||
|
filePath: pomXmlFilepath,
|
||||||
graphName: 'empty',
|
graphName: 'empty',
|
||||||
artifacts: [],
|
artifacts: [],
|
||||||
dependencies: [],
|
dependencies: [],
|
||||||
isMultiModule: isMultiModule
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const depGraph: Depgraph = JSON.parse(data);
|
const depGraph: Depgraph = JSON.parse(data);
|
||||||
depGraph.isMultiModule = isMultiModule;
|
return {
|
||||||
return depGraph;
|
...depGraph,
|
||||||
|
filePath: pomXmlFilepath,
|
||||||
|
};
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
throw new Error(`Failed to parse JSON dependency data: ${err.message}`);
|
throw new Error(`Failed to parse JSON dependency data: ${err.message}`);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ program.option('-j --job-name <jobName>', 'Optional name for the activity creati
|
|||||||
program.option('-i --run-id <jobName>', 'Optional Run ID number for the activity that is providing the graph');
|
program.option('-i --run-id <jobName>', 'Optional Run ID number for the activity that is providing the graph');
|
||||||
|
|
||||||
program.option('--snapshot-exclude-file-name', 'exclude the file name in the dependency snapshot report. If false the name of the artifactor from the POM will be used, but any links in GitHub will not work.');
|
program.option('--snapshot-exclude-file-name', 'exclude the file name in the dependency snapshot report. If false the name of the artifactor from the POM will be used, but any links in GitHub will not work.');
|
||||||
program.option('--snapshot-dependency-file-name <fileName>', 'optional override to specificy the path to the file that the snapshot will be associated with in the repository');
|
|
||||||
|
|
||||||
program.option('--detector-name <detectorName>', 'optional name of the detector that generated the snapshot');
|
program.option('--detector-name <detectorName>', 'optional name of the detector that generated the snapshot');
|
||||||
program.option('--detector-url <detectorUrl>', 'optional URL of the detector that generated the snapshot, but not optional if you specify an detector-name');
|
program.option('--detector-url <detectorUrl>', 'optional URL of the detector that generated the snapshot, but not optional if you specify an detector-name');
|
||||||
@@ -92,8 +91,6 @@ async function execute() {
|
|||||||
sha: opts.sha,
|
sha: opts.sha,
|
||||||
ref: opts.branchRef,
|
ref: opts.branchRef,
|
||||||
|
|
||||||
manifestFile: opts.snapshotDependencyFileName,
|
|
||||||
includeManifestFile: !opts.snapshotExcludeFileName,
|
|
||||||
detector: detector
|
detector: detector
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,8 +13,6 @@ async function run() {
|
|||||||
mavenArgs: core.getInput('maven-args') || '',
|
mavenArgs: core.getInput('maven-args') || '',
|
||||||
}
|
}
|
||||||
const snapshotConfig: SnapshotConfig = {
|
const snapshotConfig: SnapshotConfig = {
|
||||||
includeManifestFile: core.getBooleanInput('snapshot-include-file-name'),
|
|
||||||
manifestFile: core.getInput('snapshot-dependency-file-name'),
|
|
||||||
sha: core.getInput('snapshot-sha'),
|
sha: core.getInput('snapshot-sha'),
|
||||||
ref: core.getInput('snapshot-ref'),
|
ref: core.getInput('snapshot-ref'),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { getMavenProjectDirectory } from './utils/test-util';
|
import { getMavenProjectDirectory } from './utils/test-util';
|
||||||
import { generateDependencyGraph, generateSnapshot } from './snapshot-generator';
|
import { generateDependencyGraphs, generateSnapshot } from './snapshot-generator';
|
||||||
import {describe, it, expect} from 'vitest';
|
import {describe, it, expect} from 'vitest';
|
||||||
|
import { Manifest } from '@github/dependency-submission-toolkit';
|
||||||
|
|
||||||
describe('snapshot-generator', () => {
|
describe('snapshot-generator', () => {
|
||||||
|
|
||||||
@@ -8,7 +9,11 @@ describe('snapshot-generator', () => {
|
|||||||
|
|
||||||
it('should generate a snapshot for a simple project', async () => {
|
it('should generate a snapshot for a simple project', async () => {
|
||||||
const projectDir = getMavenProjectDirectory('simple');
|
const projectDir = getMavenProjectDirectory('simple');
|
||||||
const depGraph = await generateDependencyGraph(projectDir);
|
const depGraphs = await generateDependencyGraphs(projectDir);
|
||||||
|
expect(depGraphs).toBeDefined();
|
||||||
|
expect(depGraphs.length).toBe(1);
|
||||||
|
const depGraph = depGraphs[0];
|
||||||
|
|
||||||
expect(depGraph.dependencies.length).toBe(20);
|
expect(depGraph.dependencies.length).toBe(20);
|
||||||
}, 20000);
|
}, 20000);
|
||||||
});
|
});
|
||||||
@@ -37,9 +42,50 @@ describe('snapshot-generator', () => {
|
|||||||
const projectDir = getMavenProjectDirectory('multi-module-multi-branch');
|
const projectDir = getMavenProjectDirectory('multi-module-multi-branch');
|
||||||
const snapshot = await generateSnapshot(projectDir);
|
const snapshot = await generateSnapshot(projectDir);
|
||||||
|
|
||||||
expect(snapshot.manifests['bs-parent']).toBeDefined();
|
|
||||||
expect(snapshot.detector.version).toBe(version);
|
expect(snapshot.detector.version).toBe(version);
|
||||||
expect(snapshot.manifests['bs-parent'].countDependencies()).toBe(20);
|
|
||||||
|
const bsParentManifest = snapshot.manifests['bs-parent'];
|
||||||
|
expect(bsParentManifest).toBeDefined();
|
||||||
|
expect(getDirectDependencyPurls(bsParentManifest)).toEqual([
|
||||||
|
'pkg:maven/junit/junit@4.13?type=jar']);
|
||||||
|
|
||||||
|
const bsApplicationManifest = snapshot.manifests['bs-application'];
|
||||||
|
expect(bsApplicationManifest).toBeDefined();
|
||||||
|
expect(getDirectDependencyPurls(bsApplicationManifest)).toEqual([
|
||||||
|
'pkg:maven/com.github.octodemo/bs-library-web@1.0.0-SNAPSHOT?type=jar',
|
||||||
|
'pkg:maven/junit/junit@4.13?type=jar',
|
||||||
|
'pkg:maven/org.eclipse.jetty/jetty-server@10.0.10?type=jar',
|
||||||
|
]);
|
||||||
|
|
||||||
|
const bsLibrariesManifest = snapshot.manifests['bs-libraries'];
|
||||||
|
expect(bsLibrariesManifest).toBeDefined();
|
||||||
|
expect(getDirectDependencyPurls(bsLibrariesManifest)).toEqual([
|
||||||
|
'pkg:maven/junit/junit@4.13?type=jar',
|
||||||
|
'pkg:maven/org.apache.logging.log4j/log4j-api@2.19.0?type=jar',
|
||||||
|
]);
|
||||||
|
|
||||||
|
const bsOtherManifest = snapshot.manifests['bs-other'];
|
||||||
|
expect(bsOtherManifest).toBeDefined();
|
||||||
|
expect(getDirectDependencyPurls(bsOtherManifest)).toEqual([
|
||||||
|
'pkg:maven/junit/junit@4.13?type=jar',
|
||||||
|
]);
|
||||||
|
|
||||||
|
const bsLibraryDatabaseManifest = snapshot.manifests['bs-library-database'];
|
||||||
|
expect(bsLibraryDatabaseManifest).toBeDefined();
|
||||||
|
expect(getDirectDependencyPurls(bsLibraryDatabaseManifest)).toEqual([
|
||||||
|
'pkg:maven/junit/junit@4.13?type=jar',
|
||||||
|
'pkg:maven/org.apache.logging.log4j/log4j-api@2.19.0?type=jar',
|
||||||
|
'pkg:maven/org.postgresql/postgresql@42.5.0?type=jar',
|
||||||
|
'pkg:maven/org.xerial/sqlite-jdbc@3.36.0.3?type=jar',
|
||||||
|
]);
|
||||||
|
|
||||||
|
const bsLibraryWebManifest = snapshot.manifests['bs-library-web'];
|
||||||
|
expect(bsLibraryWebManifest).toBeDefined();
|
||||||
|
expect(getDirectDependencyPurls(bsLibraryWebManifest)).toEqual([
|
||||||
|
'pkg:maven/junit/junit@4.13?type=jar',
|
||||||
|
'pkg:maven/org.apache.logging.log4j/log4j-api@2.19.0?type=jar',
|
||||||
|
'pkg:maven/org.eclipse.jetty.http2/http2-http-client-transport@10.0.10?type=jar',
|
||||||
|
]);
|
||||||
}, 20000);
|
}, 20000);
|
||||||
|
|
||||||
it('should generate a snapshot for a maven-wrapper project', async () => {
|
it('should generate a snapshot for a maven-wrapper project', async () => {
|
||||||
@@ -94,4 +140,8 @@ describe('snapshot-generator', () => {
|
|||||||
expect(snapshot.job.correlator).toBe('jobCorrelator');
|
expect(snapshot.job.correlator).toBe('jobCorrelator');
|
||||||
}, 20000);
|
}, 20000);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function getDirectDependencyPurls(manifest: Manifest): string[] {
|
||||||
|
return Object.values(manifest.resolved).filter(dep => dep.relationship === 'direct').map(dep => dep.depPackage.packageURL.toString()).sort();
|
||||||
|
}
|
||||||
|
|||||||
+68
-87
@@ -2,9 +2,10 @@ import * as core from '@actions/core';
|
|||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
|
|
||||||
import { Manifest, Snapshot } from '@github/dependency-submission-toolkit';
|
import { Manifest, Snapshot } from '@github/dependency-submission-toolkit';
|
||||||
import { Depgraph, MavenDependencyGraph, parseDependencyJson } from './depgraph';
|
import { Depgraph, MavenDependencyGraph, parseDependencyJson, depgraphfilename } from './depgraph';
|
||||||
import { MavenRunner } from './maven-runner';
|
import { MavenRunner } from './maven-runner';
|
||||||
import { loadFileContents } from './utils/file-utils';
|
import { loadFileContents } from './utils/file-utils';
|
||||||
|
import { readdirSync } from 'fs';
|
||||||
|
|
||||||
const packageData = require('../package.json');
|
const packageData = require('../package.json');
|
||||||
const DEPGRAPH_MAVEN_PLUGIN_VERSION = '4.0.3';
|
const DEPGRAPH_MAVEN_PLUGIN_VERSION = '4.0.3';
|
||||||
@@ -16,8 +17,6 @@ export type MavenConfiguration = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export type SnapshotConfig = {
|
export type SnapshotConfig = {
|
||||||
includeManifestFile?: boolean;
|
|
||||||
manifestFile?: string;
|
|
||||||
context?: any;
|
context?: any;
|
||||||
job?: any;
|
job?: any;
|
||||||
sha?: any;
|
sha?: any;
|
||||||
@@ -31,48 +30,37 @@ export type SnapshotConfig = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export async function generateSnapshot(directory: string, mvnConfig?: MavenConfiguration, snapshotConfig?: SnapshotConfig) {
|
export async function generateSnapshot(directory: string, mvnConfig?: MavenConfiguration, snapshotConfig?: SnapshotConfig) {
|
||||||
const depgraph = await generateDependencyGraph(directory, mvnConfig);
|
const depgraphs = await generateDependencyGraphs(directory, mvnConfig);
|
||||||
|
const detector = snapshotConfig?.detector ?? getDetector();
|
||||||
|
let snapshot = new Snapshot(detector, snapshotConfig?.context, snapshotConfig?.job);
|
||||||
|
|
||||||
|
snapshot.job.correlator = snapshotConfig?.correlator
|
||||||
|
? snapshotConfig.correlator
|
||||||
|
: snapshot.job?.correlator;
|
||||||
|
|
||||||
|
const specifiedRef = getNonEmptyValue(snapshotConfig?.ref);
|
||||||
|
if (specifiedRef) {
|
||||||
|
snapshot.ref = specifiedRef;
|
||||||
|
}
|
||||||
|
|
||||||
|
const specifiedSha = getNonEmptyValue(snapshot?.sha);
|
||||||
|
if (specifiedSha) {
|
||||||
|
snapshot.sha = specifiedSha;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const mavenDependencies = new MavenDependencyGraph(depgraph);
|
for (const depgraph of depgraphs) {
|
||||||
|
const mavenDependencies = new MavenDependencyGraph(depgraph);
|
||||||
|
const pomFile = getRepositoryRelativePath(depgraph.filePath);
|
||||||
|
const manifest = mavenDependencies.createManifest(pomFile);
|
||||||
|
|
||||||
let manifest: Manifest;
|
snapshot.addManifest(manifest);
|
||||||
if (snapshotConfig?.includeManifestFile) {
|
|
||||||
let pomFile;
|
|
||||||
if (snapshotConfig?.manifestFile) {
|
|
||||||
pomFile = snapshotConfig.manifestFile;
|
|
||||||
} else {
|
|
||||||
// The filepath to the POM needs to be relative to the root of the GitHub repository for the links to work once uploaded
|
|
||||||
pomFile = getRepositoryRelativePath(path.join(directory, 'pom.xml'));
|
|
||||||
}
|
|
||||||
manifest = mavenDependencies.createManifest(pomFile);
|
|
||||||
} else {
|
|
||||||
manifest = mavenDependencies.createManifest();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const detector = snapshotConfig?.detector ?? getDetector();
|
|
||||||
const snapshot = new Snapshot(detector, snapshotConfig?.context, snapshotConfig?.job);
|
|
||||||
snapshot.addManifest(manifest);
|
|
||||||
|
|
||||||
snapshot.job.correlator = snapshotConfig?.correlator
|
|
||||||
? snapshotConfig.correlator
|
|
||||||
: snapshot.job?.correlator;
|
|
||||||
|
|
||||||
const specifiedRef = getNonEmptyValue(snapshotConfig?.ref);
|
|
||||||
if (specifiedRef) {
|
|
||||||
snapshot.ref = specifiedRef;
|
|
||||||
}
|
|
||||||
|
|
||||||
const specifiedSha = getNonEmptyValue(snapshot?.sha);
|
|
||||||
if (specifiedSha) {
|
|
||||||
snapshot.sha = specifiedSha;
|
|
||||||
}
|
|
||||||
|
|
||||||
return snapshot;
|
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
core.error(err);
|
core.error(err);
|
||||||
throw new Error(`Could not generate a snapshot of the dependencies; ${err.message}`);
|
throw new Error(`Could not generate a snapshot of the dependencies; ${err.message}`);
|
||||||
}
|
}
|
||||||
|
return snapshot;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getDetector() {
|
function getDetector() {
|
||||||
@@ -83,75 +71,42 @@ function getDetector() {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function generateDependencyGraph(directory: string, config?: MavenConfiguration): Promise<Depgraph> {
|
export async function generateDependencyGraphs(directory: string, config?: MavenConfiguration): Promise<Depgraph[]> {
|
||||||
try {
|
try {
|
||||||
const mvn = new MavenRunner(directory, config?.settingsFile, config?.ignoreMavenWrapper, config?.mavenArgs);
|
const mvn = new MavenRunner(directory, config?.settingsFile, config?.ignoreMavenWrapper, config?.mavenArgs);
|
||||||
|
|
||||||
core.startGroup('depgraph-maven-plugin:reactor');
|
|
||||||
const mavenReactorArguments = [
|
|
||||||
`com.github.ferstl:depgraph-maven-plugin:${DEPGRAPH_MAVEN_PLUGIN_VERSION}:reactor`,
|
|
||||||
'-DgraphFormat=json',
|
|
||||||
'-DoutputFileName=reactor.json'
|
|
||||||
];
|
|
||||||
const reactorResults = await mvn.exec(directory, mavenReactorArguments);
|
|
||||||
|
|
||||||
core.info(reactorResults.stdout);
|
|
||||||
core.info(reactorResults.stderr);
|
|
||||||
core.endGroup();
|
|
||||||
|
|
||||||
if (reactorResults.exitCode !== 0) {
|
|
||||||
throw new Error(`Failed to successfully generate reactor results with Maven, exit code: ${reactorResults.exitCode}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
core.startGroup('depgraph-maven-plugin:aggregate');
|
core.startGroup('depgraph-maven-plugin:aggregate');
|
||||||
const mavenAggregateArguments = [
|
const mavenGraphArguments = [
|
||||||
`com.github.ferstl:depgraph-maven-plugin:${DEPGRAPH_MAVEN_PLUGIN_VERSION}:aggregate`,
|
`com.github.ferstl:depgraph-maven-plugin:${DEPGRAPH_MAVEN_PLUGIN_VERSION}:graph`,
|
||||||
'-DgraphFormat=json',
|
'-DgraphFormat=json',
|
||||||
'-DoutputDirectory=target',
|
`-DoutputFileName=${depgraphfilename}`,
|
||||||
'-DoutputFileName=aggregate-depgraph.json'
|
|
||||||
];
|
];
|
||||||
const aggregateResults = await mvn.exec(directory, mavenAggregateArguments);
|
const graphResults = await mvn.exec(directory, mavenGraphArguments);
|
||||||
|
|
||||||
core.info(aggregateResults.stdout);
|
core.info(graphResults.stdout);
|
||||||
core.info(aggregateResults.stderr);
|
core.info(graphResults.stderr);
|
||||||
core.endGroup();
|
core.endGroup();
|
||||||
|
|
||||||
if (aggregateResults.exitCode !== 0) {
|
if (graphResults.exitCode !== 0) {
|
||||||
throw new Error(`Failed to successfully dependency results with Maven, exit code: ${aggregateResults.exitCode}`);
|
throw new Error(`Failed to successfully generate dependency results with Maven, exit code: ${graphResults.exitCode}`);
|
||||||
}
|
}
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
core.error(err);
|
core.error(err);
|
||||||
throw new Error(`A problem was encountered generating dependency files, please check execution logs for details; ${err.message}`);
|
throw new Error(`A problem was encountered generating dependency files, please check execution logs for details; ${err.message}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const targetPath = path.join(directory, 'target');
|
const graphFiles = getDepgraphFiles(directory, depgraphfilename);
|
||||||
const isMultiModule = checkForMultiModule(path.join(targetPath, 'reactor.json'));
|
let results: Depgraph[] = [];
|
||||||
|
for (const graphFile of graphFiles) {
|
||||||
// Now we have the aggregate dependency graph file to process
|
core.debug(`Found depgraph file: ${graphFile}`);
|
||||||
const aggregateGraphFile = path.join(targetPath, 'aggregate-depgraph.json');
|
|
||||||
try {
|
|
||||||
return parseDependencyJson(aggregateGraphFile, isMultiModule);
|
|
||||||
} catch (err: any) {
|
|
||||||
core.error(err);
|
|
||||||
throw new Error(`Could not parse maven dependency file, '${aggregateGraphFile}': ${err.message}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function checkForMultiModule(reactorJsonFile): boolean {
|
|
||||||
const data = loadFileContents(reactorJsonFile);
|
|
||||||
|
|
||||||
if (data) {
|
|
||||||
try {
|
try {
|
||||||
const reactor = JSON.parse(data);
|
const depgraph = parseDependencyJson(graphFile);
|
||||||
// The reactor file will have an array of artifacts making up the parent and child modules if it is a multi module project
|
results.push(depgraph);
|
||||||
return reactor.artifacts && reactor.artifacts.length > 0;
|
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
throw new Error(`Failed to parse reactor JSON payload: ${err.message}`);
|
core.error(`Could not parse depgraph file, '${graphFile}': ${err.message}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return results;
|
||||||
// If no data report that it is not a multi module project
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO this is assuming the checkout was made into the base path of the workspace...
|
// TODO this is assuming the checkout was made into the base path of the workspace...
|
||||||
@@ -182,3 +137,29 @@ function getNonEmptyValue(str?: string) {
|
|||||||
}
|
}
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getDepgraphFiles recursively finds all files that match the filename within the directory
|
||||||
|
function getDepgraphFiles(directory: string, filename: string): string[] {
|
||||||
|
let files: string[] = [];
|
||||||
|
try {
|
||||||
|
files = readdirSync(directory)
|
||||||
|
.filter((f: string) => f === filename)
|
||||||
|
.map((f: string) => path.join(directory, f));
|
||||||
|
} catch (err: any) {
|
||||||
|
core.error(`Could not read depgraphs directory: ${err.message}`);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
// recursively find all files that match the filename within the directory
|
||||||
|
const subdirs = readdirSync(directory, { withFileTypes: true })
|
||||||
|
.filter(dirent => dirent.isDirectory())
|
||||||
|
.map(dirent => dirent.name);
|
||||||
|
|
||||||
|
for (const subdir of subdirs) {
|
||||||
|
const subdirPath = path.join(directory, subdir);
|
||||||
|
const subdirFiles = getDepgraphFiles(subdirPath, filename);
|
||||||
|
files = files.concat(subdirFiles);
|
||||||
|
}
|
||||||
|
|
||||||
|
return files;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user