Compare commits

...

74 Commits

Author SHA1 Message Date
dependabot[bot] 918fd669ea Bump picomatch
Publish Executables / publish (push) Has been cancelled
Bumps  and [picomatch](https://github.com/micromatch/picomatch). These dependencies needed to be updated together.

Updates `picomatch` from 2.3.1 to 2.3.2
- [Release notes](https://github.com/micromatch/picomatch/releases)
- [Changelog](https://github.com/micromatch/picomatch/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/picomatch/compare/2.3.1...2.3.2)

Updates `picomatch` from 4.0.2 to 4.0.4
- [Release notes](https://github.com/micromatch/picomatch/releases)
- [Changelog](https://github.com/micromatch/picomatch/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/picomatch/compare/2.3.1...2.3.2)

---
updated-dependencies:
- dependency-name: picomatch
  dependency-version: 2.3.2
  dependency-type: indirect
- dependency-name: picomatch
  dependency-version: 4.0.4
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-26 00:14:22 +00:00
Lewis Jones 600bc1c22b Merge pull request #15 from actions/weekly-sync-branch-15812379965
Publish Executables / publish (push) Has been cancelled
Sync Fork with Upstream
2025-06-23 09:58:40 +01:00
github-actions[bot] e5f056b20d Empty commit to open PR 2025-06-23 00:22:55 +00:00
github-actions[bot] 61257b1734 Merge upstream:main 2025-06-23 00:22:55 +00:00
Ashely Tenesaca df268dd168 Merge pull request #116 from advanced-security/dependabot/npm_and_yarn/npm_and_yarn-762d904987
Bump tar-fs from 2.1.2 to 2.1.3 in the npm_and_yarn group across 1 directory
2025-06-12 10:30:22 -04:00
dependabot[bot] 58eef77972 Bump tar-fs in the npm_and_yarn group across 1 directory
Bumps the npm_and_yarn group with 1 update in the / directory: [tar-fs](https://github.com/mafintosh/tar-fs).


Updates `tar-fs` from 2.1.2 to 2.1.3
- [Commits](https://github.com/mafintosh/tar-fs/commits)

---
updated-dependencies:
- dependency-name: tar-fs
  dependency-version: 2.1.3
  dependency-type: indirect
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-03 09:26:27 +00:00
Kevin Dangoor c781803819 Merge pull request #12 from actions/main-sync
Synchronize from upstream (advanced-security)
2025-05-22 17:10:34 -04:00
Kevin Dangoor 3b967f57c3 Fix CODEOWNERS
Publish Executables / publish (push) Has been cancelled
2025-05-22 16:45:01 -04:00
Kevin Dangoor 2be53d9e6d Update from upstream 'main' into main-sync 2025-05-22 16:23:52 -04:00
Kevin Dangoor b275d12641 Merge pull request #114 from advanced-security/contrib-5.0
Bump the tag mentioned in the contrib doc to v5
2025-05-21 14:53:43 -04:00
Kevin Dangoor bdc082b320 Bump the tag mentioned in the contrib doc to v5 2025-05-21 14:04:55 -04:00
Kevin Dangoor 2c65a53e24 Merge pull request #110 from advanced-security/juxtin/file-centric-manifests
Stop aggregating manifests in multi-module projects
2025-05-21 13:56:28 -04:00
Kevin Dangoor aa342c187f Merge branch 'main' into juxtin/file-centric-manifests 2025-05-21 12:37:29 -04:00
Kevin Dangoor f86e5bfc17 README updates for v5.0.0 2025-05-21 12:35:36 -04:00
Kevin Dangoor fe8d4d650a Merge pull request #113 from advanced-security/dangoor/413
Bump version number to 4.1.3
2025-05-19 17:51:44 -04:00
Kevin Dangoor 05a8a347d6 Bump version number to 4.1.3 2025-05-19 17:09:37 -04:00
Kevin Dangoor 5d790318e6 Merge pull request #112 from advanced-security/workflow-permissions
Set workflow permissions
2025-05-19 13:05:25 -04:00
Kevin Dangoor 66812695c4 Set workflow permissions 2025-05-16 17:30:56 -04:00
Kevin Dangoor 4b6fc92adc Merge pull request #111 from advanced-security/dependabot/npm_and_yarn/npm_and_yarn-06dd3a6abc
Bump the npm_and_yarn group across 1 directory with 4 updates
2025-05-16 17:23:24 -04:00
dependabot[bot] a82c97775c Bump the npm_and_yarn group across 1 directory with 4 updates
Bumps the npm_and_yarn group with 2 updates in the / directory: [vitest](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest) and [undici](https://github.com/nodejs/undici).


Updates `vitest` from 1.6.1 to 3.1.3
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Commits](https://github.com/vitest-dev/vitest/commits/v3.1.3/packages/vitest)

Updates `esbuild` from 0.21.5 to 0.25.4
- [Release notes](https://github.com/evanw/esbuild/releases)
- [Changelog](https://github.com/evanw/esbuild/blob/main/CHANGELOG-2024.md)
- [Commits](https://github.com/evanw/esbuild/compare/v0.21.5...v0.25.4)

Updates `undici` from 5.28.4 to 5.29.0
- [Release notes](https://github.com/nodejs/undici/releases)
- [Commits](https://github.com/nodejs/undici/compare/v5.28.4...v5.29.0)

Updates `vite` from 5.4.16 to 6.3.5
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v6.3.5/packages/vite)

---
updated-dependencies:
- dependency-name: vitest
  dependency-version: 3.1.3
  dependency-type: direct:development
  dependency-group: npm_and_yarn
- dependency-name: esbuild
  dependency-version: 0.25.4
  dependency-type: indirect
  dependency-group: npm_and_yarn
- dependency-name: undici
  dependency-version: 5.29.0
  dependency-type: indirect
  dependency-group: npm_and_yarn
- dependency-name: vite
  dependency-version: 6.3.5
  dependency-type: indirect
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-16 21:21:46 +00:00
Kevin Dangoor fd44dd789a Merge pull request #101 from advanced-security/dependabot/npm_and_yarn/octokit/request-8.4.1
Bump @octokit/request from 8.4.0 to 8.4.1
2025-05-16 17:20:05 -04:00
Kevin Dangoor b08977e686 Merge pull request #100 from advanced-security/dependabot/npm_and_yarn/octokit/request-error-5.1.1
Bump @octokit/request-error from 5.1.0 to 5.1.1
2025-05-16 17:19:33 -04:00
Kevin Dangoor 0fdf861094 Merge pull request #98 from advanced-security/dependabot/npm_and_yarn/octokit/endpoint-9.0.6
Bump @octokit/endpoint from 9.0.5 to 9.0.6
2025-05-16 17:19:11 -04:00
Kevin Dangoor dc41d4a792 Merge pull request #97 from advanced-security/dependabot/npm_and_yarn/tar-fs-2.1.2
Bump tar-fs from 2.1.1 to 2.1.2
2025-05-16 17:18:45 -04:00
Kevin Dangoor 1f5918021f Merge pull request #95 from advanced-security/dependabot/npm_and_yarn/octokit/plugin-paginate-rest-9.2.2
Bump @octokit/plugin-paginate-rest from 9.2.1 to 9.2.2
2025-05-16 17:18:20 -04:00
Justin Holguín 69b8872e09 Update wording in error message
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-05-15 09:09:03 -07:00
Justin Holguín e11bd00d83 Remove debug line
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-05-15 09:08:06 -07:00
Justin Holguín b737283803 Update version to 5.0.0 since this has breaking changes 2025-05-14 22:58:01 +00:00
Justin Holguín 3059e7f9fa Minor tweaks 2025-05-14 22:53:15 +00:00
Justin Holguín 06796b833d 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
2025-05-14 22:46:16 +00:00
Indigo 0ac7fe97bd Merge pull request #11 from actions/weekly-sync-branch
Merge branch 'main' into weekly-sync-branch
2025-05-14 06:51:58 -07:00
Indigo f79a6b5f42 Merge branch 'main' into weekly-sync-branch 2025-05-13 18:52:21 +00:00
Indigo 4fa0fa1ad1 Merge pull request #10 from actions/indigok-patch-1
Create CODEOWNERS
2025-05-12 12:30:45 -07:00
Indigo 7bd449e03d Create CODEOWNERS 2025-05-12 11:54:02 -07:00
Justin Holguín 4bf8a28b00 Merge pull request #108 from advanced-security/juxtin/release-docs
Update release docs to include release artifacts
2025-04-07 09:32:51 -07:00
Justin Holguín e457a508a1 Update release docs to include release artifacts 2025-04-07 16:25:07 +00:00
Justin Holguín aeab9f8852 Merge pull request #106 from advanced-security/juxtin/prep-412
Update version to 4.1.2 and update release instructions
2025-04-04 13:01:39 -07:00
Justin Holguín bc43a53a41 Update step numbers 2025-04-04 17:52:50 +00:00
Justin Holguín 8ec6a0b12e Add note about running npm build 2025-04-04 17:52:04 +00:00
Justin Holguín 8c8c37cf51 Merge branch 'main' into juxtin/prep-412 2025-04-04 10:49:59 -07:00
Justin Holguín 4ccf7bf0a3 Update version to 4.1.2 and update release instructions 2025-04-04 17:45:46 +00:00
Paul Hodgkinson 517058e819 Merge branch 'main' into dependabot/npm_and_yarn/octokit/endpoint-9.0.6 2025-04-04 18:33:33 +01:00
Paul Hodgkinson 88fbf083ed Merge branch 'main' into dependabot/npm_and_yarn/octokit/request-error-5.1.1 2025-04-04 18:33:19 +01:00
Paul Hodgkinson d5e8c459a7 Merge branch 'main' into dependabot/npm_and_yarn/octokit/request-8.4.1 2025-04-04 18:33:06 +01:00
Paul Hodgkinson fd85cdd6fc Merge branch 'main' into dependabot/npm_and_yarn/octokit/plugin-paginate-rest-9.2.2 2025-04-04 18:32:56 +01:00
Paul Hodgkinson 5736c58c85 Merge branch 'main' into dependabot/npm_and_yarn/tar-fs-2.1.2 2025-04-04 18:32:20 +01:00
Justin Holguín 973a8cf442 Merge pull request #104 from advanced-security/juxtin/prep-412
Prep for next release
2025-04-04 08:32:05 -07:00
Justin Holguín 48f232b0d1 Update dist files 2025-04-03 22:03:26 +00:00
Justin Holguín 769e1e8558 Prepare for 4.1.2 release 2025-04-03 18:34:20 +00:00
Justin Holguín 298a804769 Upgrade version of Maven plugin
See https://github.com/ferstl/depgraph-maven-plugin
2025-04-03 18:33:47 +00:00
Justin Holguín 29fd39885e Merge pull request #103 from advanced-security/juxtin/handle-cycles
Add cycle safety for transitive dependencies
2025-04-03 11:29:17 -07:00
Justin Holguín 595d586c88 Simplify test data and refactor 2025-04-03 16:59:49 +00:00
Justin Holguín 9e875aadac Add cycle safety for transitive dependencies 2025-04-02 22:45:08 +00:00
Kevin Dangoor 17ef6767ae Merge pull request #102 from advanced-security/GeekMasher-patch-1
Create CODEOWNERS
2025-04-02 14:01:23 -04:00
Mathew Payne 266293e200 feat: Create CODEOWNERS 2025-04-01 16:00:01 +01:00
dependabot[bot] 97bb06c6ff Bump @octokit/request from 8.4.0 to 8.4.1
Bumps [@octokit/request](https://github.com/octokit/request.js) from 8.4.0 to 8.4.1.
- [Release notes](https://github.com/octokit/request.js/releases)
- [Commits](https://github.com/octokit/request.js/compare/v8.4.0...v8.4.1)

---
updated-dependencies:
- dependency-name: "@octokit/request"
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-01 14:48:29 +00:00
dependabot[bot] 5bf0dc7e83 Bump @octokit/request-error from 5.1.0 to 5.1.1
Bumps [@octokit/request-error](https://github.com/octokit/request-error.js) from 5.1.0 to 5.1.1.
- [Release notes](https://github.com/octokit/request-error.js/releases)
- [Commits](https://github.com/octokit/request-error.js/compare/v5.1.0...v5.1.1)

---
updated-dependencies:
- dependency-name: "@octokit/request-error"
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-01 14:48:10 +00:00
dependabot[bot] e42d5157d9 Bump @octokit/endpoint from 9.0.5 to 9.0.6
Bumps [@octokit/endpoint](https://github.com/octokit/endpoint.js) from 9.0.5 to 9.0.6.
- [Release notes](https://github.com/octokit/endpoint.js/releases)
- [Commits](https://github.com/octokit/endpoint.js/compare/v9.0.5...v9.0.6)

---
updated-dependencies:
- dependency-name: "@octokit/endpoint"
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-01 14:48:01 +00:00
dependabot[bot] 5dc9268511 Bump tar-fs from 2.1.1 to 2.1.2
Bumps [tar-fs](https://github.com/mafintosh/tar-fs) from 2.1.1 to 2.1.2.
- [Commits](https://github.com/mafintosh/tar-fs/compare/v2.1.1...v2.1.2)

---
updated-dependencies:
- dependency-name: tar-fs
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-01 14:47:54 +00:00
dependabot[bot] 66fe395b94 Bump @octokit/plugin-paginate-rest from 9.2.1 to 9.2.2
Bumps [@octokit/plugin-paginate-rest](https://github.com/octokit/plugin-paginate-rest.js) from 9.2.1 to 9.2.2.
- [Release notes](https://github.com/octokit/plugin-paginate-rest.js/releases)
- [Commits](https://github.com/octokit/plugin-paginate-rest.js/compare/v9.2.1...v9.2.2)

---
updated-dependencies:
- dependency-name: "@octokit/plugin-paginate-rest"
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-01 14:47:44 +00:00
Mathew Payne 499642b4a1 Merge pull request #94 from advanced-security/dependabot/npm_and_yarn/vitest-1.6.1
Bump vitest from 1.5.2 to 1.6.1
2025-04-01 15:46:33 +01:00
dependabot[bot] e8e224050e Bump vitest from 1.5.2 to 1.6.1
Bumps [vitest](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest) from 1.5.2 to 1.6.1.
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Commits](https://github.com/vitest-dev/vitest/commits/v1.6.1/packages/vitest)

---
updated-dependencies:
- dependency-name: vitest
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-01 14:42:10 +00:00
Jon Janego 49866fead7 Merge pull request #90 from advanced-security/jonjanego-patch-2
Update README.md
2024-09-24 16:58:59 -05:00
Jon Janego f5f71df9a0 Update README.md
Dependency submission is no longer in beta
2024-09-23 17:21:52 -05:00
github-actions 4f64ddab9d chore: Updating release files 2024-08-07 14:33:45 +00:00
github-actions dba3dacedd 4.1.1 2024-08-07 14:33:28 +00:00
Henri Maurer 4883574ccf Merge pull request #89 from david-wiggs/hotfix/fix-test
Remove reference to undefined function
2024-08-07 15:31:23 +01:00
David Wiggs 33e1d3d801 Remove reference to undefined function 2024-08-07 14:29:22 +00:00
Henri Maurer 4b85c77703 Merge pull request #88 from david-wiggs/unique-job-matrix
Distinguish between multiple dependency snapshots of the same type
2024-08-07 15:10:49 +01:00
David Wiggs 73d9d97f9f Update src/snapshot-generator.test.ts
Co-authored-by: Mitchell Rysavy <mitchell.rysavy@gmail.com>
2024-07-29 10:08:09 -05:00
David Wiggs 967455e178 No need to import getMavenSettingsFile when testing 2024-07-24 12:59:25 +00:00
David Wiggs 7592e88109 Use supplied correlator without concatenation 2024-07-23 22:33:11 +00:00
David Wiggs 2ba839e04b Add some tests 2024-07-22 23:27:03 +00:00
David Wiggs 5275a08fb4 Address merge conflicts 2024-07-21 20:31:04 +00:00
18 changed files with 1262 additions and 1054 deletions
+3
View File
@@ -0,0 +1,3 @@
# Managed and Maintained by:
* @actions/advanced-security-dependency-graph
@@ -1,5 +1,8 @@
name: Publish Executables
permissions:
contents: read
on:
workflow_dispatch:
push:
-126
View File
@@ -1,126 +0,0 @@
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 github-actions@github.com
- 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/release-action@v1.13.0
with:
artifacts: cli/*
prerelease: ${{ steps.semver.outputs.isPreRelease }}
tag: v${{ steps.semver.outputs.semver }}
+3
View File
@@ -1,5 +1,8 @@
name: Test Local Action
permissions:
contents: read
on:
workflow_dispatch:
inputs:
+41
View File
@@ -24,6 +24,47 @@ Here are a few things you can do that will increase the likelihood of your pull
- Keep your change as focused as possible. If there are multiple changes you would like to make that are not dependent upon each other, consider submitting them as separate pull requests.
- Write a [good commit message](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html).
## Cutting a new release
<details>
_Note: these instructions are for maintainers_
1. Update the version number in [package.json](https://github.com/advanced-security/maven-dependency-submission-action/blob/main/package.json) and run `npm i` to update the lockfile. This is also a good time to make sure that the `dist/index.js` file is up to date by running `npm run build`.
2. Go to [Draft a new
release](https://github.com/advanced-security/maven-dependency-submission-action/releases/new)
in the Releases page.
3. Make sure that the `Publish this Action to the GitHub Marketplace`
checkbox is enabled
<img width="481" alt="Screenshot 2022-06-15 at 12 08 19" src="https://user-images.githubusercontent.com/2161/173822484-4b60d8b4-c674-4bff-b5ff-b0c4a3650ab7.png">
4. Click "Choose a tag" and then "Create new tag", where the tag name
will be your version prefixed by a `v` (e.g. `v4.1.2`).
5. Use a version number for the release title (e.g. "4.1.2").
<img width="700" alt="Screenshot 2022-06-15 at 12 08 36" src="https://user-images.githubusercontent.com/2161/173822548-33ab3432-d679-4dc1-adf8-b50fdaf47de3.png">
6. Add your release notes. If this is a major version make sure to
include a small description of the biggest changes in the new version.
7. Build the release executables by manually triggering [this action](https://github.com/advanced-security/maven-dependency-submission-action/actions/workflows/publish_executables.yml). The output of this action will be a zip file that you should download, extract, and drag into the binaries section. There should be three files there: ending in `-linux`, `-macos`, and `-win.exe`.
8. Click "Publish Release".
You now have a tag and release using the semver version you used
above. The last remaining thing to do is to move the dynamic version
identifier to match the current SHA. This allows users to adopt a
major version number (e.g. `v1`) in their workflows while
automatically getting all the
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
```
</details>
## Resources
- [How to Contribute to Open Source](https://opensource.guide/how-to-contribute/)
+35 -10
View File
@@ -2,14 +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.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.
> **Warning** The dependency submission APIs and toolkit are still currently in beta and as such subject to changes in future releases.
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
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
@@ -17,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 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
@@ -31,10 +29,7 @@ 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.
* `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
@@ -42,13 +37,43 @@ Generating and submitting a dependency snapshot using the defaults:
```
- 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;
![Screenshot 2022-08-15 at 09 33 47](https://user-images.githubusercontent.com/681306/184603264-3cd69fda-75ff-4a46-b014-630acab60fab.png)
### Configuring for Matrix-Based Workflows
To ensure that the job parameter of the submission remains unique when the action is being called from a workflow that has a matrix, you can pass a `correlator` to the action. This identifier will be appended to the default correlator propterty of a job, ensuring uniqueness across matrix-based workflows. When dealing with Maven-based Java projects that utilize different `pom.xml` files across matrix jobs, you can specify the `directory` relevant to each matrix job. This ensures that the dependency snapshot accurately reflects the dependencies for each specific configuration.
Example of specifying `pom.xml` files for different matrix jobs:
```yaml
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
include:
- java-version: 8
directory: project1
- java-version: 11
directory: project2
steps:
- uses: actions/checkout@v2
- name: Set up JDK ${{ matrix.java-version }}
uses: actions/setup-java@v2
with:
java-version: ${{ matrix.java-version }}
- name: Submit Dependency Snapshot
uses: advanced-security/maven-dependency-submission-action@v3
with:
directory: ${{ matrix.directory }}
correlator: ${{ github.job }}-${{ matrix.directory }}
```
In this example, the action is configured to use different working directories based on the Java version specified in the matrix. This ensures that the dependency snapshot is accurate for each Java version being tested.
## Command Line Usage
+6 -10
View File
@@ -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
@@ -64,6 +54,12 @@ inputs:
description: The URL to the detector that generated the dependency snapshot
type: string
correlator:
description: An optional identifier to distinguish between multiple dependency snapshots of the same type
type: string
required: false
default: ''
runs:
using: node20
main: dist/index.js
+92 -93
View File
@@ -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;
@@ -47,13 +48,19 @@ class MavenDependencyGraph {
const artifact = this.packageUrlToArtifact[depPackage.packageURL.toString()];
let scope = getDependencyScopeForMavenScope(artifact.scopes);
manifest.addDirectDependency(depPackage, scope);
function addTransitiveDeps(dependencies) {
function addTransitiveDeps(dependencies, seen = new Set()) {
if (dependencies) {
dependencies.forEach(transitiveDep => {
const transitiveDepArtifact = packageUrlToArtifact[transitiveDep.packageURL.toString()];
let purl = transitiveDep.packageURL.toString();
if (seen.has(purl)) {
// we're in a cycle! skip this one.
return;
}
const transitiveDepArtifact = packageUrlToArtifact[purl];
const transitiveDepScope = getDependencyScopeForMavenScope(transitiveDepArtifact.scopes);
manifest.addIndirectDependency(transitiveDep, transitiveDepScope);
addTransitiveDeps(transitiveDep.dependencies);
seen.add(purl);
addTransitiveDeps(transitiveDep.dependencies, seen);
});
}
}
@@ -113,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}`);
@@ -246,11 +253,13 @@ 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'),
};
const correlator = core.getInput('correlator');
if (correlator) {
snapshotConfig.correlator = correlator;
}
const detectorName = core.getInput('detector-name');
if (detectorName !== '') {
snapshotConfig.detector = {
@@ -472,53 +481,45 @@ 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.2';
const DEPGRAPH_MAVEN_PLUGIN_VERSION = '4.0.3';
function generateSnapshot(directory, mvnConfig, snapshotConfig) {
return __awaiter(this, void 0, void 0, function* () {
var _a;
const depgraph = yield generateDependencyGraph(directory, mvnConfig);
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;
}
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);
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);
}
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);
const specifiedRef = getNonEmtptyValue(snapshotConfig === null || snapshotConfig === void 0 ? void 0 : snapshotConfig.ref);
if (specifiedRef) {
snapshot.ref = specifiedRef;
}
const specifiedSha = getNonEmtptyValue(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;
@@ -529,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');
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}`);
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}`);
}
}
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 || '.');
@@ -609,7 +583,7 @@ function getRepositoryRelativePath(file) {
core.debug(`Snapshot relative file = ${result}`);
return result;
}
function getNonEmtptyValue(str) {
function getNonEmptyValue(str) {
if (str) {
const trimmed = str.trim();
if (trimmed.length > 0) {
@@ -618,6 +592,31 @@ function getNonEmtptyValue(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
/***/ }),
@@ -33288,7 +33287,7 @@ exports.submitSnapshot = L;
/***/ ((module) => {
"use strict";
module.exports = JSON.parse('{"name":"maven-dependency-submission-action","version":"4.1.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.2.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"}}');
/***/ })
+1 -1
View File
File diff suppressed because one or more lines are too long
+826 -709
View File
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "maven-dependency-submission-action",
"version": "4.1.0",
"version": "5.0.0",
"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": "^1.2.1"
"vitest": "^3.1.3"
},
"bin": {
"cli": "lib/src/executable/cli.js"
+19
View File
@@ -116,6 +116,25 @@ describe('depgraph', () => {
});
});
describe('cycle-tree', () => {
let depGraph;
beforeAll(() => {
depGraph = parseDependencyJson(getTestDataFile("cycle-tree"));
});
it('should parse out the top level dependencies', () => {
const mavenDependencies = new MavenDependencyGraph(depGraph);
expect(mavenDependencies.getPackageCount()).to.equal(3);
});
it('should be able to generate a manifest despite having a cycle', () => {
const mavenDependencies = new MavenDependencyGraph(depGraph);
const manifest = mavenDependencies.createManifest();
expect(manifest.name).to.equal('hadoop-main');
expect(manifest.countDependencies()).to.equal(2);
})
});
describe('bs-parent-dep-tree', () => {
+19 -8
View File
@@ -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;
@@ -85,13 +87,19 @@ export class MavenDependencyGraph {
let scope = getDependencyScopeForMavenScope(artifact.scopes);
manifest.addDirectDependency(depPackage, scope);
function addTransitiveDeps(dependencies) {
function addTransitiveDeps(dependencies, seen: Set<string> = new Set()) {
if (dependencies) {
dependencies.forEach(transitiveDep => {
const transitiveDepArtifact = packageUrlToArtifact[transitiveDep.packageURL.toString()];
let purl = transitiveDep.packageURL.toString();
if (seen.has(purl)) {
// we're in a cycle! skip this one.
return;
}
const transitiveDepArtifact = packageUrlToArtifact[purl];
const transitiveDepScope = getDependencyScopeForMavenScope(transitiveDepArtifact.scopes);
manifest.addIndirectDependency(transitiveDep, transitiveDepScope);
addTransitiveDeps(transitiveDep.dependencies);
seen.add(purl);
addTransitiveDeps(transitiveDep.dependencies, seen);
});
}
}
@@ -165,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}`);
}
-3
View File
@@ -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
}
+4 -2
View File
@@ -13,11 +13,13 @@ 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'),
}
const correlator = core.getInput('correlator');
if (correlator) {
snapshotConfig.correlator = correlator;
}
const detectorName = core.getInput('detector-name');
if (detectorName !== '') {
snapshotConfig.detector = {
+80 -5
View File
@@ -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 () => {
@@ -68,5 +114,34 @@ describe('snapshot-generator', () => {
expect(snapshot.detector.version).toBe(version);
expect(snapshot.manifests['problem-dependency-graph-2602'].countDependencies()).toBe(230);
}, 40000);
it('should use correlator from snapshotConfig if it exists', async() => {
const projectDir = getMavenProjectDirectory('simple');
const snapshotConfig = {
correlator: 'configCorrelator',
job: {
correlator: 'jobCorrelator'
}
};
const snapshot = await generateSnapshot(projectDir, undefined, snapshotConfig);
expect(snapshot.job.correlator).toBe('configCorrelator');
}, 20000);
it('should use a default job correlator when not specified', async() => {
const projectDir = getMavenProjectDirectory('simple');
const snapshotConfig = {
job: {
correlator: 'jobCorrelator'
}
};
const snapshot = await generateSnapshot(projectDir, undefined, snapshotConfig);
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();
}
+71 -85
View File
@@ -2,12 +2,13 @@ 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.2';
const DEPGRAPH_MAVEN_PLUGIN_VERSION = '4.0.3';
export type MavenConfiguration = {
ignoreMavenWrapper?: boolean;
@@ -16,8 +17,6 @@ export type MavenConfiguration = {
}
export type SnapshotConfig = {
includeManifestFile?: boolean;
manifestFile?: string;
context?: any;
job?: any;
sha?: any;
@@ -27,47 +26,41 @@ export type SnapshotConfig = {
url: string;
version: string;
};
correlator?: string;
};
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 {
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;
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();
snapshot.addManifest(manifest);
}
const detector = snapshotConfig?.detector ?? getDetector();
const snapshot = new Snapshot(detector, snapshotConfig?.context, snapshotConfig?.job);
snapshot.addManifest(manifest);
const specifiedRef = getNonEmtptyValue(snapshotConfig?.ref);
if (specifiedRef) {
snapshot.ref = specifiedRef;
}
const specifiedSha = getNonEmtptyValue(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() {
@@ -78,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 generate 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');
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) {
const graphFiles = getDepgraphFiles(directory, depgraphfilename);
let results: Depgraph[] = [];
for (const graphFile of graphFiles) {
core.debug(`Found depgraph file: ${graphFile}`);
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;
const depgraph = parseDependencyJson(graphFile);
results.push(depgraph);
} catch (err: any) {
throw new Error(`Failed to parse reactor JSON payload: ${err.message}`);
core.error(`Could not parse depgraph file, '${graphFile}': ${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...
@@ -168,7 +128,7 @@ function getRepositoryRelativePath(file) {
return result;
}
function getNonEmtptyValue(str?: string) {
function getNonEmptyValue(str?: string) {
if (str) {
const trimmed = str.trim();
if (trimmed.length > 0) {
@@ -177,3 +137,29 @@ function getNonEmtptyValue(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;
}
@@ -0,0 +1,57 @@
{
"graphName" : "hadoop-main",
"artifacts" : [ {
"id" : "org.apache.hadoop:hadoop-annotations:jar:compile",
"numericId" : 1,
"groupId" : "org.apache.hadoop",
"artifactId" : "hadoop-annotations",
"version" : "3.5.0-SNAPSHOT",
"optional" : false,
"scopes" : [ "compile" ],
"types" : [ "jar" ]
}, {
"id" : "jdiff:jdiff:jar:provided",
"numericId" : 2,
"groupId" : "jdiff",
"artifactId" : "jdiff",
"version" : "1.0.9",
"optional" : false,
"scopes" : [ "provided" ],
"types" : [ "jar" ]
}, {
"id" : "org.apache.hadoop:hadoop-project-dist:pom:compile",
"numericId" : 3,
"groupId" : "org.apache.hadoop",
"artifactId" : "hadoop-project-dist",
"version" : "3.5.0-SNAPSHOT",
"optional" : false,
"scopes" : [ "compile" ],
"types" : [ "pom" ]
} ],
"dependencies" : [ {
"from" : "org.apache.hadoop:hadoop-annotations:jar:compile",
"to" : "jdiff:jdiff:jar:provided",
"numericFrom" : 1,
"numericTo" : 2,
"resolution" : "INCLUDED"
}, {
"from" : "org.apache.hadoop:hadoop-annotations:jar:compile",
"to" : "jdiff:jdiff:jar:provided",
"numericFrom" : 1,
"numericTo" : 3,
"resolution" : "INCLUDED"
}, {
"from" : "jdiff:jdiff:jar:provided",
"to" : "org.apache.hadoop:hadoop-project-dist:pom:compile",
"numericFrom" : 2,
"numericTo" : 3,
"resolution" : "INCLUDED"
}, {
"from" : "org.apache.hadoop:hadoop-project-dist:pom:compile",
"to" : "jdiff:jdiff:jar:provided",
"numericFrom" : 3,
"numericTo" : 2,
"resolution" : "INCLUDED"
}
]
}