| 
							
							
							
						 |  |  | @@ -1,8 +1,7 @@ | 
		
	
		
			
				|  |  |  |  | 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 {DefaultArtifactClient} from '@actions/artifact' | 
		
	
		
			
				|  |  |  |  | import {GitHub} from '@actions/github/lib/utils' | 
		
	
		
			
				|  |  |  |  | import {RequestError} from '@octokit/request-error' | 
		
	
		
			
				|  |  |  |  | import type {PullRequestEvent} from '@octokit/webhooks-types' | 
		
	
	
		
			
				
					
					|  |  |  | @@ -13,7 +12,7 @@ import fs from 'fs' | 
		
	
		
			
				|  |  |  |  | import * as layout from './repository-layout' | 
		
	
		
			
				|  |  |  |  | import {DependencyGraphOption, getJobMatrix, getArtifactRetentionDays} from './input-params' | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | const DEPENDENCY_GRAPH_ARTIFACT = 'dependency-graph' | 
		
	
		
			
				|  |  |  |  | const DEPENDENCY_GRAPH_PREFIX = 'dependency-graph_' | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | export async function setup(option: DependencyGraphOption): Promise<void> { | 
		
	
		
			
				|  |  |  |  |     if (option === DependencyGraphOption.Disabled) { | 
		
	
	
		
			
				
					
					|  |  |  | @@ -39,37 +38,48 @@ export async function setup(option: DependencyGraphOption): Promise<void> { | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | export async function complete(option: DependencyGraphOption): Promise<void> { | 
		
	
		
			
				|  |  |  |  |     switch (option) { | 
		
	
		
			
				|  |  |  |  |         case DependencyGraphOption.Disabled: | 
		
	
		
			
				|  |  |  |  |         case DependencyGraphOption.DownloadAndSubmit: // Performed in setup | 
		
	
		
			
				|  |  |  |  |             return | 
		
	
		
			
				|  |  |  |  |         case DependencyGraphOption.Generate: | 
		
	
		
			
				|  |  |  |  |             await uploadDependencyGraphs() | 
		
	
		
			
				|  |  |  |  |             return | 
		
	
		
			
				|  |  |  |  |         case DependencyGraphOption.GenerateAndSubmit: | 
		
	
		
			
				|  |  |  |  |             await submitDependencyGraphs(await uploadDependencyGraphs()) | 
		
	
		
			
				|  |  |  |  |             return | 
		
	
		
			
				|  |  |  |  |     try { | 
		
	
		
			
				|  |  |  |  |         switch (option) { | 
		
	
		
			
				|  |  |  |  |             case DependencyGraphOption.Disabled: | 
		
	
		
			
				|  |  |  |  |             case DependencyGraphOption.Generate: // Performed via init-script: nothing to do here | 
		
	
		
			
				|  |  |  |  |             case DependencyGraphOption.DownloadAndSubmit: // Performed in setup | 
		
	
		
			
				|  |  |  |  |                 return | 
		
	
		
			
				|  |  |  |  |             case DependencyGraphOption.GenerateAndSubmit: | 
		
	
		
			
				|  |  |  |  |                 await submitDependencyGraphs(await findGeneratedDependencyGraphFiles()) | 
		
	
		
			
				|  |  |  |  |                 return | 
		
	
		
			
				|  |  |  |  |             case DependencyGraphOption.GenerateAndUpload: | 
		
	
		
			
				|  |  |  |  |                 await uploadDependencyGraphs(await findGeneratedDependencyGraphFiles()) | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |     } catch (e) { | 
		
	
		
			
				|  |  |  |  |         core.warning(`Failed to ${option} dependency graph. Will continue. ${String(e)}`) | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | async function uploadDependencyGraphs(): Promise<string[]> { | 
		
	
		
			
				|  |  |  |  | async function findGeneratedDependencyGraphFiles(): Promise<string[]> { | 
		
	
		
			
				|  |  |  |  |     const workspaceDirectory = layout.workspaceDirectory() | 
		
	
		
			
				|  |  |  |  |     const graphFiles = await findDependencyGraphFiles(workspaceDirectory) | 
		
	
		
			
				|  |  |  |  |     return await findDependencyGraphFiles(workspaceDirectory) | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |     const relativeGraphFiles = graphFiles.map(x => getRelativePathFromWorkspace(x)) | 
		
	
		
			
				|  |  |  |  |     core.info(`Uploading dependency graph files: ${relativeGraphFiles}`) | 
		
	
		
			
				|  |  |  |  | async function uploadDependencyGraphs(dependencyGraphFiles: string[]): Promise<void> { | 
		
	
		
			
				|  |  |  |  |     const workspaceDirectory = layout.workspaceDirectory() | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |     const artifactClient = artifact.create() | 
		
	
		
			
				|  |  |  |  |     artifactClient.uploadArtifact(DEPENDENCY_GRAPH_ARTIFACT, graphFiles, workspaceDirectory, { | 
		
	
		
			
				|  |  |  |  |         retentionDays: getArtifactRetentionDays() | 
		
	
		
			
				|  |  |  |  |     }) | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |     return graphFiles | 
		
	
		
			
				|  |  |  |  |     const artifactClient = new DefaultArtifactClient() | 
		
	
		
			
				|  |  |  |  |     for (const dependencyGraphFile of dependencyGraphFiles) { | 
		
	
		
			
				|  |  |  |  |         const relativePath = getRelativePathFromWorkspace(dependencyGraphFile) | 
		
	
		
			
				|  |  |  |  |         core.info(`Uploading dependency graph file: ${relativePath}`) | 
		
	
		
			
				|  |  |  |  |         const artifactName = `${DEPENDENCY_GRAPH_PREFIX}${path.basename(dependencyGraphFile)}` | 
		
	
		
			
				|  |  |  |  |         await artifactClient.uploadArtifact(artifactName, [dependencyGraphFile], workspaceDirectory, { | 
		
	
		
			
				|  |  |  |  |             retentionDays: getArtifactRetentionDays() | 
		
	
		
			
				|  |  |  |  |         }) | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | async function downloadAndSubmitDependencyGraphs(): Promise<void> { | 
		
	
		
			
				|  |  |  |  |     const workspaceDirectory = layout.workspaceDirectory() | 
		
	
		
			
				|  |  |  |  |     submitDependencyGraphs(await retrieveDependencyGraphs(workspaceDirectory)) | 
		
	
		
			
				|  |  |  |  |     try { | 
		
	
		
			
				|  |  |  |  |         await submitDependencyGraphs(await downloadDependencyGraphs()) | 
		
	
		
			
				|  |  |  |  |     } catch (e) { | 
		
	
		
			
				|  |  |  |  |         core.warning(`Download and submit dependency graph failed. Will continue. ${String(e)}`) | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | async function submitDependencyGraphs(dependencyGraphFiles: string[]): Promise<void> { | 
		
	
	
		
			
				
					
					|  |  |  | @@ -111,56 +121,37 @@ async function submitDependencyGraphFile(jsonFile: string): Promise<void> { | 
		
	
		
			
				|  |  |  |  |     core.notice(`Submitted ${relativeJsonFile}: ${response.data.message}`) | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | async function retrieveDependencyGraphs(workspaceDirectory: string): Promise<string[]> { | 
		
	
		
			
				|  |  |  |  |     if (github.context.payload.workflow_run) { | 
		
	
		
			
				|  |  |  |  |         return await retrieveDependencyGraphsForWorkflowRun(github.context.payload.workflow_run.id, workspaceDirectory) | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     return retrieveDependencyGraphsForCurrentWorkflow(workspaceDirectory) | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | async function downloadDependencyGraphs(): Promise<string[]> { | 
		
	
		
			
				|  |  |  |  |     const workspaceDirectory = layout.workspaceDirectory() | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | async function retrieveDependencyGraphsForWorkflowRun(runId: number, workspaceDirectory: string): Promise<string[]> { | 
		
	
		
			
				|  |  |  |  |     const octokit = getOctokit() | 
		
	
		
			
				|  |  |  |  |     const findBy = github.context.payload.workflow_run | 
		
	
		
			
				|  |  |  |  |         ? { | 
		
	
		
			
				|  |  |  |  |               token: getGithubToken(), | 
		
	
		
			
				|  |  |  |  |               workflowRunId: github.context.payload.workflow_run.id, | 
		
	
		
			
				|  |  |  |  |               repositoryName: github.context.repo.repo, | 
		
	
		
			
				|  |  |  |  |               repositoryOwner: github.context.repo.owner | 
		
	
		
			
				|  |  |  |  |           } | 
		
	
		
			
				|  |  |  |  |         : undefined | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |     // 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 artifactClient = new DefaultArtifactClient() | 
		
	
		
			
				|  |  |  |  |     const downloadPath = path.resolve(workspaceDirectory, 'dependency-graph') | 
		
	
		
			
				|  |  |  |  |     await artifactClient.downloadArtifact(DEPENDENCY_GRAPH_ARTIFACT, downloadPath) | 
		
	
		
			
				|  |  |  |  |     return await findDependencyGraphFiles(downloadPath) | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |     const dependencyGraphArtifacts = ( | 
		
	
		
			
				|  |  |  |  |         await artifactClient.listArtifacts({ | 
		
	
		
			
				|  |  |  |  |             latest: true, | 
		
	
		
			
				|  |  |  |  |             findBy | 
		
	
		
			
				|  |  |  |  |         }) | 
		
	
		
			
				|  |  |  |  |     ).artifacts.filter(candidate => candidate.name.startsWith(DEPENDENCY_GRAPH_PREFIX)) | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |     for (const artifact of dependencyGraphArtifacts) { | 
		
	
		
			
				|  |  |  |  |         const downloadedArtifact = await artifactClient.downloadArtifact(artifact.id, { | 
		
	
		
			
				|  |  |  |  |             path: downloadPath, | 
		
	
		
			
				|  |  |  |  |             findBy | 
		
	
		
			
				|  |  |  |  |         }) | 
		
	
		
			
				|  |  |  |  |         core.info(`Downloading dependency-graph artifact ${artifact.name} to ${downloadedArtifact.downloadPath}`) | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |     return findDependencyGraphFiles(downloadPath) | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | async function findDependencyGraphFiles(dir: string): Promise<string[]> { | 
		
	
	
		
			
				
					
					|  |  |  |   |