mirror of
https://github.com/gradle/gradle-build-action.git
synced 2024-11-22 17:12:51 +00:00
be413309fa
- Dependency graph init-script references published version of plugin jar. - `dependency-graph-generate` action will: - Provision Gradle if required - Execute Gradle with dependency-graph plugin to generate graph JSON - Upload dependency-graph JSON file as workflow artifact - `dependency-graph-submit` action will: - Download dependency-graph JSON artifact - Submit the graph via the GitHub dependency submission API
155 lines
5.6 KiB
TypeScript
155 lines
5.6 KiB
TypeScript
import * as core from '@actions/core'
|
|
import * as artifact from '@actions/artifact'
|
|
import * as github from '@actions/github'
|
|
import * as glob from '@actions/glob'
|
|
import * as toolCache from '@actions/tool-cache'
|
|
import {Octokit} from '@octokit/rest'
|
|
|
|
import * as path from 'path'
|
|
import fs from 'fs'
|
|
|
|
import * as execution from './execution'
|
|
import * as layout from './repository-layout'
|
|
|
|
const DEPENDENCY_GRAPH_ARTIFACT = 'dependency-graph'
|
|
const DEPENDENCY_GRAPH_FILE = 'dependency-graph.json'
|
|
|
|
export async function generateDependencyGraph(executable: string | undefined): Promise<void> {
|
|
const workspaceDirectory = layout.workspaceDirectory()
|
|
const buildRootDirectory = layout.buildRootDirectory()
|
|
const buildPath = getRelativePathFromWorkspace(buildRootDirectory)
|
|
|
|
const initScript = path.resolve(
|
|
__dirname,
|
|
'..',
|
|
'..',
|
|
'src',
|
|
'resources',
|
|
'init-scripts',
|
|
'github-dependency-graph.init.gradle'
|
|
)
|
|
const args = [
|
|
`-Dorg.gradle.github.env.GRADLE_BUILD_PATH=${buildPath}`,
|
|
'--init-script',
|
|
initScript,
|
|
':GitHubDependencyGraphPlugin_generateDependencyGraph'
|
|
]
|
|
|
|
await execution.executeGradleBuild(executable, buildRootDirectory, args)
|
|
const dependencyGraphJson = copyDependencyGraphToBuildRoot(buildRootDirectory)
|
|
|
|
const artifactClient = artifact.create()
|
|
artifactClient.uploadArtifact(DEPENDENCY_GRAPH_ARTIFACT, [dependencyGraphJson], workspaceDirectory)
|
|
}
|
|
|
|
function copyDependencyGraphToBuildRoot(buildRootDirectory: string): string {
|
|
const sourceFile = path.resolve(
|
|
buildRootDirectory,
|
|
'build',
|
|
'reports',
|
|
'github-dependency-graph-plugin',
|
|
'github-dependency-snapshot.json'
|
|
)
|
|
|
|
const destFile = path.resolve(buildRootDirectory, DEPENDENCY_GRAPH_FILE)
|
|
fs.copyFileSync(sourceFile, destFile)
|
|
return destFile
|
|
}
|
|
|
|
export async function submitDependencyGraph(): Promise<void> {
|
|
const workspaceDirectory = layout.workspaceDirectory()
|
|
const octokit: Octokit = getOctokit()
|
|
|
|
for (const jsonFile of await retrieveDependencyGraphs(octokit, workspaceDirectory)) {
|
|
const jsonContent = fs.readFileSync(jsonFile, 'utf8')
|
|
|
|
const jsonObject = JSON.parse(jsonContent)
|
|
jsonObject.owner = github.context.repo.owner
|
|
jsonObject.repo = github.context.repo.repo
|
|
const response = await octokit.request('POST /repos/{owner}/{repo}/dependency-graph/snapshots', jsonObject)
|
|
|
|
const relativeJsonFile = getRelativePathFromWorkspace(jsonFile)
|
|
core.info(`Submitted ${relativeJsonFile}: ${JSON.stringify(response)}`)
|
|
core.notice(`Submitted ${relativeJsonFile}: ${response.data.message}`)
|
|
}
|
|
}
|
|
|
|
async function findDependencyGraphFiles(dir: string): Promise<string[]> {
|
|
const globber = await glob.create(`${dir}/**/${DEPENDENCY_GRAPH_FILE}`)
|
|
const graphFiles = globber.glob()
|
|
core.info(`Found graph files in ${dir}: ${graphFiles}`)
|
|
return graphFiles
|
|
}
|
|
|
|
async function retrieveDependencyGraphs(octokit: Octokit, workspaceDirectory: string): Promise<string[]> {
|
|
if (github.context.payload.workflow_run) {
|
|
return await retrieveDependencyGraphsForWorkflowRun(
|
|
github.context.payload.workflow_run.id,
|
|
octokit,
|
|
workspaceDirectory
|
|
)
|
|
}
|
|
return retrieveDependencyGraphsForCurrentWorkflow(workspaceDirectory)
|
|
}
|
|
|
|
async function retrieveDependencyGraphsForWorkflowRun(
|
|
runId: number,
|
|
octokit: Octokit,
|
|
workspaceDirectory: string
|
|
): Promise<string[]> {
|
|
// Find the workflow run artifacts named "dependency-graph"
|
|
const artifacts = await octokit.rest.actions.listWorkflowRunArtifacts({
|
|
owner: github.context.repo.owner,
|
|
repo: github.context.repo.repo,
|
|
run_id: runId
|
|
})
|
|
|
|
const matchArtifact = artifacts.data.artifacts.find(candidate => {
|
|
return candidate.name === DEPENDENCY_GRAPH_ARTIFACT
|
|
})
|
|
|
|
if (matchArtifact === undefined) {
|
|
throw new Error(`Dependency graph artifact not found. Has it been generated by workflow run '${runId}'?`)
|
|
}
|
|
|
|
// Download the dependency-graph artifact
|
|
const download = await octokit.rest.actions.downloadArtifact({
|
|
owner: github.context.repo.owner,
|
|
repo: github.context.repo.repo,
|
|
artifact_id: matchArtifact.id,
|
|
archive_format: 'zip'
|
|
})
|
|
|
|
const downloadBuffer = download.data as ArrayBuffer
|
|
const downloadZip = path.resolve(workspaceDirectory, 'dependency-graph.zip')
|
|
fs.writeFileSync(downloadZip, Buffer.from(downloadBuffer))
|
|
|
|
// Expance the dependency-graph zip and locate each dependency-graph JSON file
|
|
const extractDir = path.resolve(workspaceDirectory, 'dependency-graph')
|
|
const extracted = await toolCache.extractZip(downloadZip, extractDir)
|
|
core.info(`Extracted dependency graph artifacts to ${extracted}: ${fs.readdirSync(extracted)}`)
|
|
|
|
return findDependencyGraphFiles(extracted)
|
|
}
|
|
|
|
async function retrieveDependencyGraphsForCurrentWorkflow(workspaceDirectory: string): Promise<string[]> {
|
|
const artifactClient = artifact.create()
|
|
const downloadPath = path.resolve(workspaceDirectory, 'dependency-graph')
|
|
await artifactClient.downloadArtifact(DEPENDENCY_GRAPH_ARTIFACT, downloadPath)
|
|
return await findDependencyGraphFiles(downloadPath)
|
|
}
|
|
|
|
function getOctokit(): Octokit {
|
|
return new Octokit({
|
|
auth: getGithubToken()
|
|
})
|
|
}
|
|
|
|
function getGithubToken(): string {
|
|
return core.getInput('github-token', {required: true})
|
|
}
|
|
|
|
function getRelativePathFromWorkspace(file: string): string {
|
|
const workspaceDirectory = layout.workspaceDirectory()
|
|
return path.relative(workspaceDirectory, file)
|
|
}
|