Skip to content

Commit

Permalink
Allow a task name to be specified for dependency-submission
Browse files Browse the repository at this point in the history
Fixes: #125
  • Loading branch information
bigdaz committed Apr 9, 2024
1 parent e235596 commit 92975d7
Show file tree
Hide file tree
Showing 8 changed files with 88 additions and 38 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/integ-test-dependency-submission.yml
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ jobs:
uses: ./dependency-submission
with:
build-root-directory: .github/workflow-samples/groovy-dsl
additional-arguments: --no-build-cache
dependency-resolution-task: assemble
- name: Check generated dependency graphs
shell: bash
run: |
Expand Down
7 changes: 7 additions & 0 deletions dependency-submission/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ name: Gradle Dependency Submission
description: Generates a dependency graph for a Gradle project and submits it via the Dependency Submission API

inputs:
# Gradle execution configuration
gradle-version:
description: |
Gradle version to use. If specified, this Gradle version will be downloaded, added to the PATH and used for invoking Gradle.
Expand All @@ -12,6 +13,12 @@ inputs:
description: Path to the root directory of the build. Default is the root of the GitHub workspace.
required: false

dependency-resolution-task:
description: |
Task(s) that should be executed in order to resolve all project dependencies.
By default, the built-in `:ForceDependencyResolutionPlugin_resolveAllDependencies` task is executed.
required: false

additional-arguments:
description: |
Additional arguments to pass to Gradle when generating the dependency graph.
Expand Down
25 changes: 23 additions & 2 deletions docs/dependency-submission.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,21 @@ jobs:
- name: Generate and submit dependency graph
uses: gradle/actions/dependency-submission@v3
```

### Gradle execution

To generate a dependency graph, the `dependency-submission` action must perform a Gradle execution that resolves
the dependencies of the project. All dependencies that are resolved in this execution will be included in the
generated dependency graph. By default action executes a built-in task that is designed to resolve all build dependencies
(`:ForceDependencyResolutionPlugin_resolveAllDependencies`).

The action looks for a Gradle project in the root of the workspace, and executes this project with
the Gradle wrapper, if configured for the project. If the wrapper is not configured, whatever `gradle` available
on the command-line will be used.

The action provides the ability to override the Gradle version and task to execute, as well as provide
additional arguments that will be passed to Gradle on the command-line. See [Configuration Parameters](#configuration-parameters) below.

### Publishing a Develocity Build Scan® from your dependency submission workflow

You can automatically publish a free Develocity Build Scan on every run of `gradle/actions/dependency-submission`.
Expand All @@ -64,8 +79,6 @@ A Build Scan makes it easy to determine the source of any dependency vulnerabili

In some cases, the default action configuration will not be sufficient, and additional action parameters will need to be specified.

See the example below for a summary, and the [Action Metadata file](action.yml) for a more detailed description of each input parameter.

```yaml
- name: Generate and save dependency graph
uses: gradle/actions/dependency-submission@v3
Expand All @@ -76,13 +89,21 @@ See the example below for a summary, and the [Action Metadata file](action.yml)
# The gradle project is not in the root of the repository.
build-root-directory: my-gradle-project

# Choose a task that will trigger dependency resolution
dependency-resolution-task: myDependencyResolutionTask

# Additional arguments that should be passed to execute Gradle
additonal-arguments: --no-configuration-cache

# Enable configuration-cache reuse for this build.
cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }}

