Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve dependency graph failure handling #1036

Merged
merged 7 commits into from
Jan 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 5 additions & 0 deletions .github/workflows/ci-full-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ jobs:
with:
cache-key-prefix: ${{github.run_number}}-

dependency-graph-failures:
uses: ./.github/workflows/integ-test-dependency-graph-failures.yml
with:
cache-key-prefix: ${{github.run_number}}-

execution-with-caching:
uses: ./.github/workflows/integ-test-execution-with-caching.yml
with:
Expand Down
7 changes: 7 additions & 0 deletions .github/workflows/ci-quick-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,13 @@ jobs:
runner-os: '["ubuntu-latest"]'
download-dist: true

dependency-graph-failures:
needs: build-distribution
uses: ./.github/workflows/integ-test-dependency-graph-failures.yml
with:
runner-os: '["ubuntu-latest"]'
download-dist: true

execution-with-caching:
needs: build-distribution
uses: ./.github/workflows/integ-test-execution-with-caching.yml
Expand Down
103 changes: 103 additions & 0 deletions .github/workflows/integ-test-dependency-graph-failures.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
name: Test dependency graph

on:
workflow_call:
inputs:
cache-key-prefix:
type: string
runner-os:
type: string
default: '["ubuntu-latest"]'
download-dist:
type: boolean
default: false

env:
DOWNLOAD_DIST: ${{ inputs.download-dist }}
GRADLE_BUILD_ACTION_CACHE_KEY_PREFIX: dependency-graph-${{ inputs.cache-key-prefix }}
GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED: true

jobs:
unsupported-gradle-version-warning:
runs-on: ubuntu-latest
steps:
- name: Checkout sources
uses: actions/checkout@v4
- name: Download distribution if required
uses: ./.github/actions/download-dist
- name: Setup Gradle for dependency-graph generate
uses: ./
with:
gradle-version: 7.0.1
dependency-graph: generate
dependency-graph-continue-on-failure: true
- name: Run with unsupported Gradle version
working-directory: .github/workflow-samples/groovy-dsl
run: |
if gradle help | grep -q 'warning::Dependency Graph is not supported for Gradle 7.0.1. No dependency snapshot will be generated.';
then
echo "Got the expected warning"
else
echo "Did not get the expected warning"
exit 1
fi

unsupported-gradle-version-failure:
runs-on: ubuntu-latest
steps:
- name: Checkout sources
uses: actions/checkout@v4
- name: Download distribution if required
uses: ./.github/actions/download-dist
- name: Setup Gradle for dependency-graph generate
uses: ./
with:
gradle-version: 7.0.1
dependency-graph: generate
dependency-graph-continue-on-failure: false
- name: Run with unsupported Gradle version
working-directory: .github/workflow-samples/groovy-dsl
run: |
if gradle help; then
echo "Expected build to fail with Gradle 7.0.1"
exit 1
fi

insufficient-permissions-warning:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout sources
uses: actions/checkout@v4
- name: Download distribution if required
uses: ./.github/actions/download-dist
- name: Setup Gradle for dependency-graph generate
uses: ./
with:
dependency-graph: generate-and-submit
dependency-graph-continue-on-failure: true
- name: Run with insufficient permissions
working-directory: .github/workflow-samples/groovy-dsl
run: ./gradlew help
# This test is primarily for demonstration: it's unclear how to check for warnings emitted in the post-action

