Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SCP-48 Extract licenses from results #4

Merged
merged 1 commit into from
Jan 22, 2024
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
24 changes: 9 additions & 15 deletions .github/workflows/test-action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,36 +4,30 @@ on:
pull_request:
push:
branches:
- main
- '*'

permissions:
contents: read

jobs:
test-action:
name: GitHub Actions Test
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.os }}
runs-on: ubuntu-latest

steps:
- name: Checkout
id: checkout
uses: actions/checkout@v4

- name: Setup Python
id: setup-python
uses: actions/setup-python@v5
with:
python-version: '3.10'

- run: pip install scanoss[fast_winnowing] scancode-toolkit

- name: Test Local Action
id: test-action
uses: ./

- name: Print Output
id: output
- name: Print output command
run: echo "${{ steps.test-action.outputs.output-command }}"

- name: Print Licenses
run: echo "${{ steps.test-action.outputs.licenses }}"

- name: Print Result
run: cat "${{ steps.test-action.outputs.result-filepath }}"
2 changes: 1 addition & 1 deletion .prettierrc.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{

Check warning on line 1 in .prettierrc.json

View workflow job for this annotation

GitHub Actions / Lint Codebase

File ignored by default.
"printWidth": 80,
"printWidth": 120,
"tabWidth": 2,
"useTabs": false,
"semi": false,
Expand Down
21 changes: 4 additions & 17 deletions __tests__/main.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,19 +49,9 @@ describe('action', () => {

// Verify that all of the core library functions were called correctly
expect(debugMock).toHaveBeenNthCalledWith(1, 'Waiting 500 milliseconds ...')
expect(debugMock).toHaveBeenNthCalledWith(
2,
expect.stringMatching(timeRegex)
)
expect(debugMock).toHaveBeenNthCalledWith(
3,
expect.stringMatching(timeRegex)
)
expect(setOutputMock).toHaveBeenNthCalledWith(
1,
'time',
expect.stringMatching(timeRegex)
)
expect(debugMock).toHaveBeenNthCalledWith(2, expect.stringMatching(timeRegex))
expect(debugMock).toHaveBeenNthCalledWith(3, expect.stringMatching(timeRegex))
expect(setOutputMock).toHaveBeenNthCalledWith(1, 'time', expect.stringMatching(timeRegex))
expect(errorMock).not.toHaveBeenCalled()
})

Expand All @@ -80,10 +70,7 @@ describe('action', () => {
expect(runMock).toHaveReturned()

// Verify that all of the core library functions were called correctly
expect(setFailedMock).toHaveBeenNthCalledWith(
1,
'milliseconds not a number'
)
expect(setFailedMock).toHaveBeenNthCalledWith(1, 'milliseconds not a number')
expect(errorMock).not.toHaveBeenCalled()
})
})
93 changes: 90 additions & 3 deletions dist/index.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Empty file added results.json
Empty file.
20 changes: 14 additions & 6 deletions src/main.ts
Original file line number Diff line number Diff line change
@@ -1,34 +1,42 @@
import * as core from '@actions/core'
import * as exec from '@actions/exec'
import { getLicenses, readResult } from './services/result.service'

/**
* The main function for the action.
* @returns {Promise<void>} Resolves when the action is complete.
*/
export async function run(): Promise<void> {
try {
const scanParams: string = core.getInput('scan-parameters')

const repoDir = process.env.GITHUB_WORKSPACE as string
const outputPath = 'results.json'

// Declara las opciones para ejecutar el exec
const options: exec.ExecOptions = {}
let output: string = ''
let output = ''
options.listeners = {
stdout: (data: Buffer) => {
output += data.toString()
},
stderr: (data: Buffer) => {
output += data.toString()
}
}
options.silent = true

// run scan
await exec.exec(
'scanoss-py',
['scan', repoDir, '--output', outputPath],
`docker run -v "${repoDir}":"/scanoss" ghcr.io/scanoss/scanoss-py:v1.9.0 scan . --output ${outputPath}`,
[],
options
)

const scannerResults = await readResult(outputPath)
const licenses = getLicenses(scannerResults)

core.setOutput('licenses', licenses.toString())

core.setOutput('output-command', output)

// set outputs for other workflow steps to use
core.setOutput('result-filepath', outputPath)
} catch (error) {
Expand Down
95 changes: 95 additions & 0 deletions src/services/result.interfaces.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
export type ScannerResults = Record<string, ScannerComponent[] | DependencyComponent[]>

export enum ComponentID {

Check failure on line 3 in src/services/result.interfaces.ts

View workflow job for this annotation

GitHub Actions / Lint Codebase

'ComponentID' is already declared in the upper scope on line 3 column 13

Check failure on line 3 in src/services/result.interfaces.ts

View workflow job for this annotation

GitHub Actions / TypeScript Tests

'ComponentID' is already declared in the upper scope on line 3 column 13
NONE = 'none',
FILE = 'file',
SNIPPET = 'snippet',
DEPENDENCY = 'dependency'
}

interface CommonComponent {
id: ComponentID
status: string
}

export interface DependencyComponent extends CommonComponent {
dependencies: {
licenses: {
is_spdx_approved: boolean
name: string
spdx_id: string
}[]
purl: string
url: string
version: string
}[]
}

export interface ScannerComponent extends CommonComponent {
lines: string
oss_lines: string
matched: string
purl: string[]
vendor: string
component: string
version: string
latest: string
url: string
release_date: string
file: string
url_hash: string
file_hash: string
source_hash: string
file_url: string
licenses: {
name: string
patent_hints: string
copyleft: string
checklist_url: string
osadl_updated: string
source: string
incompatible_with?: string
}[]
dependencies: {
vendor: string
component: string
version: string
source: string
}[]
copyrights: {
name: string
source: string
}[]
vulnerabilities: {
ID: string
CVE: string
severity: string
reported: string
introduced: string
patched: string
summary: string
source: string
}[]
quality: {
score: string
source: string
}[]
cryptography: any[]

Check failure on line 77 in src/services/result.interfaces.ts

View workflow job for this annotation

GitHub Actions / Lint Codebase

Unexpected any. Specify a different type

Check failure on line 77 in src/services/result.interfaces.ts

View workflow job for this annotation

GitHub Actions / TypeScript Tests

Unexpected any. Specify a different type
health: {
creation_date: string
issues: number
last_push: string
last_update: string
watchers: number
country: string
stars: number
forks: number
}
server: {
version: string
kb_version: { monthly: string; daily: string }
hostname: string
flags: string
elapsed: string
}
}
32 changes: 32 additions & 0 deletions src/services/result.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { ComponentID, DependencyComponent, ScannerComponent, ScannerResults } from './result.interfaces'
import * as fs from 'fs'

export async function readResult(filepath: string): Promise<ScannerResults> {
const content = await fs.promises.readFile(filepath, 'utf-8')
return JSON.parse(content) as ScannerResults
}

export function getLicenses(results: ScannerResults): string[] {
const licenses = new Set<string>()

for (const component of Object.values(results)) {
for (const c of component) {
if (c.id === ComponentID.DEPENDENCY) {
const dependencies = (c as DependencyComponent).dependencies
for (const d of dependencies) {
for (const l of d.licenses) {
licenses.add(l.spdx_id)
}
}
}

if (c.id === ComponentID.FILE || c.id === ComponentID.SNIPPET) {
for (const l of (c as ScannerComponent).licenses) {
licenses.add(l.name)
}
}
}
}

return Array.from(licenses)
}
Loading
Loading