Skip to content

Commit

Permalink
feat: make detect-version optional by downloading latest (#8)
Browse files Browse the repository at this point in the history
  • Loading branch information
tvcsantos authored Sep 11, 2023
1 parent 9cd26a9 commit 9292525
Show file tree
Hide file tree
Showing 11 changed files with 165 additions and 48 deletions.
10 changes: 9 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [1.1.0] - 2023-09-11

### Added

- Make `detect-version` optional by downloading latest
- Support major version pattern on `detect-version`

## [1.0.0] - 2023-09-10

### Changed
Expand All @@ -29,6 +36,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Improve logging
- Update dependencies and refactor action

[Unreleased]: https://github.com/mercedesbenzio/detect-action/compare/v1.0.0...main
[Unreleased]: https://github.com/mercedesbenzio/detect-action/compare/v1.1.0...main
[1.1.0]: https://github.com/mercedesbenzio/detect-action/compare/v1.0.0...v1.1.0
[1.0.0]: https://github.com/mercedesbenzio/detect-action/compare/v0.4.0...v1.0.0
[0.4.0]: https://github.com/mercedesbenzio/detect-action/releases/tag/v0.4.0
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ to run, provide:

- Black Duck URL (`blackduck-url`)
- Black Duck API Token (`blackduck-api-token`)
- Your desired Detect Version (`detect-version`) to execute
- Your desired Detect Version (`detect-version`), or empty if you want to scan using the latest version
- Your _GITHUB\_TOKEN_ (`github-token`) to comment on Pull Requests or hook into GitHub Checks (in most cases, this
is `${{ secrets.GITHUB_TOKEN }}`)

Expand Down Expand Up @@ -366,7 +366,7 @@ After running detect this action will set the following output variables with de
- `detect-exit-code-name` - The corresponding human name of the error code.

Note that if Detect is not called these variables are not populated. Also, if a mapping for the exit code number is not
found on our side `detect-exit-code-name` we will set it to `UNKOWN`.
found on our side `detect-exit-code-name` we will set it to `UNKNOWN`.

### Include Custom Certificates (Optional)

Expand Down
19 changes: 12 additions & 7 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,26 +8,31 @@ inputs:
description: 'Your GitHub token'
required: true
detect-version:
description: 'The version of Detect to download'
required: true
description: |-
Detect version to be used on Black Duck scan.
The following input patterns are allowed:
- A full version (e.g. 8.4.0) to scan using that exact version.
- A major version (e.g. 8) to scan using the latest version of the given major.
- Empty or not specified, to scan using the latest version of Detect.
required: false
blackduck-url:
description: 'Url of Black Duck instance'
required: true
blackduck-api-token:
description: 'API Token for Black Duck instance'
required: true
scan-mode:
description: |
Either RAPID or INTELLIGENT, configures how Detect is invoked.
RAPID will not persist the results and disables select Detect functionality for faster results.
INTELLIGENT persists the results and permits all features of Detect.
description: |-
Configures how Detect is invoked. When specified use one of the following:
- RAPID: will not persist the results and disables selected Detect functionality for faster results.
- INTELLIGENT: persists the results and allows all features of Detect.
required: false
default: 'RAPID'
output-path-override:
description: 'Override for where to output Detect files, default is $RUNNER_TEMP/blackduck/'
required: false
detect-trust-cert:
description: |
description: |-
When set to true Detect will trust the Black Duck certificate
even if the certificate is not in the keystore.
default: 'true'
Expand Down
69 changes: 54 additions & 15 deletions dist/index.js

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

4 changes: 2 additions & 2 deletions package-lock.json

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

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "detect-action",
"description": "Richly integrate Synopsys Detect and Black Duck policy into your GitHub Action pipelines",
"version": "1.0.0",
"version": "1.1.0",
"author": "Mercedes-Benz.io",
"private": true,
"homepage": "https://github.com/mercedesbenzio/detect-action",
Expand Down
4 changes: 2 additions & 2 deletions src/action/action-orchestrator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ export class ActionOrchestrator {
)
core.info(`${Input.SCAN_MODE}: ${this.inputs.scanMode}.`)

const detectPath = await new DetectToolDownloader(
const detectPath = await DetectToolDownloader.getInstance().download(
this.inputs.detectVersion
).download()
)

const detectFacade = new DetectFacade(
APPLICATION_NAME,
Expand Down
87 changes: 72 additions & 15 deletions src/detect/detect-tool-downloader.ts
Original file line number Diff line number Diff line change
@@ -1,39 +1,96 @@
import { ToolDownloader } from '../downloader/tool-downloader'
import * as toolCache from '@actions/tool-cache'
import path from 'path'
import { HttpClient } from 'typed-rest-client/HttpClient'
import { APPLICATION_NAME } from '../action/constants'
import { IHeaders } from 'typed-rest-client/Interfaces'
import { DetectToolsVersions } from './detect-tools-versions'
import { DetectToolVersion } from './detect-tool-version'

const DETECT_BINARY_REPO_URL = 'https://sig-repo.synopsys.com'
export const TOOL_NAME = 'detect'

export class DetectToolDownloader implements ToolDownloader {
private readonly version: string
private async getDetectVersions(): Promise<DetectToolsVersions> {
const authenticationClient = new HttpClient(APPLICATION_NAME)
const headers: IHeaders = {
'X-Result-Detail': 'info'
}

constructor(version: string) {
this.version = version
const httpClientResponse = await authenticationClient.get(
`${DETECT_BINARY_REPO_URL}/api/storage/bds-integrations-release/com/synopsys/integration/synopsys-detect?properties`,
headers
)
const responseBody = await httpClientResponse.readBody()
return JSON.parse(responseBody) as DetectToolsVersions
}

private getDetectDownloadUrl(): string {
return `${DETECT_BINARY_REPO_URL}/bds-integrations-release/com/synopsys/integration/synopsys-detect/${this.version}/synopsys-detect-${this.version}.jar`
private async findDetectVersion(
version?: string
): Promise<DetectToolVersion> {
if (version?.match(/^[0-9]+.[0-9]+.[0-9]+$/)) {
return {
url: `${DETECT_BINARY_REPO_URL}/bds-integrations-release/com/synopsys/integration/synopsys-detect/${version}/synopsys-detect-${version}.jar`,
version,
jarName: `synopsys-detect-${version}.jar`
}
}

let detectVersionKey = 'DETECT_LATEST_'

if (version?.match(/^[0-9]+/)) {
detectVersionKey = `DETECT_LATEST_${version}`
} else if (version) {
throw new Error(`Invalid input version '${version}'`)
}

const detectVersions = await this.getDetectVersions()
const keys = Object.keys(detectVersions.properties)
const key = keys.filter(x => x.match(detectVersionKey)).at(-1)
if (!key) {
throw new Error(
`Cannot find matching key ${detectVersionKey} on detect versions!`
)
}
const url = detectVersions.properties[key].at(-1)
if (!url) {
throw new Error(`Cannot find url for property ${key} on detect versions!`)
}

const jarName = url.substring(url.lastIndexOf('/') + 1)
const resultVersion = jarName.substring(
jarName.lastIndexOf('-') + 1,
jarName.length - 4
)

return { url, version: resultVersion, jarName }
}

async download(): Promise<string> {
const jarName = `synopsys-detect-${this.version}.jar`
async download(version?: string): Promise<string> {
const detectVersion = await this.findDetectVersion(version)

const cachedDetect = toolCache.find(TOOL_NAME, this.version)
const cachedDetect = toolCache.find(TOOL_NAME, detectVersion.version)
if (cachedDetect) {
return path.resolve(cachedDetect, jarName)
return path.resolve(cachedDetect, detectVersion.jarName)
}

const detectDownloadUrl = this.getDetectDownloadUrl()

const detectDownloadPath = await toolCache.downloadTool(detectDownloadUrl)
const detectDownloadPath = await toolCache.downloadTool(detectVersion.url)
const cachedFolder = await toolCache.cacheFile(
detectDownloadPath,
jarName,
detectVersion.jarName,
TOOL_NAME,
this.version
detectVersion.version
)

return path.resolve(cachedFolder, jarName)
return path.resolve(cachedFolder, detectVersion.jarName)
}

private static instance: DetectToolDownloader | null

static getInstance(): DetectToolDownloader {
if (!DetectToolDownloader.instance) {
DetectToolDownloader.instance = new DetectToolDownloader()
}
return DetectToolDownloader.instance
}
}
5 changes: 5 additions & 0 deletions src/detect/detect-tool-version.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export interface DetectToolVersion {
url: string
version: string
jarName: string
}
3 changes: 3 additions & 0 deletions src/detect/detect-tools-versions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export interface DetectToolsVersions {
properties: Record<string, string[]>
}
6 changes: 3 additions & 3 deletions src/input/inputs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ export interface Inputs {
token: string
blackDuckUrl: string
blackDuckApiToken: string
detectVersion: string
detectVersion?: string
scanMode: string
outputPathOverride: string
detectTrustCertificate: string
Expand Down Expand Up @@ -52,8 +52,8 @@ function getInputBlackDuckApiToken(): string {
return core.getInput(Input.BLACKDUCK_API_TOKEN, { required: true })
}

function getInputDetectVersion(): string {
return core.getInput(Input.DETECT_VERSION, { required: true })
function getInputDetectVersion(): string | undefined {
return core.getInput(Input.DETECT_VERSION) ?? undefined
}

function getInputScanMode(): string {
Expand Down

0 comments on commit 9292525

Please sign in to comment.