SHOULD_FAIL-insufficient-permissions-failure:
runs-on: ubuntu-latest
permissions:
contents: read
continue-on-error: true
steps:
- name: Checkout sources
uses: actions/checkout@v4
- name: Download distribution if required
uses: ./.github/actions/download-dist
- name: Setup Gradle for dependency-graph generate
uses: ./
with:
dependency-graph: generate-and-submit
dependency-graph-continue-on-failure: false
- name: Run with insufficient permissions
working-directory: .github/workflow-samples/groovy-dsl
run: ./gradlew help
# This test is primarily for demonstration: it's unclear how to check for a failure in the post-action
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -512,6 +512,22 @@ Depending on [repository settings](https://docs.github.com/en/actions/security-g
> for a PR submitted from a forked repository.
> For a configuration that supports this setup, see [Dependency Graphs for pull request workflows](#dependency-graphs-for-pull-request-workflows).

### Making dependency graph failures cause Job failures

By default, if a failure is encountered when generating or submitting the dependency graph, the action will log the failure as a warning and continue.
This allows your workflow to be resilient to dependency graph failures, in case dependency graph production is a side-effect rather than the primary purpose of a workflow.

If instead you have a workflow that has a primary purpose to generate and submit a dependency graph, then it makes sense for this workflow to fail if the dependency
graph cannot be generated or submitted. You can enable this behaviour with the `dependency-graph-continue-on-failure` parameter, which defaults to `true`.

```yaml
# Ensure that the workflow Job will fail if the dependency graph cannot be submitted
- uses: gradle/gradle-build-action@v3
with:
dependency-graph: generate-and-submit
dependency-graph-continue-on-failure: false
```

### Using a custom plugin repository

By default, the action downloads the `github-dependency-graph-gradle-plugin` from the Gradle Plugin Portal (https://plugins.gradle.org). If your GitHub Actions environment does not have access to this URL, you can specify a custom plugin repository to use.
Expand Down
5 changes: 5 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,11 @@ inputs:
required: false
default: 'disabled'

dependency-graph-continue-on-failure:
description: When 'false' a failure to generate or submit a dependency graph will fail the Step or Job. When 'true' a warning will be emitted but no failure will result.
required: false
default: true

artifact-retention-days:
description: Specifies the number of days to retain any artifacts generated by the action. If not set, the default retention settings for the repository will apply.
required: false
Expand Down
48 changes: 42 additions & 6 deletions dist/main/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -139971,6 +139971,7 @@ const request_error_1 = __nccwpck_require__(10537);
const path = __importStar(__nccwpck_require__(71017));
const fs_1 = __importDefault(__nccwpck_require__(57147));
const layout = __importStar(__nccwpck_require__(28182));
const errors_1 = __nccwpck_require__(36976);
const input_params_1 = __nccwpck_require__(23885);
const DEPENDENCY_GRAPH_PREFIX = 'dependency-graph_';
function setup(option) {
Expand All @@ -139984,6 +139985,7 @@ function setup(option) {
}
core.info('Enabling dependency graph generation');
core.exportVariable('GITHUB_DEPENDENCY_GRAPH_ENABLED', 'true');
core.exportVariable('GITHUB_DEPENDENCY_GRAPH_CONTINUE_ON_FAILURE', (0, input_params_1.getDependencyGraphContinueOnFailure)());
core.exportVariable('GITHUB_DEPENDENCY_GRAPH_JOB_CORRELATOR', getJobCorrelator());
core.exportVariable('GITHUB_DEPENDENCY_GRAPH_JOB_ID', github.context.runId);
core.exportVariable('GITHUB_DEPENDENCY_GRAPH_REF', github.context.ref);
Expand All @@ -140009,7 +140011,7 @@ function complete(option) {
}
}
catch (e) {
core.warning(`Failed to ${option} dependency graph. Will continue. ${String(e)}`);
warnOrFail(option, e);
}
});
}
Expand Down Expand Up @@ -140040,7 +140042,7 @@ function downloadAndSubmitDependencyGraphs() {
yield submitDependencyGraphs(yield downloadDependencyGraphs());
}
catch (e) {
core.warning(`Download and submit dependency graph failed. Will continue. ${String(e)}`);
warnOrFail(input_params_1.DependencyGraphOption.DownloadAndSubmit, e);
}
});
}
Expand All @@ -140052,7 +140054,7 @@ function submitDependencyGraphs(dependencyGraphFiles) {
}
catch (error) {
if (error instanceof request_error_1.RequestError) {
core.warning(buildWarningMessage(jsonFile, error));
throw new Error(translateErrorMessage(jsonFile, error));
}
else {
throw error;
Expand All @@ -140061,9 +140063,9 @@ function submitDependencyGraphs(dependencyGraphFiles) {
}
});
}
function buildWarningMessage(jsonFile, error) {
function translateErrorMessage(jsonFile, error) {
const relativeJsonFile = getRelativePathFromWorkspace(jsonFile);
const mainWarning = `Failed to submit dependency graph ${relativeJsonFile}.\n${String(error)}`;
const mainWarning = `Dependency submission failed for ${relativeJsonFile}.\n${String(error)}`;
if (error.message === 'Resource not accessible by integration') {
return `${mainWarning}
Please ensure that the 'contents: write' permission is available for the workflow job.
Expand Down Expand Up @@ -140118,6 +140120,12 @@ function findDependencyGraphFiles(dir) {
return graphFiles;
});
}
function warnOrFail(option, error) {
if (!(0, input_params_1.getDependencyGraphContinueOnFailure)()) {
throw new errors_1.PostActionJobFailure(error);
}
core.warning(`Failed to ${option} dependency graph. Will continue.\n${String(error)}`);
}
function getOctokit() {
return github.getOctokit(getGithubToken());
}
Expand Down Expand Up @@ -140169,6 +140177,30 @@ function sanitize(value) {
}


/***/ }),

/***/ 36976:
/***/ ((__unused_webpack_module, exports) => {

"use strict";

Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.PostActionJobFailure = void 0;
class PostActionJobFailure extends Error {
constructor(error) {
if (error instanceof Error) {
super(error.message);
this.name = error.name;
this.stack = error.stack;
}
else {
super(String(error));
}
}
}
exports.PostActionJobFailure = PostActionJobFailure;


/***/ }),

/***/ 23584:
Expand Down Expand Up @@ -140332,7 +140364,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
return result;
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.JobSummaryOption = exports.DependencyGraphOption = exports.parseNumericInput = exports.getArtifactRetentionDays = exports.getDependencyGraphOption = exports.getPRCommentOption = exports.getJobSummaryOption = exports.isJobSummaryEnabled = exports.getGithubToken = exports.getJobMatrix = exports.getArguments = exports.getGradleVersion = exports.getBuildRootDirectory = exports.getCacheExcludes = exports.getCacheIncludes = exports.getCacheEncryptionKey = exports.isCacheCleanupEnabled = exports.isCacheDebuggingEnabled = exports.isCacheStrictMatch = exports.isCacheOverwriteExisting = exports.isCacheWriteOnly = exports.isCacheReadOnly = exports.isCacheDisabled = void 0;
exports.JobSummaryOption = exports.DependencyGraphOption = exports.parseNumericInput = exports.getArtifactRetentionDays = exports.getDependencyGraphContinueOnFailure = exports.getDependencyGraphOption = exports.getPRCommentOption = exports.getJobSummaryOption = exports.isJobSummaryEnabled = exports.getGithubToken = exports.getJobMatrix = exports.getArguments = exports.getGradleVersion = exports.getBuildRootDirectory = exports.getCacheExcludes = exports.getCacheIncludes = exports.getCacheEncryptionKey = exports.isCacheCleanupEnabled = exports.isCacheDebuggingEnabled = exports.isCacheStrictMatch = exports.isCacheOverwriteExisting = exports.isCacheWriteOnly = exports.isCacheReadOnly = exports.isCacheDisabled = void 0;
const core = __importStar(__nccwpck_require__(42186));
const string_argv_1 = __nccwpck_require__(19663);
function isCacheDisabled() {
Expand Down Expand Up @@ -140437,6 +140469,10 @@ function getDependencyGraphOption() {
throw TypeError(`The value '${val}' is not valid for 'dependency-graph'. Valid values are: [disabled, generate, generate-and-submit, generate-and-upload, download-and-submit]. The default value is 'disabled'.`);
}
exports.getDependencyGraphOption = getDependencyGraphOption;
function getDependencyGraphContinueOnFailure() {
return getBooleanInput('dependency-graph-continue-on-failure', true);
}
exports.getDependencyGraphContinueOnFailure = getDependencyGraphContinueOnFailure;
function getArtifactRetentionDays() {
const val = core.getInput('artifact-retention-days');
return parseNumericInput('artifact-retention-days', val, 0);
Expand Down
2 changes: 1 addition & 1 deletion dist/main/index.js.map

Large diffs are not rendered by default.