# Do not attempt to submit the dependency-graph. Save it as a workflow artifact.
dependency-graph: generate-and-upload
```

See the [Action Metadata file](../dependency-submission/action.yml) for a more detailed description of each input parameter.

# Resolving a dependency vulnerability

## Finding the source of a dependency vulnerability
Expand Down
20 changes: 16 additions & 4 deletions sources/src/dependency-submission/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,13 @@ import * as gradle from '../execution/gradle'
import * as dependencyGraph from '../dependency-graph'

import {parseArgsStringToArgv} from 'string-argv'
import {BuildScanConfig, CacheConfig, DependencyGraphConfig, DependencyGraphOption} from '../input-params'
import {
BuildScanConfig,
CacheConfig,
DependencyGraphConfig,
DependencyGraphOption,
GradleExecutionConfig
} from '../input-params'

/**
* The main entry point for the action, called by Github Actions for the step.
Expand All @@ -25,16 +31,22 @@ export async function run(): Promise<void> {
}

// Only execute if arguments have been provided
const additionalArgs = core.getInput('additional-arguments')
const executionConfig = new GradleExecutionConfig()
const taskList = executionConfig.getDependencyResolutionTask()
const additionalArgs = executionConfig.getAdditionalArguments()
const executionArgs = `
-Dorg.gradle.configureondemand=false
-Dorg.gradle.dependency.verification=off
-Dorg.gradle.unsafe.isolated-projects=false
:ForceDependencyResolutionPlugin_resolveAllDependencies
${taskList}
${additionalArgs}
`
const args: string[] = parseArgsStringToArgv(executionArgs)
await gradle.provisionAndMaybeExecute(args)
await gradle.provisionAndMaybeExecute(
executionConfig.getGradleVersion(),
executionConfig.getBuildRootDirectory(),
args
)

await dependencyGraph.complete(config)
} catch (error) {
Expand Down
23 changes: 7 additions & 16 deletions sources/src/execution/gradle.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
import * as core from '@actions/core'
import * as exec from '@actions/exec'
import * as path from 'path'

import * as params from '../input-params'
import * as provisioner from './provision'
import * as gradlew from './gradlew'
import {getWorkspaceDirectory} from '../input-params'

export async function provisionAndMaybeExecute(args: string[]): Promise<void> {
export async function provisionAndMaybeExecute(
gradleVersion: string,
buildRootDirectory: string,
args: string[]
): Promise<void> {
// Download and install Gradle if required
const executable = await provisioner.provisionGradle()
const executable = await provisioner.provisionGradle(gradleVersion)

// Only execute if arguments have been provided
if (args.length > 0) {
await executeGradleBuild(executable, buildRootDirectory(), args)
await executeGradleBuild(executable, buildRootDirectory, args)
}
}

Expand All @@ -30,13 +31,3 @@ async function executeGradleBuild(executable: string | undefined, root: string,
core.setFailed(`Gradle build failed: see console output for details`)
}
}

function buildRootDirectory(): string {
const baseDirectory = getWorkspaceDirectory()
const buildRootDirectoryInput = params.getBuildRootDirectory()
const resolvedBuildRootDirectory =
buildRootDirectoryInput === ''
? path.resolve(baseDirectory)
: path.resolve(baseDirectory, buildRootDirectoryInput)
return resolvedBuildRootDirectory
}
4 changes: 1 addition & 3 deletions sources/src/execution/provision.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import * as cache from '@actions/cache'
import * as toolCache from '@actions/tool-cache'

import * as gradlew from './gradlew'
import * as params from '../input-params'
import {handleCacheFailure} from '../caching/cache-utils'
import {CacheConfig} from '../input-params'

Expand All @@ -17,8 +16,7 @@ const gradleVersionsBaseUrl = 'https://services.gradle.org/versions'
* Install any configured version of Gradle, adding the executable to the PATH.
* @return Installed Gradle executable or undefined if no version configured.
*/
export async function provisionGradle(): Promise<string | undefined> {
const gradleVersion = params.getGradleVersion()
export async function provisionGradle(gradleVersion: string): Promise<string | undefined> {
if (gradleVersion !== '' && gradleVersion !== 'wrapper') {
return addToPath(await installGradle(gradleVersion))
}
Expand Down
35 changes: 26 additions & 9 deletions sources/src/input-params.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import * as cache from '@actions/cache'
import {SUMMARY_ENV_VAR} from '@actions/core/lib/summary'

import {parseArgsStringToArgv} from 'string-argv'
import path from 'path'

export class DependencyGraphConfig {
getDependencyGraphOption(): DependencyGraphOption {
Expand Down Expand Up @@ -218,17 +219,33 @@ export class BuildScanConfig {
}
}

export function getGradleVersion(): string {
return core.getInput('gradle-version')
}
export class GradleExecutionConfig {
getGradleVersion(): string {
return core.getInput('gradle-version')
}

export function getBuildRootDirectory(): string {
return core.getInput('build-root-directory')
}
getBuildRootDirectory(): string {
const baseDirectory = getWorkspaceDirectory()
const buildRootDirectoryInput = core.getInput('build-root-directory')
const resolvedBuildRootDirectory =
buildRootDirectoryInput === ''
? path.resolve(baseDirectory)
: path.resolve(baseDirectory, buildRootDirectoryInput)
return resolvedBuildRootDirectory
}

export function getArguments(): string[] {
const input = core.getInput('arguments')
return parseArgsStringToArgv(input)
getArguments(): string[] {
const input = core.getInput('arguments')
return parseArgsStringToArgv(input)
}

getDependencyResolutionTask(): string {
return core.getInput('dependency-resolution-task') || ':ForceDependencyResolutionPlugin_resolveAllDependencies'
}

getAdditionalArguments(): string {
return core.getInput('additional-arguments')
}
}

// Internal parameters
Expand Down
10 changes: 7 additions & 3 deletions sources/src/setup-gradle/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import * as core from '@actions/core'
import * as setupGradle from '../setup-gradle'
import * as gradle from '../execution/gradle'
import * as dependencyGraph from '../dependency-graph'
import {BuildScanConfig, CacheConfig, DependencyGraphConfig, getArguments} from '../input-params'
import {BuildScanConfig, CacheConfig, DependencyGraphConfig, GradleExecutionConfig} from '../input-params'

/**
* The main entry point for the action, called by Github Actions for the step.
Expand All @@ -16,8 +16,12 @@ export async function run(): Promise<void> {
// Configure the dependency graph submission
await dependencyGraph.setup(new DependencyGraphConfig())

const args: string[] = getArguments()
await gradle.provisionAndMaybeExecute(args)
const config = new GradleExecutionConfig()
await gradle.provisionAndMaybeExecute(
config.getGradleVersion(),
config.getBuildRootDirectory(),
config.getArguments()
)
} catch (error) {
core.setFailed(String(error))
if (error instanceof Error && error.stack) {
Expand Down

0 comments on commit 92975d7

Please sign in to comment.