Compare commits

..

8 Commits

Author SHA1 Message Date
daz
a8f75513ea Build outputs 2024-01-23 16:12:23 -07:00
daz
9283312acb Add new option to clear dependency-graph
When changing workflow names or when changing to the new 'dependency-submission'
action, it can be useful to clear existing dependency graph snapshots from previous
submissions. While the old graphs will eventually "age out", the 'clear' option will
submit an empty dependency graph for an existing Job correlator, ensuring that old
dependency graphs don't linger.
2024-01-23 16:11:35 -07:00
daz
7c8a278ea0 Remove old clear-dependency-graph action 2024-01-23 15:07:13 -07:00
daz
d8ca9b7d2e Do full checks on release branches 2024-01-23 15:07:13 -07:00
daz
982da8e78c Attempt to make init-script compatible with Gradle 1.12
The `PluginManager` type wasn't introduced until Gradle 2.x.
Remove this type from the method signature in an attempt to allow this
file to be parsed with Gradle 1.12.
2023-12-19 14:12:27 -07:00
daz
a0fc8606d2 Build outputs 2023-12-19 14:08:34 -07:00
daz
a1980784de Improve reporting for dependency-graph failure
The previous message was assuming a permissions issue, and was not
including the underlying error message in the response.
2023-12-19 14:05:20 -07:00
Daz DeBoer
f95e9c7459 Clarify dependency-graph example 2023-12-12 10:48:54 -07:00
13 changed files with 78 additions and 48 deletions

View File

