Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 4 additions & 8 deletions .github/workflows/integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,19 @@ on:
types:
- completed
workflow_dispatch:
pull_request:
branches:
- main

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
call-shared:
# Only run if the test workflow succeeded, or if triggered directly
# Only run if the test workflow succeeded, or if triggered manually
if: |
(github.event_name == 'workflow_run' && github.event.workflow_run.conclusion == 'success') ||
github.event_name == 'workflow_dispatch' ||
github.event_name == 'pull_request'
github.event_name == 'workflow_dispatch'
uses: trustification/exhort-integration-tests/.github/workflows/integration.yml@main
with:
language: javascript
repo-url: ${{ github.event.pull_request.head.repo.full_name || github.repository }}
commit-sha: ${{ github.event.pull_request.head.sha || github.sha }}
repo-url: ${{ github.repository }}
commit-sha: ${{ github.event.workflow_run && github.event.workflow_run.head_sha || github.sha }}
50 changes: 49 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,14 @@ let stackAnalysis = await exhort.stackAnalysis('/path/to/pom.xml')
let stackAnalysisHtml = await exhort.stackAnalysis('/path/to/pom.xml', true)
// Get component analysis in JSON format
let componentAnalysis = await exhort.componentAnalysis('/path/to/pom.xml')
// Get image analysis in JSON format
let imageAnalysis = await exhort.imageAnalysis(['docker.io/library/node:18'])
// Get image analysis in HTML format (string)
let imageAnalysisHtml = await exhort.imageAnalysis(['docker.io/library/node:18'], true)
// Analyze multiple images
let multipleImagesAnalysis = await exhort.imageAnalysis(['docker.io/library/node:18', 'docker.io/library/python:3.9'])
// Specify architecture using ^^ notation (e.g., httpd:2.4.49^^amd64)
let imageAnalysisWithArch = await exhort.imageAnalysis(['httpd:2.4.49^^amd64'])
```
</li>
</ul>
Expand Down Expand Up @@ -68,11 +76,12 @@ Use as CLI Script
```shell
$ npx @trustify-da/trustify-da-javascript-client help

Usage: trustify-da-javascript-client {component|stack}
Usage: trustify-da-javascript-client {component|stack|image|validate-token}

Commands:
trustify-da-javascript-client stack </path/to/manifest> [--html|--summary] produce stack report for manifest path
trustify-da-javascript-client component <path/to/manifest> [--summary] produce component report for a manifest type and content
trustify-da-javascript-client image <image-refs..> [--html|--summary] produce image analysis report for OCI image references

Options:
--help Show help [boolean]
Expand All @@ -91,6 +100,22 @@ $ npx @trustify-da/trustify-da-javascript-client stack /path/to/pom.xml --html

# get component analysis
$ npx @trustify-da/trustify-da-javascript-client component /path/to/pom.xml

# get image analysis in json format
$ npx @trustify-da/trustify-da-javascript-client image docker.io/library/node:18

# get image analysis in json format (summary only)
# Note: summary returns an object with imageRef as key
$ npx @trustify-da/trustify-da-javascript-client image docker.io/library/node:18 --summary

# get image analysis in html format
$ npx @trustify-da/trustify-da-javascript-client image docker.io/library/node:18 --html

# analyze multiple images
$ npx @trustify-da/trustify-da-javascript-client image docker.io/library/node:18 docker.io/library/python:3.9

# specify architecture using ^^ notation (e.g., httpd:2.4.49^^amd64)
$ npx @trustify-da/trustify-da-javascript-client image httpd:2.4.49^^amd64
```
</li>

Expand All @@ -113,6 +138,22 @@ $ trustify-da-javascript-client stack /path/to/pom.xml --html

# get component analysis
$ trustify-da-javascript-client component /path/to/pom.xml

# get image analysis in json format
$ trustify-da-javascript-client image docker.io/library/node:18

# get image analysis in json format (summary only)
# Note: summary returns an object with imageRef as key
$ trustify-da-javascript-client image docker.io/library/node:18 --summary

# get image analysis in html format
$ trustify-da-javascript-client image docker.io/library/node:18 --html

# analyze multiple images
$ trustify-da-javascript-client image docker.io/library/node:18 docker.io/library/python:3.9

# specify architecture using ^^ notation (e.g., httpd:2.4.49^^amd64)
$ trustify-da-javascript-client image httpd:2.4.49^^amd64
```
</li>
</ul>
Expand Down Expand Up @@ -288,6 +329,13 @@ let stackAnalysisHtml = await exhort.stackAnalysis('/path/to/pom.xml', true, opt

// Get component analysis in JSON format
let componentAnalysis = await exhort.componentAnalysis('/path/to/pom.xml', options)

// Get image analysis in JSON format
let imageAnalysis = await exhort.imageAnalysis(['docker.io/library/node:18'], false, options)
// Get image analysis in HTML format in string
let imageAnalysisHtml = await exhort.imageAnalysis(['docker.io/library/node:18'], true, options)
// Specify architecture using ^^ notation (e.g., httpd:2.4.49^^amd64)
let imageAnalysisWithArch = await exhort.imageAnalysis(['httpd:2.4.49^^amd64'], false, options)
```
**_Environment variables takes precedence._**
</p>
Expand Down
61 changes: 60 additions & 1 deletion src/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,64 @@ const validateToken = {
}
}

// command for image analysis takes OCI image references
const image = {
command: 'image <image-refs..>',
desc: 'produce image analysis report for OCI image references',
builder: yargs => yargs.positional(
'image-refs',
{
desc: 'OCI image references to analyze (one or more)',
type: 'string',
array: true,
}
).options({
html: {
alias: 'r',
desc: 'Get the report as HTML instead of JSON',
type: 'boolean',
conflicts: 'summary'
},
summary: {
alias: 's',
desc: 'For JSON report, get only the \'summary\'',
type: 'boolean',
conflicts: 'html'
}
}),
handler: async args => {
let imageRefs = args['image-refs']
if (!Array.isArray(imageRefs)) {
imageRefs = [imageRefs]
}
let html = args['html']
let summary = args['summary']
let res = await exhort.imageAnalysis(imageRefs, html)
if(summary && !html) {
let summaries = {}
for (let [imageRef, report] of Object.entries(res)) {
for (let provider in report.providers) {
if (report.providers[provider].sources !== undefined) {
for (let source in report.providers[provider].sources) {
if (report.providers[provider].sources[source].summary) {
if (!summaries[imageRef]) {
summaries[imageRef] = {};
}
if (!summaries[imageRef][provider]) {
summaries[imageRef][provider] = {};
}
summaries[imageRef][provider][source] = report.providers[provider].sources[source].summary
}
}
}
}
}
res = summaries
}
console.log(html ? res : JSON.stringify(res, null, 2))
}
}

// command for stack analysis takes a manifest path
const stack = {
command: 'stack </path/to/manifest> [--html|--summary]',
Expand Down Expand Up @@ -112,9 +170,10 @@ const stack = {

// parse and invoke the command
yargs(hideBin(process.argv))
.usage(`Usage: ${process.argv[0].includes("node") ? path.parse(process.argv[1]).base : path.parse(process.argv[0]).base} {component|stack|validate-token}`)
.usage(`Usage: ${process.argv[0].includes("node") ? path.parse(process.argv[1]).base : path.parse(process.argv[0]).base} {component|stack|image|validate-token}`)
.command(stack)
.command(component)
.command(image)
.command(validateToken)
.scriptName('')
.version(false)
Expand Down
Loading