Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8525842317 | ||
|
|
16baf7d7ba |
@@ -1,3 +0,0 @@
|
||||
# Managed and Maintained by:
|
||||
|
||||
* @actions/advanced-security-dependency-graph
|
||||
@@ -1,8 +1,5 @@
|
||||
name: Publish Executables
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
name: Release
|
||||
|
||||
run-name: Release ${{ inputs.version }}
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
type: string
|
||||
required: true
|
||||
|
||||
jobs:
|
||||
build_and_test:
|
||||
name: Build and test
|
||||
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
cache: npm
|
||||
|
||||
- name: Build and Test
|
||||
run: |
|
||||
npm ci
|
||||
npm run test --if-present
|
||||
npm run build --if-present
|
||||
npm run build-exe --if-present
|
||||
|
||||
# - name: Check that build is clean
|
||||
# run: |
|
||||
# git diff --exit-code
|
||||
|
||||
|
||||
validate_version:
|
||||
name: Validate version number
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
steps:
|
||||
- name: Process version number as SemVer
|
||||
id: semver
|
||||
uses: peter-murray/semver-data-action@v1
|
||||
with:
|
||||
version: ${{ inputs.version }}
|
||||
|
||||
|
||||
release:
|
||||
name: Release
|
||||
|
||||
needs:
|
||||
- validate_version
|
||||
- build_and_test
|
||||
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
steps:
|
||||
- name: Process version number as SemVer
|
||||
id: semver
|
||||
uses: peter-murray/semver-data-action@v1
|
||||
with:
|
||||
version: ${{ inputs.version }}
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set git user
|
||||
run: |
|
||||
git config user.name github-actions
|
||||
git config user.email [email protected]
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
cache: npm
|
||||
|
||||
- name: Version application
|
||||
run: |
|
||||
npm version ${{ steps.semver.outputs.semver }}
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
npm ci
|
||||
npm run build --if-present
|
||||
npm run build-exe --if-present
|
||||
|
||||
- name: Check that build is clean
|
||||
id: clean_build
|
||||
continue-on-error: true
|
||||
run: |
|
||||
git diff --exit-code
|
||||
|
||||
- name: Update release
|
||||
if: steps.clean_build.outcome == 'failure'
|
||||
run: |
|
||||
git add .
|
||||
git commit -m "chore: Updating release files"
|
||||
|
||||
- name: Update tags
|
||||
if: steps.semver.outputs.isPreRelease == 'false'
|
||||
run: |
|
||||
git tag "v${{ steps.semver.outputs.semver }}" --force
|
||||
git tag "v${{ steps.semver.outputs.major }}" --force
|
||||
git tag "v${{ steps.semver.outputs.major }}.${{ steps.semver.outputs.minor }}" --force
|
||||
git tag "v${{ steps.semver.outputs.major }}.${{ steps.semver.outputs.minor }}.${{ steps.semver.outputs.patch }}" --force
|
||||
|
||||
git push origin ${{ github.ref_name }}
|
||||
git push origin --tags --force
|
||||
|
||||
- name: Attach CLI artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: cli
|
||||
path: cli
|
||||
|
||||
- name: Create release
|
||||
uses: ncipollo/[email protected]
|
||||
with:
|
||||
artifacts: cli/*
|
||||
prerelease: ${{ steps.semver.outputs.isPreRelease }}
|
||||
tag: v${{ steps.semver.outputs.semver }}
|
||||
@@ -6,7 +6,6 @@ on:
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
sync:
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
name: Test Local Action
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
|
||||
+2
-2
@@ -60,8 +60,8 @@ minor/patch updates.
|
||||
To do this just checkout `main`, force-create a new annotated tag, and push it:
|
||||
|
||||
```
|
||||
git tag -fa v5 -m "Updating v5 to 5.0.0"
|
||||
git push origin v5 --force
|
||||
git tag -fa v4 -m "Updating v4 to 4.1.2"
|
||||
git push origin v4 --force
|
||||
```
|
||||
</details>
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
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.
|
||||
As of version `3.0.0` this action now support Maven multi-module projects as well as additional Maven configuration parameters.
|
||||
|
||||
|
||||
### 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.
|
||||
|
||||
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))
|
||||
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))
|
||||
|
||||
### Inputs
|
||||
|
||||
@@ -29,6 +29,10 @@ This action writes information in the repository dependency graph, so if you are
|
||||
|
||||
* `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.
|
||||
|
||||
## Examples
|
||||
@@ -37,7 +41,7 @@ Generating and submitting a dependency snapshot using the defaults:
|
||||
|
||||
```
|
||||
- name: Submit Dependency Snapshot
|
||||
uses: advanced-security/maven-dependency-submission-action@v5
|
||||
uses: advanced-security/maven-dependency-submission-action@v4
|
||||
```
|
||||
|
||||
Upon success it will generate a snapshot captured from Maven POM like;
|
||||
|
||||
+10
@@ -25,6 +25,16 @@ 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
+91
-77
@@ -7,11 +7,10 @@ require('./sourcemap-register.js');/******/ (() => { // webpackBootstrap
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||
exports.artifactToPackageURL = exports.parseDependencyJson = exports.MavenDependencyGraph = exports.depgraphfilename = void 0;
|
||||
exports.artifactToPackageURL = exports.parseDependencyJson = exports.MavenDependencyGraph = 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;
|
||||
@@ -120,20 +119,20 @@ class MavenDependencyGraph {
|
||||
}
|
||||
}
|
||||
exports.MavenDependencyGraph = MavenDependencyGraph;
|
||||
function parseDependencyJson(file) {
|
||||
function parseDependencyJson(file, isMultiModule = false) {
|
||||
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);
|
||||
return Object.assign(Object.assign({}, depGraph), { filePath: pomXmlFilepath });
|
||||
depGraph.isMultiModule = isMultiModule;
|
||||
return depGraph;
|
||||
}
|
||||
catch (err) {
|
||||
throw new Error(`Failed to parse JSON dependency data: ${err.message}`);
|
||||
@@ -253,6 +252,8 @@ 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'),
|
||||
};
|
||||
@@ -481,45 +482,56 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
||||
});
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||
exports.generateDependencyGraphs = exports.generateSnapshot = void 0;
|
||||
exports.generateDependencyGraph = 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 fs_1 = __nccwpck_require__(7147);
|
||||
const file_utils_1 = __nccwpck_require__(799);
|
||||
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 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;
|
||||
}
|
||||
const depgraph = yield generateDependencyGraph(directory, mvnConfig);
|
||||
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);
|
||||
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 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) {
|
||||
core.error(err);
|
||||
throw new Error(`Could not generate a snapshot of the dependencies; ${err.message}`);
|
||||
}
|
||||
return snapshot;
|
||||
});
|
||||
}
|
||||
exports.generateSnapshot = generateSnapshot;
|
||||
@@ -530,44 +542,71 @@ function getDetector() {
|
||||
version: packageData.version
|
||||
};
|
||||
}
|
||||
function generateDependencyGraphs(directory, config) {
|
||||
function generateDependencyGraph(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:aggregate');
|
||||
const mavenGraphArguments = [
|
||||
`com.github.ferstl:depgraph-maven-plugin:${DEPGRAPH_MAVEN_PLUGIN_VERSION}:graph`,
|
||||
core.startGroup('depgraph-maven-plugin:reactor');
|
||||
const mavenReactorArguments = [
|
||||
`com.github.ferstl:depgraph-maven-plugin:${DEPGRAPH_MAVEN_PLUGIN_VERSION}:reactor`,
|
||||
'-DgraphFormat=json',
|
||||
`-DoutputFileName=${depgraph_1.depgraphfilename}`,
|
||||
'-DoutputFileName=reactor.json'
|
||||
];
|
||||
const graphResults = yield mvn.exec(directory, mavenGraphArguments);
|
||||
core.info(graphResults.stdout);
|
||||
core.info(graphResults.stderr);
|
||||
const reactorResults = yield mvn.exec(directory, mavenReactorArguments);
|
||||
core.info(reactorResults.stdout);
|
||||
core.info(reactorResults.stderr);
|
||||
core.endGroup();
|
||||
if (graphResults.exitCode !== 0) {
|
||||
throw new Error(`Failed to successfully dependency results with Maven, exit code: ${graphResults.exitCode}`);
|
||||
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`,
|
||||
'-DgraphFormat=json',
|
||||
'-DoutputDirectory=target',
|
||||
'-DoutputFileName=aggregate-depgraph.json'
|
||||
];
|
||||
const aggregateResults = yield mvn.exec(directory, mavenAggregateArguments);
|
||||
core.info(aggregateResults.stdout);
|
||||
core.info(aggregateResults.stderr);
|
||||
core.endGroup();
|
||||
if (aggregateResults.exitCode !== 0) {
|
||||
throw new Error(`Failed to successfully dependency results with Maven, exit code: ${aggregateResults.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 graphFiles = getDepgraphFiles(directory, depgraph_1.depgraphfilename);
|
||||
let results = [];
|
||||
for (const graphFile of graphFiles) {
|
||||
core.debug(`Found depgraph file: ${graphFile}`);
|
||||
try {
|
||||
const depgraph = (0, depgraph_1.parseDependencyJson)(graphFile);
|
||||
results.push(depgraph);
|
||||
}
|
||||
catch (err) {
|
||||
core.error(`Could not parse depgraph file, '${graphFile}': ${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');
|
||||
try {
|
||||
return (0, depgraph_1.parseDependencyJson)(aggregateGraphFile, isMultiModule);
|
||||
}
|
||||
catch (err) {
|
||||
core.error(err);
|
||||
throw new Error(`Could not parse maven dependency file, '${aggregateGraphFile}': ${err.message}`);
|
||||
}
|
||||
return results;
|
||||
});
|
||||
}
|
||||
exports.generateDependencyGraphs = generateDependencyGraphs;
|
||||
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;
|
||||
}
|
||||
// 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 || '.');
|
||||
@@ -592,31 +631,6 @@ function getNonEmptyValue(str) {
|
||||
}
|
||||
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
|
||||
|
||||
/***/ }),
|
||||
@@ -33287,7 +33301,7 @@ exports.submitSnapshot = L;
|
||||
/***/ ((module) => {
|
||||
|
||||
"use strict";
|
||||
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"}}');
|
||||
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"}}');
|
||||
|
||||
/***/ })
|
||||
|
||||
|
||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Generated
+697
-681
File diff suppressed because it is too large
Load Diff
+2
-2
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "maven-dependency-submission-action",
|
||||
"version": "5.0.0",
|
||||
"version": "4.1.2",
|
||||
"description": "Submit Maven dependencies to GitHub dependency submission API",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
@@ -34,7 +34,7 @@
|
||||
"@yao-pkg/pkg": "^5.11.5",
|
||||
"ts-node": "^10.9.2",
|
||||
"typescript": "^5.3.3",
|
||||
"vitest": "^3.1.3"
|
||||
"vitest": "^1.6.1"
|
||||
},
|
||||
"bin": {
|
||||
"cli": "lib/src/executable/cli.js"
|
||||
|
||||
+5
-10
@@ -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,8 +30,6 @@ export type DepgraphDependency = {
|
||||
resolution: string,
|
||||
}
|
||||
|
||||
export const depgraphfilename = 'maven-dependency-submission-action-depgraph.json';
|
||||
|
||||
export class MavenDependencyGraph {
|
||||
|
||||
private depGraph: Depgraph;
|
||||
@@ -173,25 +171,22 @@ export class MavenDependencyGraph {
|
||||
}
|
||||
}
|
||||
|
||||
export function parseDependencyJson(file: string): Depgraph {
|
||||
export function parseDependencyJson(file: string, isMultiModule: boolean = false): 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);
|
||||
return {
|
||||
...depGraph,
|
||||
filePath: pomXmlFilepath,
|
||||
};
|
||||
depGraph.isMultiModule = isMultiModule;
|
||||
return depGraph;
|
||||
} catch (err: any) {
|
||||
throw new Error(`Failed to parse JSON dependency data: ${err.message}`);
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ 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');
|
||||
@@ -91,6 +92,8 @@ async function execute() {
|
||||
sha: opts.sha,
|
||||
ref: opts.branchRef,
|
||||
|
||||
manifestFile: opts.snapshotDependencyFileName,
|
||||
includeManifestFile: !opts.snapshotExcludeFileName,
|
||||
detector: detector
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,8 @@ 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,7 +1,6 @@
|
||||
import { getMavenProjectDirectory } from './utils/test-util';
|
||||
import { generateDependencyGraphs, generateSnapshot } from './snapshot-generator';
|
||||
import { generateDependencyGraph, generateSnapshot } from './snapshot-generator';
|
||||
import {describe, it, expect} from 'vitest';
|
||||
import { Manifest } from '@github/dependency-submission-toolkit';
|
||||
|
||||
describe('snapshot-generator', () => {
|
||||
|
||||
@@ -9,11 +8,7 @@ describe('snapshot-generator', () => {
|
||||
|
||||
it('should generate a snapshot for a simple project', async () => {
|
||||
const projectDir = getMavenProjectDirectory('simple');
|
||||
const depGraphs = await generateDependencyGraphs(projectDir);
|
||||
expect(depGraphs).toBeDefined();
|
||||
expect(depGraphs.length).toBe(1);
|
||||
const depGraph = depGraphs[0];
|
||||
|
||||
const depGraph = await generateDependencyGraph(projectDir);
|
||||
expect(depGraph.dependencies.length).toBe(20);
|
||||
}, 20000);
|
||||
});
|
||||
@@ -42,50 +37,9 @@ 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);
|
||||
|
||||
const bsParentManifest = snapshot.manifests['bs-parent'];
|
||||
expect(bsParentManifest).toBeDefined();
|
||||
expect(getDirectDependencyPurls(bsParentManifest)).toEqual([
|
||||
'pkg:maven/junit/[email protected]?type=jar']);
|
||||
|
||||
const bsApplicationManifest = snapshot.manifests['bs-application'];
|
||||
expect(bsApplicationManifest).toBeDefined();
|
||||
expect(getDirectDependencyPurls(bsApplicationManifest)).toEqual([
|
||||
'pkg:maven/com.github.octodemo/[email protected]?type=jar',
|
||||
'pkg:maven/junit/[email protected]?type=jar',
|
||||
'pkg:maven/org.eclipse.jetty/[email protected]?type=jar',
|
||||
]);
|
||||
|
||||
const bsLibrariesManifest = snapshot.manifests['bs-libraries'];
|
||||
expect(bsLibrariesManifest).toBeDefined();
|
||||
expect(getDirectDependencyPurls(bsLibrariesManifest)).toEqual([
|
||||
'pkg:maven/junit/[email protected]?type=jar',
|
||||
'pkg:maven/org.apache.logging.log4j/[email protected]?type=jar',
|
||||
]);
|
||||
|
||||
const bsOtherManifest = snapshot.manifests['bs-other'];
|
||||
expect(bsOtherManifest).toBeDefined();
|
||||
expect(getDirectDependencyPurls(bsOtherManifest)).toEqual([
|
||||
'pkg:maven/junit/[email protected]?type=jar',
|
||||
]);
|
||||
|
||||
const bsLibraryDatabaseManifest = snapshot.manifests['bs-library-database'];
|
||||
expect(bsLibraryDatabaseManifest).toBeDefined();
|
||||
expect(getDirectDependencyPurls(bsLibraryDatabaseManifest)).toEqual([
|
||||
'pkg:maven/junit/[email protected]?type=jar',
|
||||
'pkg:maven/org.apache.logging.log4j/[email protected]?type=jar',
|
||||
'pkg:maven/org.postgresql/[email protected]?type=jar',
|
||||
'pkg:maven/org.xerial/[email protected]?type=jar',
|
||||
]);
|
||||
|
||||
const bsLibraryWebManifest = snapshot.manifests['bs-library-web'];
|
||||
expect(bsLibraryWebManifest).toBeDefined();
|
||||
expect(getDirectDependencyPurls(bsLibraryWebManifest)).toEqual([
|
||||
'pkg:maven/junit/[email protected]?type=jar',
|
||||
'pkg:maven/org.apache.logging.log4j/[email protected]?type=jar',
|
||||
'pkg:maven/org.eclipse.jetty.http2/[email protected]?type=jar',
|
||||
]);
|
||||
expect(snapshot.manifests['bs-parent'].countDependencies()).toBe(20);
|
||||
}, 20000);
|
||||
|
||||
it('should generate a snapshot for a maven-wrapper project', async () => {
|
||||
@@ -140,8 +94,4 @@ describe('snapshot-generator', () => {
|
||||
expect(snapshot.job.correlator).toBe('jobCorrelator');
|
||||
}, 20000);
|
||||
});
|
||||
});
|
||||
|
||||
function getDirectDependencyPurls(manifest: Manifest): string[] {
|
||||
return Object.values(manifest.resolved).filter(dep => dep.relationship === 'direct').map(dep => dep.depPackage.packageURL.toString()).sort();
|
||||
}
|
||||
});
|
||||
+88
-69
@@ -2,10 +2,9 @@ import * as core from '@actions/core';
|
||||
import * as path from 'path';
|
||||
|
||||
import { Manifest, Snapshot } from '@github/dependency-submission-toolkit';
|
||||
import { Depgraph, MavenDependencyGraph, parseDependencyJson, depgraphfilename } from './depgraph';
|
||||
import { Depgraph, MavenDependencyGraph, parseDependencyJson } 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';
|
||||
@@ -17,6 +16,8 @@ export type MavenConfiguration = {
|
||||
}
|
||||
|
||||
export type SnapshotConfig = {
|
||||
includeManifestFile?: boolean;
|
||||
manifestFile?: string;
|
||||
context?: any;
|
||||
job?: any;
|
||||
sha?: any;
|
||||
@@ -30,37 +31,48 @@ export type SnapshotConfig = {
|
||||
};
|
||||
|
||||
export async function generateSnapshot(directory: string, mvnConfig?: MavenConfiguration, snapshotConfig?: SnapshotConfig) {
|
||||
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;
|
||||
}
|
||||
const depgraph = await generateDependencyGraph(directory, mvnConfig);
|
||||
|
||||
try {
|
||||
for (const depgraph of depgraphs) {
|
||||
const mavenDependencies = new MavenDependencyGraph(depgraph);
|
||||
const pomFile = getRepositoryRelativePath(depgraph.filePath);
|
||||
const manifest = mavenDependencies.createManifest(pomFile);
|
||||
const mavenDependencies = new MavenDependencyGraph(depgraph);
|
||||
|
||||
snapshot.addManifest(manifest);
|
||||
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 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) {
|
||||
core.error(err);
|
||||
throw new Error(`Could not generate a snapshot of the dependencies; ${err.message}`);
|
||||
}
|
||||
return snapshot;
|
||||
}
|
||||
|
||||
function getDetector() {
|
||||
@@ -71,42 +83,75 @@ function getDetector() {
|
||||
};
|
||||
}
|
||||
|
||||
export async function generateDependencyGraphs(directory: string, config?: MavenConfiguration): Promise<Depgraph[]> {
|
||||
export async function generateDependencyGraph(directory: string, config?: MavenConfiguration): Promise<Depgraph> {
|
||||
try {
|
||||
const mvn = new MavenRunner(directory, config?.settingsFile, config?.ignoreMavenWrapper, config?.mavenArgs);
|
||||
|
||||
core.startGroup('depgraph-maven-plugin:aggregate');
|
||||
const mavenGraphArguments = [
|
||||
`com.github.ferstl:depgraph-maven-plugin:${DEPGRAPH_MAVEN_PLUGIN_VERSION}:graph`,
|
||||
core.startGroup('depgraph-maven-plugin:reactor');
|
||||
const mavenReactorArguments = [
|
||||
`com.github.ferstl:depgraph-maven-plugin:${DEPGRAPH_MAVEN_PLUGIN_VERSION}:reactor`,
|
||||
'-DgraphFormat=json',
|
||||
`-DoutputFileName=${depgraphfilename}`,
|
||||
'-DoutputFileName=reactor.json'
|
||||
];
|
||||
const graphResults = await mvn.exec(directory, mavenGraphArguments);
|
||||
const reactorResults = await mvn.exec(directory, mavenReactorArguments);
|
||||
|
||||
core.info(graphResults.stdout);
|
||||
core.info(graphResults.stderr);
|
||||
core.info(reactorResults.stdout);
|
||||
core.info(reactorResults.stderr);
|
||||
core.endGroup();
|
||||
|
||||
if (graphResults.exitCode !== 0) {
|
||||
throw new Error(`Failed to successfully generate dependency results with Maven, exit code: ${graphResults.exitCode}`);
|
||||
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`,
|
||||
'-DgraphFormat=json',
|
||||
'-DoutputDirectory=target',
|
||||
'-DoutputFileName=aggregate-depgraph.json'
|
||||
];
|
||||
const aggregateResults = await mvn.exec(directory, mavenAggregateArguments);
|
||||
|
||||
core.info(aggregateResults.stdout);
|
||||
core.info(aggregateResults.stderr);
|
||||
core.endGroup();
|
||||
|
||||
if (aggregateResults.exitCode !== 0) {
|
||||
throw new Error(`Failed to successfully dependency results with Maven, exit code: ${aggregateResults.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 graphFiles = getDepgraphFiles(directory, depgraphfilename);
|
||||
let results: Depgraph[] = [];
|
||||
for (const graphFile of graphFiles) {
|
||||
core.debug(`Found depgraph file: ${graphFile}`);
|
||||
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');
|
||||
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 {
|
||||
const depgraph = parseDependencyJson(graphFile);
|
||||
results.push(depgraph);
|
||||
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) {
|
||||
core.error(`Could not parse depgraph file, '${graphFile}': ${err.message}`);
|
||||
throw new Error(`Failed to parse reactor JSON payload: ${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...
|
||||
@@ -137,29 +182,3 @@ function getNonEmptyValue(str?: string) {
|
||||
}
|
||||
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