Skip to content

Commit 33ee13a

Browse files
committed
Merge remote-tracking branch 'upstream/main' into rust
2 parents 4111fc3 + 29f6867 commit 33ee13a

53 files changed

Lines changed: 2575 additions & 441 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/publish.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ jobs:
7676
steps:
7777
- name: Get releasebranch.txt artifact from Release pipeline
7878
if: github.event_name == 'workflow_run'
79-
uses: actions/download-artifact@v7
79+
uses: actions/download-artifact@v8
8080
with:
8181
name: releasebranch.txt
8282
run-id: ${{ github.event.workflow_run.id }}

.github/workflows/push-to-registry.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,26 +65,26 @@ jobs:
6565
echo "created=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" >> $GITHUB_OUTPUT
6666
6767
- name: Set up Docker Buildx
68-
uses: docker/setup-buildx-action@v3
68+
uses: docker/setup-buildx-action@v4
6969

7070
- name: Log in to Container Registry
71-
uses: docker/login-action@v3
71+
uses: docker/login-action@v4
7272
with:
7373
registry: ${{ env.REGISTRY }}
7474
username: ${{ github.actor }}
7575
password: ${{ secrets.GITHUB_TOKEN }}
7676

7777
- name: Extract Docker metadata
7878
id: meta
79-
uses: docker/metadata-action@v5
79+
uses: docker/metadata-action@v6
8080
with:
8181
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
8282
tags: |
8383
type=raw,value=latest,enable=${{ steps.version.outputs.ea_build == 'true' }}
8484
type=raw,value=${{ steps.version.outputs.version }}
8585
8686
- name: Build and push Docker image
87-
uses: docker/build-push-action@v6
87+
uses: docker/build-push-action@v7
8888
with:
8989
context: .
9090
file: ./docker-image/Dockerfiles/Dockerfile

.github/workflows/release.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ jobs:
6464
git push origin "$BRANCH"
6565
echo "$BRANCH" > releasebranch.txt
6666
67-
- uses: actions/upload-artifact@v6
67+
- uses: actions/upload-artifact@v7
6868
with:
6969
name: releasebranch.txt
7070
path: releasebranch.txt

.github/workflows/test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ jobs:
9797

9898
- name: Upload coverage reports
9999
if: ${{ matrix.node == env.MAIN_NODE_VER }}
100-
uses: actions/upload-artifact@v6
100+
uses: actions/upload-artifact@v7
101101
with:
102102
name: coverage
103103
path: ./coverage/coverage-final.json

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,4 @@ unit-tests-result.json
99
build
1010
target
1111
.npmrc
12+
src/providers/tree-sitter-requirements.wasm

README.md

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,21 @@ let imageAnalysisWithArch = await client.imageAnalysis(['httpd:2.4.49^^amd64'])
4343
```
4444
</li>
4545
</ul>
46+
47+
<h3>License Detection</h3>
48+
<p>
49+
The client automatically detects your project's license with intelligent fallback:
50+
</p>
51+
<ul>
52+
<li><strong>Manifest-first:</strong> For ecosystems with license support (Maven, JavaScript, Rust Cargo), reads from manifest file (<code>pom.xml</code>, <code>package.json</code>, <code>Cargo.toml</code>)</li>
53+
<li><strong>LICENSE file fallback:</strong> If no license in manifest, or for ecosystems without license support (Gradle, Go, Python), automatically reads from <code>LICENSE</code>, <code>LICENSE.md</code>, or <code>LICENSE.txt</code></li>
54+
<li><strong>SBOM integration:</strong> Detected licenses are included in generated SBOMs for all ecosystems</li>
55+
<li><strong>SPDX support:</strong> Automatically detects common licenses (Apache-2.0, MIT, GPL, BSD) from LICENSE file content</li>
56+
</ul>
57+
<p>
58+
See <a href="./docs/license-resolution-and-compliance.md">License Resolution and Compliance</a> for detailed documentation.
59+
</p>
60+
4661
<ul>
4762
<li>
4863
Use as ESM Module from Common-JS module
@@ -83,12 +98,13 @@ Use as CLI Script
8398
```shell
8499
$ npx @trustify-da/trustify-da-javascript-client help
85100

