Do not aggregate manifest files in multi-module projects
Also remove snapshot-dependency-file-name and snapshot-dependency-file-name options, since they no longer make sense
This commit is contained in:
-10
@@ -25,16 +25,6 @@ inputs:
|
||||
type: string
|
||||
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:
|
||||
description: The GitHub token to use to submit the depedency snapshot to the repository
|
||||
type: string
|
||||
|
||||
Vendored
+62
-76
@@ -7,10 +7,11 @@ require('./sourcemap-register.js');/******/ (() => { // webpackBootstrap
|
||||
"use strict";
|
||||
|
||||
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 dependency_submission_toolkit_1 = __nccwpck_require__(3415);
|
||||
const file_utils_1 = __nccwpck_require__(799);
|
||||
exports.depgraphfilename = 'maven-dependency-submission-action-depgraph.json';
|
||||
class MavenDependencyGraph {
|
||||
constructor(graph) {
|
||||
this.depGraph = graph;
|
||||
@@ -119,20 +120,20 @@ class MavenDependencyGraph {
|
||||
}
|
||||
}
|
||||
exports.MavenDependencyGraph = MavenDependencyGraph;
|
||||
function parseDependencyJson(file, isMultiModule = false) {
|
||||
function parseDependencyJson(file) {
|
||||
const data = (0, file_utils_1.loadFileContents)(file);
|
||||
const pomXmlFilepath = file.replace(`target/${exports.depgraphfilename}`, 'pom.xml');
|
||||
if (!data) {
|
||||
return {
|
||||
filePath: pomXmlFilepath,
|
||||
graphName: 'empty',
|
||||
artifacts: [],
|
||||
dependencies: [],
|
||||
isMultiModule: isMultiModule
|
||||
};
|
||||
}
|
||||
try {
|
||||
const depGraph = JSON.parse(data);
|
||||
depGraph.isMultiModule = isMultiModule;
|
||||
return depGraph;
|
||||
return Object.assign(Object.assign({}, depGraph), { filePath: pomXmlFilepath });
|
||||
}
|
||||
catch (err) {
|
||||
throw new Error(`Failed to parse JSON dependency data: ${err.message}`);
|
||||
@@ -252,8 +253,6 @@ function run() {
|
||||
mavenArgs: core.getInput('maven-args') || '',
|
||||
};
|
||||
const snapshotConfig = {
|
||||
includeManifestFile: core.getBooleanInput('snapshot-include-file-name'),
|
||||
manifestFile: core.getInput('snapshot-dependency-file-name'),
|
||||
sha: core.getInput('snapshot-sha'),
|
||||
ref: core.getInput('snapshot-ref'),
|
||||
};
|
||||
@@ -482,39 +481,21 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
||||
});
|
||||
};
|
||||
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 path = __importStar(__nccwpck_require__(1017));
|
||||
const dependency_submission_toolkit_1 = __nccwpck_require__(3415);
|
||||
const depgraph_1 = __nccwpck_require__(8047);
|
||||
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 DEPGRAPH_MAVEN_PLUGIN_VERSION = '4.0.3';
|
||||
function generateSnapshot(directory, mvnConfig, snapshotConfig) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
var _a, _b;
|
||||
const depgraph = yield generateDependencyGraph(directory, mvnConfig);
|
||||
try {
|
||||
const mavenDependencies = new depgraph_1.MavenDependencyGraph(depgraph);
|
||||
let manifest;
|
||||
if (snapshotConfig === null || snapshotConfig === void 0 ? void 0 : snapshotConfig.includeManifestFile) {
|
||||
let pomFile;
|
||||
if (snapshotConfig === null || snapshotConfig === void 0 ? void 0 : 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 depgraphs = yield generateDependencyGraphs(directory, mvnConfig);
|
||||
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);
|
||||
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;
|
||||
@@ -526,12 +507,19 @@ function generateSnapshot(directory, mvnConfig, snapshotConfig) {
|
||||
if (specifiedSha) {
|
||||
snapshot.sha = specifiedSha;
|
||||
}
|
||||
return snapshot;
|
||||
try {
|
||||
for (const depgraph of depgraphs) {
|
||||
const mavenDependencies = new depgraph_1.MavenDependencyGraph(depgraph);
|
||||
const pomFile = getRepositoryRelativePath(depgraph.filePath);
|
||||
const manifest = mavenDependencies.createManifest(pomFile);
|
||||
snapshot.addManifest(manifest);
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
core.error(err);
|
||||
throw new Error(`Could not generate a snapshot of the dependencies; ${err.message}`);
|
||||
}
|
||||
return snapshot;
|
||||
});
|
||||
}
|
||||
exports.generateSnapshot = generateSnapshot;
|
||||
@@ -542,71 +530,44 @@ function getDetector() {
|
||||
version: packageData.version
|
||||
};
|
||||
}
|
||||
function generateDependencyGraph(directory, config) {
|
||||
function generateDependencyGraphs(directory, config) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
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);
|
||||
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');
|
||||
const mavenAggregateArguments = [
|
||||
`com.github.ferstl:depgraph-maven-plugin:${DEPGRAPH_MAVEN_PLUGIN_VERSION}:aggregate`,
|
||||
const mavenGraphArguments = [
|
||||
`com.github.ferstl:depgraph-maven-plugin:${DEPGRAPH_MAVEN_PLUGIN_VERSION}:graph`,
|
||||
'-DgraphFormat=json',
|
||||
'-DoutputDirectory=target',
|
||||
'-DoutputFileName=aggregate-depgraph.json'
|
||||
`-DoutputFileName=${depgraph_1.depgraphfilename}`,
|
||||
];
|
||||
const aggregateResults = yield mvn.exec(directory, mavenAggregateArguments);
|
||||
core.info(aggregateResults.stdout);
|
||||
core.info(aggregateResults.stderr);
|
||||
const graphResults = yield mvn.exec(directory, mavenGraphArguments);
|
||||
core.info(graphResults.stdout);
|
||||
core.info(graphResults.stderr);
|
||||
core.endGroup();
|
||||
if (aggregateResults.exitCode !== 0) {
|
||||
throw new Error(`Failed to successfully dependency results with Maven, exit code: ${aggregateResults.exitCode}`);
|
||||
if (graphResults.exitCode !== 0) {
|
||||
throw new Error(`Failed to successfully dependency results with Maven, exit code: ${graphResults.exitCode}`);
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
core.error(err);
|
||||
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 isMultiModule = checkForMultiModule(path.join(targetPath, 'reactor.json'));
|
||||
// Now we have the aggregate dependency graph file to process
|
||||
const aggregateGraphFile = path.join(targetPath, 'aggregate-depgraph.json');
|
||||
const graphFiles = getDepgraphFiles(directory, depgraph_1.depgraphfilename);
|
||||
let results = [];
|
||||
for (const graphFile of graphFiles) {
|
||||
core.debug(`Found depgraph file: ${graphFile}`);
|
||||
try {
|
||||
return (0, depgraph_1.parseDependencyJson)(aggregateGraphFile, isMultiModule);
|
||||
const depgraph = (0, depgraph_1.parseDependencyJson)(graphFile);
|
||||
results.push(depgraph);
|
||||
}
|
||||
catch (err) {
|
||||
core.error(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;
|
||||
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;
|
||||
}
|
||||
exports.generateDependencyGraphs = generateDependencyGraphs;
|
||||
// TODO this is assuming the checkout was made into the base path of the workspace...
|
||||
function getRepositoryRelativePath(file) {
|
||||
const workspaceDirectory = path.resolve(process.env.GITHUB_WORKSPACE || '.');
|
||||
@@ -631,6 +592,31 @@ function getNonEmptyValue(str) {
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
// getDepgraphFiles should *recursively* find 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
|
||||
|
||||
/***/ }),
|
||||
|
||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
+10
-5
@@ -4,10 +4,10 @@ import { DependencyScope } from '@github/dependency-submission-toolkit';
|
||||
import { loadFileContents } from './utils/file-utils';
|
||||
|
||||
export type Depgraph = {
|
||||
filePath: string,
|
||||
graphName: string,
|
||||
artifacts: DepgraphArtifact[],
|
||||
dependencies: DepgraphDependency[],
|
||||
isMultiModule: boolean,
|
||||
}
|
||||
|
||||
export type DepgraphArtifact = {
|
||||
@@ -30,6 +30,8 @@ export type DepgraphDependency = {
|
||||
resolution: string,
|
||||
}
|
||||
|
||||
export const depgraphfilename = 'maven-dependency-submission-action-depgraph.json';
|
||||
|
||||
export class MavenDependencyGraph {
|
||||
|
||||
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 pomXmlFilepath = file.replace(`target/${depgraphfilename}`, 'pom.xml');
|
||||
|
||||
if (!data) {
|
||||
return {
|
||||
filePath: pomXmlFilepath,
|
||||
graphName: 'empty',
|
||||
artifacts: [],
|
||||
dependencies: [],
|
||||
isMultiModule: isMultiModule
|
||||
};
|
||||
}
|
||||
|
||||
try {
|
||||
const depGraph: Depgraph = JSON.parse(data);
|
||||
depGraph.isMultiModule = isMultiModule;
|
||||
return depGraph;
|
||||
return {
|
||||
...depGraph,
|
||||
filePath: pomXmlFilepath,
|
||||
};
|
||||
} catch (err: any) {
|
||||
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('--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-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,
|
||||
ref: opts.branchRef,
|
||||
|
||||
manifestFile: opts.snapshotDependencyFileName,
|
||||
includeManifestFile: !opts.snapshotExcludeFileName,
|
||||
detector: detector
|
||||
}
|
||||
|
||||
|
||||
@@ -13,8 +13,6 @@ async function run() {
|
||||
mavenArgs: core.getInput('maven-args') || '',
|
||||
}
|
||||
const snapshotConfig: SnapshotConfig = {
|
||||
includeManifestFile: core.getBooleanInput('snapshot-include-file-name'),
|
||||
manifestFile: core.getInput('snapshot-dependency-file-name'),
|
||||
sha: core.getInput('snapshot-sha'),
|
||||
ref: core.getInput('snapshot-ref'),
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
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 { Manifest } from '@github/dependency-submission-toolkit';
|
||||
|
||||
describe('snapshot-generator', () => {
|
||||
|
||||
@@ -8,7 +9,11 @@ describe('snapshot-generator', () => {
|
||||
|
||||
it('should generate a snapshot for a simple project', async () => {
|
||||
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);
|
||||
}, 20000);
|
||||
});
|
||||
@@ -37,9 +42,50 @@ describe('snapshot-generator', () => {
|
||||
const projectDir = getMavenProjectDirectory('multi-module-multi-branch');
|
||||
const snapshot = await generateSnapshot(projectDir);
|
||||
|
||||
expect(snapshot.manifests['bs-parent']).toBeDefined();
|
||||
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);
|
||||
|
||||
it('should generate a snapshot for a maven-wrapper project', async () => {
|
||||
@@ -95,3 +141,11 @@ describe('snapshot-generator', () => {
|
||||
}, 20000);
|
||||
});
|
||||
});
|
||||
|
||||
function getDirectDependencyPurls(manifest: Manifest): string[] {
|
||||
return Object.values(manifest.resolved).filter(dep => dep.relationship === 'direct').map(dep => dep.depPackage.packageURL.toString()).sort();
|
||||
}
|
||||
|
||||
function getOtherDependencyPurls(manifest: Manifest): string[] {
|
||||
return Object.values(manifest.resolved).filter(dep => dep.relationship !== 'direct').map(dep => dep.depPackage.packageURL.toString()).sort();
|
||||
}
|
||||
+58
-75
@@ -2,9 +2,10 @@ import * as core from '@actions/core';
|
||||
import * as path from 'path';
|
||||
|
||||
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 { loadFileContents } from './utils/file-utils';
|
||||
import { readdirSync } from 'fs';
|
||||
|
||||
const packageData = require('../package.json');
|
||||
const DEPGRAPH_MAVEN_PLUGIN_VERSION = '4.0.3';
|
||||
@@ -16,8 +17,6 @@ export type MavenConfiguration = {
|
||||
}
|
||||
|
||||
export type SnapshotConfig = {
|
||||
includeManifestFile?: boolean;
|
||||
manifestFile?: string;
|
||||
context?: any;
|
||||
job?: any;
|
||||
sha?: any;
|
||||
@@ -31,28 +30,9 @@ export type SnapshotConfig = {
|
||||
};
|
||||
|
||||
export async function generateSnapshot(directory: string, mvnConfig?: MavenConfiguration, snapshotConfig?: SnapshotConfig) {
|
||||
const depgraph = await generateDependencyGraph(directory, mvnConfig);
|
||||
|
||||
try {
|
||||
const mavenDependencies = new MavenDependencyGraph(depgraph);
|
||||
|
||||
let manifest: 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 depgraphs = await generateDependencyGraphs(directory, mvnConfig);
|
||||
const detector = snapshotConfig?.detector ?? getDetector();
|
||||
const snapshot = new Snapshot(detector, snapshotConfig?.context, snapshotConfig?.job);
|
||||
snapshot.addManifest(manifest);
|
||||
let snapshot = new Snapshot(detector, snapshotConfig?.context, snapshotConfig?.job);
|
||||
|
||||
snapshot.job.correlator = snapshotConfig?.correlator
|
||||
? snapshotConfig.correlator
|
||||
@@ -68,11 +48,19 @@ export async function generateSnapshot(directory: string, mvnConfig?: MavenConfi
|
||||
snapshot.sha = specifiedSha;
|
||||
}
|
||||
|
||||
return snapshot;
|
||||
try {
|
||||
for (const depgraph of depgraphs) {
|
||||
const mavenDependencies = new MavenDependencyGraph(depgraph);
|
||||
const pomFile = getRepositoryRelativePath(depgraph.filePath);
|
||||
const manifest = mavenDependencies.createManifest(pomFile);
|
||||
|
||||
snapshot.addManifest(manifest);
|
||||
}
|
||||
} catch (err: any) {
|
||||
core.error(err);
|
||||
throw new Error(`Could not generate a snapshot of the dependencies; ${err.message}`);
|
||||
}
|
||||
return snapshot;
|
||||
}
|
||||
|
||||
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 {
|
||||
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');
|
||||
const mavenAggregateArguments = [
|
||||
`com.github.ferstl:depgraph-maven-plugin:${DEPGRAPH_MAVEN_PLUGIN_VERSION}:aggregate`,
|
||||
const mavenGraphArguments = [
|
||||
`com.github.ferstl:depgraph-maven-plugin:${DEPGRAPH_MAVEN_PLUGIN_VERSION}:graph`,
|
||||
'-DgraphFormat=json',
|
||||
'-DoutputDirectory=target',
|
||||
'-DoutputFileName=aggregate-depgraph.json'
|
||||
`-DoutputFileName=${depgraphfilename}`,
|
||||
];
|
||||
const aggregateResults = await mvn.exec(directory, mavenAggregateArguments);
|
||||
const graphResults = await mvn.exec(directory, mavenGraphArguments);
|
||||
|
||||
core.info(aggregateResults.stdout);
|
||||
core.info(aggregateResults.stderr);
|
||||
core.info(graphResults.stdout);
|
||||
core.info(graphResults.stderr);
|
||||
core.endGroup();
|
||||
|
||||
if (aggregateResults.exitCode !== 0) {
|
||||
throw new Error(`Failed to successfully dependency results with Maven, exit code: ${aggregateResults.exitCode}`);
|
||||
if (graphResults.exitCode !== 0) {
|
||||
throw new Error(`Failed to successfully dependency results with Maven, exit code: ${graphResults.exitCode}`);
|
||||
}
|
||||
} catch (err: any) {
|
||||
core.error(err);
|
||||
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 isMultiModule = checkForMultiModule(path.join(targetPath, 'reactor.json'));
|
||||
|
||||
// Now we have the aggregate dependency graph file to process
|
||||
const aggregateGraphFile = path.join(targetPath, 'aggregate-depgraph.json');
|
||||
const graphFiles = getDepgraphFiles(directory, depgraphfilename);
|
||||
let results: Depgraph[] = [];
|
||||
for (const graphFile of graphFiles) {
|
||||
core.debug(`Found depgraph file: ${graphFile}`);
|
||||
try {
|
||||
return parseDependencyJson(aggregateGraphFile, isMultiModule);
|
||||
const depgraph = parseDependencyJson(graphFile);
|
||||
results.push(depgraph);
|
||||
} catch (err: any) {
|
||||
core.error(err);
|
||||
throw new Error(`Could not parse maven dependency file, '${aggregateGraphFile}': ${err.message}`);
|
||||
core.error(`Could not parse depgraph file, '${graphFile}': ${err.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
function checkForMultiModule(reactorJsonFile): boolean {
|
||||
const data = 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: any) {
|
||||
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;
|
||||
return results;
|
||||
}
|
||||
|
||||
// TODO this is assuming the checkout was made into the base path of the workspace...
|
||||
@@ -182,3 +137,31 @@ function getNonEmptyValue(str?: string) {
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// getDepgraphFiles should *recursively* find all files that match the filename within the directory
|
||||
function getDepgraphFiles(directory: string, filename: string): string[] {
|
||||
let files: string[] = [];
|
||||
// debug only
|
||||
files = readdirSync(directory);
|
||||
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