@@ -9,6 +9,7 @@ on:
push:
branches:
- main
- release/**
paths:
- '.github/**'
- 'dist/**'

View File

@@ -3,7 +3,9 @@ name: CI-quick-check
on:
workflow_dispatch:
push:
branches-ignore: main
branches-ignore:
- main
- release/**
jobs:
build-distribution:

View File

@@ -8,6 +8,7 @@ on:
push:
branches:
- main
- release/**
- dependabot/**
jobs:

View File

@@ -547,9 +547,9 @@ You enable GitHub Dependency Graph support by setting the `dependency-graph` act
| `generate-and-submit` | As per `generate`, but any generated dependency graph snapshots will be submitted at the end of the job. |
| `download-and-submit` | Download any previously saved dependency graph snapshots, submitting them via the Dependency Submission API. This can be useful to collect all snapshots in a matrix of builds and submit them in one step. |
Example of a simple workflow that generates and submits a dependency graph:
Example of a CI workflow that generates and submits a dependency graph:
```yaml
name: Submit dependency graph
name: CI build
on:
push:
@@ -565,11 +565,12 @@ jobs:
uses: gradle/gradle-build-action@v2
with:
dependency-graph: generate-and-submit
- name: Run a build and generate the dependency graph which will be submitted post-job
- name: Run the usual CI build (dependency-graph will be generated and submitted post-job)
run: ./gradlew build
```
The `contents: write` permission is not required to generate the dependency graph, but is required in order to submit the graph via the GitHub API. This permission will need to be explicitly enabled in the workflow file for dependency graph submission to succeed.
The `contents: write` permission is required in order to submit (but not generate) the dependency graph file.
Depending on [repository settings](https://docs.github.com/en/actions/security-guides/automatic-token-authentication#permissions-for-the-github_token), this permission may be available by default or may need to be explicitly enabled in the workflow file (as above).
> [!IMPORTANT]
> The above configuration will work for workflows that run as a result of commits to a repository branch,

View File

@@ -69,7 +69,7 @@ inputs:
default: true
dependency-graph:
description: Specifies if a GitHub dependency snapshot should be generated for each Gradle build, and if so, how. Valid values are 'disabled' (default), 'generate', 'generate-and-submit' and 'download-and-submit'.
description: Specifies if a GitHub dependency snapshot should be generated for each Gradle build, and if so, how. Valid values are 'disabled' (default), 'generate', 'generate-and-submit', 'download-and-submit' and 'clear'.
required: false
default: 'disabled'

View File

@@ -1,24 +0,0 @@
name: 'Clear dependency graph for a correlator'
inputs:
job-correlator:
required: true
runs:
using: "composite"
steps:
- name: Set current timestamp as env variable
shell: bash
run: echo "NOW=$(date -Iseconds)" >> $GITHUB_ENV
- name: Submit empty dependency graph
shell: bash
run: |
curl -L \
-X POST \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer ${{ github.token }}" \
-H "X-GitHub-Api-Version: 2022-11-28" \
https://api.github.com/repos/${{ github.repository }}/dependency-graph/snapshots \
-d '{ "version" : 0, "job" : { "id" : "${{ github.run_id }}", "correlator" : "${{ inputs.job-correlator }} " }, "sha" : "${{ github.sha }}", "ref" : "${{ github.ref }}", "detector" : { "name" : "GitHub Dependency Graph Gradle Plugin", "version" : "0.0.3", "url" : "https://github.com/gradle/github-dependency-graph-gradle-plugin" }, "manifests" : {}, "scanned" : "${{ env.NOW }}" }'
- run: echo "::notice ::Cleared dependency graph for job correlator '${{ inputs.job-correlator }}'"
shell: bash

24
dist/main/index.js vendored
View File

@@ -93650,6 +93650,10 @@ function setup(option) {
core.exportVariable('GITHUB_DEPENDENCY_GRAPH_SHA', getShaFromContext());
core.exportVariable('GITHUB_DEPENDENCY_GRAPH_WORKSPACE', layout.workspaceDirectory());
core.exportVariable('DEPENDENCY_GRAPH_REPORT_DIR', path.resolve(layout.workspaceDirectory(), 'dependency-graph-reports'));
if (option === input_params_1.DependencyGraphOption.Clear) {
core.exportVariable('DEPENDENCY_GRAPH_INCLUDE_PROJECTS', '');
core.exportVariable('DEPENDENCY_GRAPH_INCLUDE_CONFIGURATIONS', '');
}
});
}
exports.setup = setup;
@@ -93663,6 +93667,7 @@ function complete(option) {
yield uploadDependencyGraphs();
return;
case input_params_1.DependencyGraphOption.GenerateAndSubmit:
case input_params_1.DependencyGraphOption.Clear:
yield submitDependencyGraphs(yield uploadDependencyGraphs());
return;
}
@@ -93696,10 +93701,7 @@ function submitDependencyGraphs(dependencyGraphFiles) {
}
catch (error) {
if (error instanceof request_error_1.RequestError) {
const relativeJsonFile = getRelativePathFromWorkspace(jsonFile);
core.warning(`Failed to submit dependency graph ${relativeJsonFile}.\n` +
"Please ensure that the 'contents: write' permission is available for the workflow job.\n" +
"Note that this permission is never available for a 'pull_request' trigger from a repository fork.");
core.warning(buildWarningMessage(jsonFile, error));
}
else {
throw error;
@@ -93708,6 +93710,17 @@ function submitDependencyGraphs(dependencyGraphFiles) {
}
});
}
function buildWarningMessage(jsonFile, error) {
const relativeJsonFile = getRelativePathFromWorkspace(jsonFile);
const mainWarning = `Failed to submit dependency graph ${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.
Note that this permission is never available for a 'pull_request' trigger from a repository fork.
`;
}
return mainWarning;
}
function submitDependencyGraphFile(jsonFile) {
return __awaiter(this, void 0, void 0, function* () {
const octokit = getOctokit();
@@ -94069,6 +94082,8 @@ function getDependencyGraphOption() {
return DependencyGraphOption.GenerateAndSubmit;
case 'download-and-submit':
return DependencyGraphOption.DownloadAndSubmit;
case 'clear':
return DependencyGraphOption.Clear;
}
throw TypeError(`The value '${val} is not valid for 'dependency-graph. Valid values are: [disabled, generate-and-upload, generate-and-submit, download-and-submit]. The default value is 'disabled'.`);
}
@@ -94107,6 +94122,7 @@ var DependencyGraphOption;
DependencyGraphOption[DependencyGraphOption["Generate"] = 1] = "Generate";
DependencyGraphOption[DependencyGraphOption["GenerateAndSubmit"] = 2] = "GenerateAndSubmit";
DependencyGraphOption[DependencyGraphOption["DownloadAndSubmit"] = 3] = "DownloadAndSubmit";
DependencyGraphOption[DependencyGraphOption["Clear"] = 4] = "Clear";
})(DependencyGraphOption || (exports.DependencyGraphOption = DependencyGraphOption = {}));

File diff suppressed because one or more lines are too long

24
dist/post/index.js vendored
View File

@@ -93650,6 +93650,10 @@ function setup(option) {
core.exportVariable('GITHUB_DEPENDENCY_GRAPH_SHA', getShaFromContext());
core.exportVariable('GITHUB_DEPENDENCY_GRAPH_WORKSPACE', layout.workspaceDirectory());
core.exportVariable('DEPENDENCY_GRAPH_REPORT_DIR', path.resolve(layout.workspaceDirectory(), 'dependency-graph-reports'));
if (option === input_params_1.DependencyGraphOption.Clear) {
core.exportVariable('DEPENDENCY_GRAPH_INCLUDE_PROJECTS', '');
core.exportVariable('DEPENDENCY_GRAPH_INCLUDE_CONFIGURATIONS', '');
}
});
}
exports.setup = setup;
@@ -93663,6 +93667,7 @@ function complete(option) {
yield uploadDependencyGraphs();
return;
case input_params_1.DependencyGraphOption.GenerateAndSubmit:
case input_params_1.DependencyGraphOption.Clear:
yield submitDependencyGraphs(yield uploadDependencyGraphs());
return;
}
@@ -93696,10 +93701,7 @@ function submitDependencyGraphs(dependencyGraphFiles) {
}
catch (error) {
if (error instanceof request_error_1.RequestError) {
const relativeJsonFile = getRelativePathFromWorkspace(jsonFile);
core.warning(`Failed to submit dependency graph ${relativeJsonFile}.\n` +
"Please ensure that the 'contents: write' permission is available for the workflow job.\n" +
"Note that this permission is never available for a 'pull_request' trigger from a repository fork.");
core.warning(buildWarningMessage(jsonFile, error));
}
else {
throw error;
@@ -93708,6 +93710,17 @@ function submitDependencyGraphs(dependencyGraphFiles) {
}
});
}
function buildWarningMessage(jsonFile, error) {
const relativeJsonFile = getRelativePathFromWorkspace(jsonFile);
const mainWarning = `Failed to submit dependency graph ${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.
Note that this permission is never available for a 'pull_request' trigger from a repository fork.
`;
}
return mainWarning;
}
function submitDependencyGraphFile(jsonFile) {
return __awaiter(this, void 0, void 0, function* () {
const octokit = getOctokit();
@@ -93937,6 +93950,8 @@ function getDependencyGraphOption() {
return DependencyGraphOption.GenerateAndSubmit;
case 'download-and-submit':
return DependencyGraphOption.DownloadAndSubmit;
case 'clear':
return DependencyGraphOption.Clear;
}
throw TypeError(`The value '${val} is not valid for 'dependency-graph. Valid values are: [disabled, generate-and-upload, generate-and-submit, download-and-submit]. The default value is 'disabled'.`);
}
@@ -93975,6 +93990,7 @@ var DependencyGraphOption;
DependencyGraphOption[DependencyGraphOption["Generate"] = 1] = "Generate";
DependencyGraphOption[DependencyGraphOption["GenerateAndSubmit"] = 2] = "GenerateAndSubmit";
DependencyGraphOption[DependencyGraphOption["DownloadAndSubmit"] = 3] = "DownloadAndSubmit";
DependencyGraphOption[DependencyGraphOption["Clear"] = 4] = "Clear";
})(DependencyGraphOption || (exports.DependencyGraphOption = DependencyGraphOption = {}));

File diff suppressed because one or more lines are too long

View File

@@ -36,6 +36,12 @@ export async function setup(option: DependencyGraphOption): Promise<void> {
'DEPENDENCY_GRAPH_REPORT_DIR',
path.resolve(layout.workspaceDirectory(), 'dependency-graph-reports')
)
// To clear the dependency graph, we generate an empty graph by excluding all projects and configurations
if (option === DependencyGraphOption.Clear) {
core.exportVariable('DEPENDENCY_GRAPH_INCLUDE_PROJECTS', '')
core.exportVariable('DEPENDENCY_GRAPH_INCLUDE_CONFIGURATIONS', '')
}
}
export async function complete(option: DependencyGraphOption): Promise<void> {
@@ -47,6 +53,7 @@ export async function complete(option: DependencyGraphOption): Promise<void> {
await uploadDependencyGraphs()
return
case DependencyGraphOption.GenerateAndSubmit:
case DependencyGraphOption.Clear: // Submit the empty dependency graph
await submitDependencyGraphs(await uploadDependencyGraphs())
return
}
@@ -78,12 +85,7 @@ async function submitDependencyGraphs(dependencyGraphFiles: string[]): Promise<v
await submitDependencyGraphFile(jsonFile)
} catch (error) {
if (error instanceof RequestError) {
const relativeJsonFile = getRelativePathFromWorkspace(jsonFile)
core.warning(
`Failed to submit dependency graph ${relativeJsonFile}.\n` +
"Please ensure that the 'contents: write' permission is available for the workflow job.\n" +
"Note that this permission is never available for a 'pull_request' trigger from a repository fork."
)
core.warning(buildWarningMessage(jsonFile, error))
} else {
throw error
}
@@ -91,6 +93,18 @@ async function submitDependencyGraphs(dependencyGraphFiles: string[]): Promise<v
}
}
function buildWarningMessage(jsonFile: string, error: RequestError): string {
const relativeJsonFile = getRelativePathFromWorkspace(jsonFile)
const mainWarning = `Failed to submit dependency graph ${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.
Note that this permission is never available for a 'pull_request' trigger from a repository fork.
`
}
return mainWarning
}
async function submitDependencyGraphFile(jsonFile: string): Promise<void> {
const octokit = getOctokit()
const jsonContent = fs.readFileSync(jsonFile, 'utf8')

View File

@@ -82,6 +82,8 @@ export function getDependencyGraphOption(): DependencyGraphOption {
return DependencyGraphOption.GenerateAndSubmit
case 'download-and-submit':
return DependencyGraphOption.DownloadAndSubmit
case 'clear':
return DependencyGraphOption.Clear
}
throw TypeError(
`The value '${val} is not valid for 'dependency-graph. Valid values are: [disabled, generate-and-upload, generate-and-submit, download-and-submit]. The default value is 'disabled'.`
@@ -122,5 +124,6 @@ export enum DependencyGraphOption {
Disabled,
Generate,
GenerateAndSubmit,
DownloadAndSubmit
DownloadAndSubmit,
Clear
}

View File

@@ -168,7 +168,7 @@ if (GradleVersion.current() < GradleVersion.version('6.0')) {
}
}
void applyPluginExternally(PluginManager pluginManager, String pluginClassName) {
void applyPluginExternally(def pluginManager, String pluginClassName) {
def externallyApplied = 'gradle.enterprise.externally-applied'
def oldValue = System.getProperty(externallyApplied)
System.setProperty(externallyApplied, 'true')