86-
Usage: trustify-da-javascript-client {component|stack|image|validate-token}
101+
Usage: trustify-da-javascript-client {component|stack|image|validate-token|license}
87102

88103
Commands:
89104
trustify-da-javascript-client stack </path/to/manifest> [--html|--summary] produce stack report for manifest path
90105
trustify-da-javascript-client component <path/to/manifest> [--summary] produce component report for a manifest type and content
91106
trustify-da-javascript-client image <image-refs..> [--html|--summary] produce image analysis report for OCI image references
107+
trustify-da-javascript-client license </path/to/manifest> display project license information from manifest and LICENSE file in JSON format
92108

93109
Options:
94110
--help Show help [boolean]
@@ -123,6 +139,9 @@ $ npx @trustify-da/trustify-da-javascript-client image docker.io/library/node:18
123139

124140
# specify architecture using ^^ notation (e.g., httpd:2.4.49^^amd64)
125141
$ npx @trustify-da/trustify-da-javascript-client image httpd:2.4.49^^amd64
142+
143+
# get project license information
144+
$ npx @trustify-da/trustify-da-javascript-client license /path/to/package.json
126145
```
127146
</li>
128147

@@ -161,6 +180,9 @@ $ trustify-da-javascript-client image docker.io/library/node:18 docker.io/librar
161180

162181
# specify architecture using ^^ notation (e.g., httpd:2.4.49^^amd64)
163182
$ trustify-da-javascript-client image httpd:2.4.49^^amd64
183+
184+
# get project license information
185+
$ trustify-da-javascript-client license /path/to/package.json
164186
```
165187
</li>
166188
</ul>
@@ -177,6 +199,21 @@ $ trustify-da-javascript-client image httpd:2.4.49^^amd64
177199
<li><a href="https://www.rust-lang.org/">Rust</a> - <a href="https://doc.rust-lang.org/cargo/">Cargo</a></li>
178200
</ul>
179201

