Skip to content
This repository was archived by the owner on Jun 16, 2022. It is now read-only.

Commit b4e5a1b

Browse files
authored
Use go list to build accurate graph
1 parent a894776 commit b4e5a1b

File tree

5 files changed

+89
-125
lines changed

5 files changed

+89
-125
lines changed

src/go_mod_parser.ts

Lines changed: 0 additions & 45 deletions
This file was deleted.

src/index.ts

Lines changed: 26 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
import * as core from '@actions/core'
22
import { run } from '@github/dependency-submission-toolkit'
33
import { ProcessDependenciesContent } from '@github/dependency-submission-toolkit/dist/processor'
4-
import { parseDependents } from './go_mod_parser'
4+
import { Detector, Metadata } from '@github/dependency-submission-toolkit/dist/snapshot'
5+
import { parseDependents } from './parse-go-package'
56
import * as path from 'path'
67
import * as process from 'process'
7-
import execa from 'execa'
8+
import fs from 'fs'
89

910
const parseDependentsFunc: ProcessDependenciesContent = parseDependents
1011

@@ -15,43 +16,35 @@ const detector = {
1516
version: core.getInput('detector-version')
1617
}
1718

18-
async function searchForFile (filename: string) {
19-
console.log(`searching for ${filename} in ${process.cwd()}`)
20-
21-
const { stdout } = await execa('find', [process.cwd(), '-name', filename])
22-
23-
const dirs = stdout
24-
.split('\n')
25-
.filter((s) => s.length > 0)
26-
// remove the file name
27-
.map((filename) => path.dirname(filename))
28-
// map to absolute path
29-
.map((pathname) => path.resolve(process.cwd(), pathname))
30-
31-
return dirs
32-
}
19+
// For a specific Go _build target_, this commands lists all dependencies used
20+
// to build the build target It does not provide association between the
21+
// dependencies (i.e. which dependencies depend on which)
22+
// eslint-disable-next-line quotes
23+
const goListDependencies = `go list -deps -f '{{define "M"}}{{.Path}}@{{.Version}}{{end}}{{with .Module}}{{if not .Main}}{{if .Replace}}{{template "M" .Replace}}{{else}}{{template "M" .}}{{end}}{{end}}{{end}}'`
3324

3425
// Enumerate directories
3526
async function detect () {
36-
const goModPaths = await searchForFile('go.mod')
37-
3827
// If provided, set the metadata provided from the action workflow input
28+
const goModPath = core.getInput('goModPath')
29+
if (path.basename(goModPath) !== 'go.mod' && fs.existsSync(goModPath)) {
30+
throw new Error(`${goModPath} is not a go.mod file or does not exist!`)
31+
}
32+
const goModDir = path.dirname(goModPath)
33+
const goBuildTarget = core.getInput('goBuildTarget')
34+
if (goBuildTarget !== 'all' && goBuildTarget !== '...' && fs.existsSync(path.join(goModDir, goBuildTarget))) {
35+
throw new Error(`The build target '${goBuildTarget}' does not exist at ${path.join(goModDir, goBuildTarget)}`)
36+
}
37+
3938
const metadataInput = core.getInput('metadata')
4039

41-
goModPaths.forEach((path) => {
42-
process.chdir(path)
43-
console.log(`Running go mod graph in ${path}`)
44-
if (metadataInput.length < 1) {
45-
run(parseDependentsFunc, { command: 'go mod graph' }, { detector })
46-
} else {
47-
const metadata = JSON.parse(metadataInput)
48-
run(
49-
parseDependentsFunc,
50-
{ command: 'go mod graph' },
51-
{ metadata, detector }
52-
)
53-
}
54-
})
40+
process.chdir(goModPath)
41+
console.log(`Running go package detection in ${path} on build target ${goBuildTarget}`)
42+
const options: {detector: Detector, metadata?: Metadata } = { detector }
43+
if (metadataInput) {
44+
const metadata = JSON.parse(metadataInput)
45+
options.metadata = metadata
46+
}
47+
run(parseDependentsFunc, { command: `${goListDependencies} ${goBuildTarget}` }, options)
5548
}
5649

5750
detect()

src/parse-go-package.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import {
2+
Entry,
3+
ParsedDependencies
4+
} from '@github/dependency-submission-toolkit/dist/processor'
5+
6+
import path from 'path'
7+
8+
// processes a list of go dependencies, one dependency per line, matching the
9+
// format "${GO_PACKAGE}@v{VERSION}"
10+
export function parseDependents (contents: string) {
11+
// split the input by newlines, sort, and dedup
12+
const packages: string[] = Array.from(new Set(contents.split('\n').map(p => p.trim()).sort()))
13+
14+
const entries: ParsedDependencies = {}
15+
packages.forEach((pkg: string) => {
16+
if (!pkg) return
17+
const [qualifiedPackage, version] = pkg.split('@')
18+
// URI-encode slashes in the namespace
19+
const namespace = encodeURIComponent(path.dirname(qualifiedPackage))
20+
const name = path.basename(qualifiedPackage)
21+
const targetPkg = `pkg:golang/${namespace}/${name}@${version}`
22+
entries[targetPkg] = new Entry(targetPkg)
23+
})
24+
return entries
25+
}

test/go_mod_parser.test.ts

Lines changed: 0 additions & 47 deletions
This file was deleted.

test/parse-go-package.test.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { describe, expect, test } from '@jest/globals'
2+
import { parseDependents } from '../src/parse-go-package'
3+
4+
const GO_DEPENDENCIES = `go.opentelemetry.io/otel/exporters/otlp/otlptrace/[email protected]
5+
golang.org/x/[email protected]
6+
golang.org/x/[email protected]
7+
golang.org/x/[email protected]
8+
golang.org/x/[email protected]`
9+
10+
describe('test dependenciesProcessorFunc', () => {
11+
test('parses output of go list command into dependencies', () => {
12+
const dependencies = parseDependents(GO_DEPENDENCIES)
13+
14+
expect(Object.values(dependencies).length).toEqual(3)
15+
expect(dependencies).toEqual(
16+
{
17+
'pkg:golang/go.opentelemetry.io%2Fotel%2Fexporters%2Fotlp%2Fotlptrace/[email protected]': {
18+
package_url: 'pkg:golang/go.opentelemetry.io%2Fotel%2Fexporters%2Fotlp%2Fotlptrace/[email protected]',
19+
name: 'pkg:golang/go.opentelemetry.io%2Fotel%2Fexporters%2Fotlp%2Fotlptrace/otlptracehttp',
20+
version: 'v1.7.0',
21+
dependencies: []
22+
},
23+
'pkg:golang/golang.org%2Fx/[email protected]': {
24+
package_url: 'pkg:golang/golang.org%2Fx/[email protected]',
25+
name: 'pkg:golang/golang.org%2Fx/sys',
26+
version: 'v0.0.0-20220317061510-51cd9980dadf',
27+
dependencies: []
28+
},
29+
'pkg:golang/golang.org%2Fx/[email protected]': {
30+
package_url: 'pkg:golang/golang.org%2Fx/[email protected]',
31+
name: 'pkg:golang/golang.org%2Fx/text',
32+
version: 'v0.3.7',
33+
dependencies: []
34+
}
35+
}
36+
)
37+
})
38+
})

0 commit comments

Comments
 (0)