202+
<h3>License Detection</h3>
203+
<p>
204+
The client automatically detects your project's license with intelligent fallback:
205+
</p>
206+
<ul>
207+
<li><strong>Manifest-first:</strong> For ecosystems with license support (Maven, JavaScript, Rust Cargo), reads from manifest file (<code>pom.xml</code>, <code>package.json</code>, <code>Cargo.toml</code>)</li>
208+
<li><strong>LICENSE file fallback:</strong> If no license in manifest, or for ecosystems without license support (Gradle, Go, Python), automatically reads from <code>LICENSE</code>, <code>LICENSE.md</code>, or <code>LICENSE.txt</code></li>
209+
<li><strong>SBOM integration:</strong> Detected licenses are included in generated SBOMs for all ecosystems</li>
210+
<li><strong>SPDX support:</strong> Automatically detects common licenses (Apache-2.0, MIT, GPL, BSD) from LICENSE file content</li>
211+
</ul>
212+
<p>
213+
See <a href="./docs/license-resolution-and-compliance.md">License Resolution and Compliance</a> for detailed documentation.
214+
</p>
215+
216+
180217
<h3>Excluding Packages</h3>
181218
<p>
182219
Excluding a package from any analysis can be achieved by marking the package for exclusion.
@@ -388,6 +425,11 @@ const options = {
388425
The proxy URL should be in the format: `http://host:port` or `https://host:port`. The API will automatically use the appropriate protocol (HTTP or HTTPS) based on the proxy URL provided.
389426
</p>
390427

428+
<h4>License resolution and dependency license compliance</h4>
429+
<p>
430+
The client can resolve the <strong>project license</strong> from the manifest (e.g. <code>package.json</code> <code>license</code>, <code>pom.xml</code> <code>&lt;licenses&gt;</code>, <code>Cargo.toml</code> <code>license</code>) and from a <code>LICENSE</code> or <code>LICENSE.md</code> file in the project, and report when they differ. For <strong>component analysis</strong>, you can optionally run a license check: the client fetches dependency licenses from the backend (by purl) and reports dependencies whose licenses are incompatible with the project license. See <a href="docs/license-resolution-and-compliance.md">License resolution and compliance</a> for design and behavior. To disable the check on component analysis, set <code>TRUSTIFY_DA_LICENSE_CHECK=false</code> or pass <code>licenseCheck: false</code> in the options.
431+
</p>
432+
391433
<h4>Customizing Executables</h4>
392434
<p>
393435
This project uses each ecosystem's executable for creating dependency trees. These executables are expected to be
Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
# License Resolution and Compliance
2+
3+
This document describes the license analysis features that help you understand your project’s license and check compatibility with your dependencies.
4+
5+
## Overview
6+
7+
License analysis is **enabled by default** and provides:
8+
9+
1. **Project license detection** from your manifest file (e.g., `package.json`, `pom.xml`) and LICENSE files
10+
2. **Dependency license information** from the Trustify DA backend
11+
3. **Compatibility checking** to identify potential license conflicts
12+
4. **Mismatch detection** when your manifest and LICENSE file declare different licenses
13+
14+
## How It Works
15+
16+
### Project License Detection
17+
18+
The client looks for your project’s license with **automatic fallback**:
19+
20+
1. **Primary: Manifest file** — Reads the license field from:
21+
- `package.json`: `license` field
22+
- `pom.xml`: `<licenses><license><name>` element
23+
- `Cargo.toml`: `license` field under `[package]` or `[workspace.package]`
24+
- `build.gradle` / `build.gradle.kts`: No standard license field (falls back to LICENSE file)
25+
- `go.mod`: No standard license field (falls back to LICENSE file)
26+
- `requirements.txt`: No standard license field (falls back to LICENSE file)
27+
28+
2. **Fallback: LICENSE file** — If no license is found in the manifest, searches for `LICENSE`, `LICENSE.md`, or `LICENSE.txt` in the same directory as your manifest
29+
30+
**How the fallback works:**
31+
- **Ecosystems with manifest license support** (Maven, JavaScript, Rust Cargo): Uses manifest license if present, otherwise falls back to LICENSE file
32+
- **Ecosystems without manifest license support** (Gradle, Go, Python): Automatically reads from LICENSE file
33+
- **SPDX detection**: Common licenses (Apache-2.0, MIT, GPL-2.0/3.0, LGPL-2.1/3.0, AGPL-3.0, BSD-2-Clause/3-Clause) are automatically detected from LICENSE file content
34+
35+
The backend’s license identification API is used for accurate LICENSE file detection when available.
36+
37+
### Compatibility Checking
38+
39+
The client checks if dependency licenses are compatible with your project license. For example:
40+
- Permissive project (MIT) + permissive dependencies → ✅ Compatible
41+
- Permissive project (MIT) + strong copyleft dependency (GPL) → ⚠️ Potentially incompatible
42+
43+
Compatibility results are included in the analysis report’s `licenseSummary`.
44+
45+
## Configuration
46+
47+
### Disable License Checking
48+
49+
License analysis runs automatically during **component analysis only** (not stack analysis). To disable it:
50+
51+
**Environment variable:**
52+
```bash
53+
export TRUSTIFY_DA_LICENSE_CHECK=false
54+
```
55+
56+
**Programmatic option:**
57+
```javascript
58+
await componentAnalysis(‘pom.xml’, { licenseCheck: false });
59+
```
60+
61+
## CLI Usage
62+
63+
### Get License Information
64+
65+
```bash
66+
exhort license path/to/pom.xml
67+
```
68+
69+
**Example output:**
70+
```json
71+
{
72+
"manifestLicense": {
73+
"spdxId": "Apache-2.0",
74+
"category": "PERMISSIVE",
75+
"name": "Apache License 2.0",
76+
"identifiers": ["Apache-2.0"]
77+
},
78+
"fileLicense": {
79+
"spdxId": "Apache-2.0",
80+
"category": "PERMISSIVE",
81+
"name": "Apache License 2.0",
82+
"identifiers": ["Apache-2.0"]
83+
},
84+
"mismatch": false
85+
}
86+
```
87+
88+
Note: The `license` command shows only your project's license. For dependency license information, use component analysis.
89+
90+
## Analysis Report Fields
91+
92+
When license checking is enabled, component analysis includes a `licenseSummary` field:
93+
94+
```javascript
95+
{
96+
// ... standard analysis fields (providers, etc.) ...
97+
"licenseSummary": {
98+
"projectLicense": {
99+
"manifest": {
100+
"spdxId": "Apache-2.0",
101+
"category": "PERMISSIVE",
102+
"name": "Apache License 2.0",
103+
"identifiers": ["Apache-2.0"]
104+
},
105+
"file": {
106+
"spdxId": "Apache-2.0",
107+
"category": "PERMISSIVE",
108+
"name": "Apache License 2.0",
109+
"identifiers": ["Apache-2.0"]
110+
},
111+
"mismatch": false
112+
},
113+
"incompatibleDependencies": [
114+
{
115+
"purl": "pkg:maven/org.example/gpl-lib@1.0.0",
116+
"licenses": ["GPL-3.0"],
117+
"category": "STRONG_COPYLEFT",
118+
"reason": "Dependency license(s) are incompatible with the project license."
119+
}
120+
]
121+
}
122+
}
123+
```
124+
125+
**Note:** Dependency license information (for all dependencies, not just incompatible ones) is available in the standard backend response under the `licenses` field. The `licenseSummary` only includes project license details and flagged incompatibilities.
126+
127+
## Common Scenarios
128+
129+
### Mismatch Between Manifest and LICENSE File
130+
131+
If your `package.json` says `"license": "MIT"` but your LICENSE file contains Apache-2.0 text, the component analysis report will show:
132+
```json
133+
{
134+
"licenseSummary": {
135+
"projectLicense": {
136+
"manifest": {
137+
"spdxId": "MIT",
138+
"category": "PERMISSIVE",
139+
"name": "MIT License"
140+
},
141+
"file": {
142+
"spdxId": "Apache-2.0",
143+
"category": "PERMISSIVE",
144+
"name": "Apache License 2.0"
145+
},
146+
"mismatch": true
147+
},
148+
"incompatibleDependencies": []
149+
}
150+
}
151+
```
152+
153+
**Action:** Update your manifest or LICENSE file to match.
154+
155+
### Incompatible Dependencies
156+
157+
If you have a permissive-licensed project (MIT, Apache) but depend on GPL-licensed libraries, they’ll appear in `incompatibleDependencies`.
158+
159+
**Action:** Review the flagged dependencies and consider:
160+
- Finding alternative libraries with compatible licenses
161+
- Consulting legal counsel if the dependency is necessary
162+
- Understanding how you’re using the dependency (linking, distribution, etc.)
163+
164+
## SBOM Integration
165+
166+
Project license information is automatically included in generated SBOMs (CycloneDX format) in the root component’s `licenses` field.
167+
168+
**LICENSE file fallback in SBOMs:**
169+
- **All ecosystems** now include license information in the SBOM when available
170+
- **Gradle, Go, Python projects**: Even though these ecosystems don’t have manifest license fields, the SBOM will include the license from your LICENSE file
171+
- **Maven, JavaScript, Rust Cargo projects**: The SBOM uses the manifest license, or falls back to LICENSE file if not specified in manifest
172+
- If neither manifest nor LICENSE file contains a license, the SBOM root component will have no `licenses` field

0 commit comments

Comments
 (0)