mirror of
https://github.com/gradle/gradle-build-action.git
synced 2025-10-19 22:38:58 +08:00
Compare commits
5 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
4e899835b3 | ||
|
3812292b26 | ||
|
c12283ec57 | ||
|
f2dc0d8256 | ||
|
717db318c1 |
70
.github/workflows/codeql-analysis.yml
vendored
Normal file
70
.github/workflows/codeql-analysis.yml
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
# For most projects, this workflow file will not need changing; you simply need
|
||||
# to commit it to your repository.
|
||||
#
|
||||
# You may wish to alter this file to override the set of languages analyzed,
|
||||
# or to provide custom queries or build logic.
|
||||
#
|
||||
# ******** NOTE ********
|
||||
# We have attempted to detect the languages in your repository. Please check
|
||||
# the `language` matrix defined below to confirm you have the correct set of
|
||||
# supported CodeQL languages.
|
||||
#
|
||||
name: "CodeQL"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
pull_request:
|
||||
# The branches below must be a subset of the branches above
|
||||
branches: [ main ]
|
||||
schedule:
|
||||
- cron: '25 23 * * 2'
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
security-events: write
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
language: [ 'javascript' ]
|
||||
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
|
||||
# Learn more about CodeQL language support at https://git.io/codeql-language-support
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v1
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
# By default, queries listed here will override any specified in a config file.
|
||||
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||
# queries: ./path/to/local/query, your-org/your-repo/queries@main
|
||||
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v1
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 https://git.io/JvXDl
|
||||
|
||||
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
|
||||
# and modify them (or add more) to build your code if your project
|
||||
# uses a compiled language
|
||||
|
||||
#- run: |
|
||||
# make bootstrap
|
||||
# make release
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v1
|
46
README.md
46
README.md
@@ -39,6 +39,19 @@ Each invocation will start its run with the filesystem state remaining from the
|
||||
arguments: check
|
||||
```
|
||||
|
||||
### Why is this better than running Gradle directly?
|
||||
|
||||
It is possible to directly invoke Gradle in your workflow, and the `setup-java` action provides a simple way to cache Gradle dependencies.
|
||||
|
||||
However, the `gradle-build-action` offers a number of advantages over this approach:
|
||||
|
||||
- Easily [run the build with different versions of Gradle](#download-install-and-use-a-specific-gradle-version) using the `gradle-version` parameter. Gradle distributions are automatically downloaded and cached.
|
||||
- More sophisticated and more efficient caching of Gradle User Home between invocations, compared to `setup-java` and most custom configurations using `actions/cache`. [More details below](#caching).
|
||||
- Detailed reporting of cache usage and cache configuration options allow you to [optimize the use of the GitHub actions cache](#optimizing-cache-effectiveness).
|
||||
- [Automatic capture of build scan links](#build-scans) from the build, making these easier to locate for workflow run.
|
||||
|
||||
The `gradle-build-action` is designed to provide these benefits with minimal configuration.
|
||||
|
||||
## Gradle Execution
|
||||
|
||||
### Command-line arguments
|
||||
@@ -158,7 +171,7 @@ cache-disabled: true
|
||||
|
||||
### Cache keys
|
||||
|
||||
For cached distributions outside of Gradle User Home, the cache key is unique to the downloaded distribution. This will not change over time.
|
||||
For distributions downloaded to satisfy a `gradle-version` parametere are stored outside of Gradle User Home and cached separately. The cache key is unique to the downloaded distribution and will not change over time.
|
||||
|
||||
The state of the Gradle User Home and configuration-cache are highly dependent on the Gradle execution, so the cache key is composed of the current commit hash and the GitHub actions job id.
|
||||
As such, the cache key is likely to change on each subsequent run of GitHub actions.
|
||||
@@ -170,7 +183,6 @@ For example, this means that all jobs executing a particular version of the Grad
|
||||
|
||||
### Using the caches read-only
|
||||
|
||||
Cache storage space is limited for GitHub actions, and writing new cache entries can trigger the deletion of exising entries.
|
||||
In some circumstances, it makes sense for a Gradle invocation to read any existing cache entries but not to write changes back.
|
||||
For example, you may want to write cache entries for builds on your `main` branch, but not for any PR build invocations.
|
||||
|
||||
@@ -202,7 +214,12 @@ gradle-home-cache-excludes: |
|
||||
You can specify any number of fixed paths or patterns to include or exclude.
|
||||
File pattern support is documented at https://docs.github.com/en/actions/learn-github-actions/workflow-syntax-for-github-actions#patterns-to-match-file-paths.
|
||||
|
||||
### Cache debugging
|
||||
### Cache debugging and analysis
|
||||
|
||||
Gradle User Home state will be restored from the cache during the first `gradle-build-action` step for any workflow job.
|
||||
This state will be saved back to the cache at the end of the job, after all Gradle executions have completed.
|
||||
A report of all cache entries restored and saved is printed to the action log when saving the cache entries.
|
||||
This report can provide valuable insignt into how much cache space is being used.
|
||||
|
||||
It is possible to enable additional debug logging for cache operations. You do via the `GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED` environment variable:
|
||||
|
||||
@@ -213,6 +230,29 @@ env:
|
||||
|
||||
Note that this setting will also prevent certain cache operations from running in parallel, further assisting with debugging.
|
||||
|
||||
### Optimizing cache effectiveness
|
||||
|
||||
Cache storage space for GitHub actions is limited, and writing new cache entries can trigger the deletion of exising entries.
|
||||
Eviction of shared cache entries can reduce cache effectiveness, slowing down your `gradle-build-action` steps.
|
||||
|
||||
There are a number of actions you can take if your cache use is less effective due to entry eviction.
|
||||
|
||||
#### Only write to the cache from the default branch
|
||||
|
||||
GitHub cache entries are not shared between builds on different branches. This means that identical cache entries will be stored separately for different branches.
|
||||
The exception to the is cache entries for the default (`master`/`main`) branch can be read by actions invoked for other branches.
|
||||
|
||||
An easy way to reduce cache usage when you run builds on many different branches is to only permit your default branch to write to the cache,
|
||||
with all other branch builds using `cache-read-only`. See [Using the caches read-only](#using-the-caches-read-only) for more details.
|
||||
|
||||
Similarly, you could use `cache-read-only` for certain jobs in the workflow, and instead have these jobs reuse the cache content from upstream jobs.
|
||||
|
||||
#### Exclude content from Gradle User Home cache
|
||||
|
||||
Each build is different, and some builds produce more Gradle User Home content than others.
|
||||
[Cache debugging ](#cache-debugging-and-analysis) can provide insight into which cache entries are the largest,
|
||||
and you can selectively [exclude content using `gradle-home-cache-exclude`](#gradle-user-home-cache-tuning).
|
||||
|
||||
## Build scans
|
||||
|
||||
If your build publishes a [build scan](https://gradle.com/build-scans/) the `gradle-build-action` action will:
|
||||
|
2
dist/main/index.js
vendored
2
dist/main/index.js
vendored
File diff suppressed because one or more lines are too long
2
dist/main/index.js.map
vendored
2
dist/main/index.js.map
vendored
File diff suppressed because one or more lines are too long
2
dist/post/index.js
vendored
2
dist/post/index.js
vendored
File diff suppressed because one or more lines are too long
2
dist/post/index.js.map
vendored
2
dist/post/index.js.map
vendored
File diff suppressed because one or more lines are too long
@@ -1,7 +1,7 @@
|
||||
import * as core from '@actions/core'
|
||||
import * as cache from '@actions/cache'
|
||||
import * as github from '@actions/github'
|
||||
import {isCacheDebuggingEnabled, getCacheKeyPrefix, hashStrings} from './cache-utils'
|
||||
import {isCacheDebuggingEnabled, getCacheKeyPrefix, hashStrings, handleCacheFailure} from './cache-utils'
|
||||
|
||||
const JOB_CONTEXT_PARAMETER = 'workflow-job-context'
|
||||
|
||||
@@ -150,9 +150,9 @@ export abstract class AbstractCache {
|
||||
return
|
||||
}
|
||||
|
||||
core.saveState(this.cacheResultStateKey, cacheResult)
|
||||
core.saveState(this.cacheResultStateKey, cacheResult.key)
|
||||
entryReport.markRestored(cacheResult.key, cacheResult.size)
|
||||
core.info(`Restored ${this.cacheDescription} from cache key: ${cacheResult}`)
|
||||
core.info(`Restored ${this.cacheDescription} from cache key: ${cacheResult.key}`)
|
||||
|
||||
try {
|
||||
await this.afterRestore(listener)
|
||||
@@ -176,12 +176,7 @@ export abstract class AbstractCache {
|
||||
try {
|
||||
return await cache.restoreCache(cachePath, cacheKey, cacheRestoreKeys)
|
||||
} catch (error) {
|
||||
if (error instanceof cache.ValidationError) {
|
||||
// Validation errors should fail the build action
|
||||
throw error
|
||||
}
|
||||
// Warn about any other error and continue
|
||||
core.warning(`Failed to restore ${cacheKey}: ${error}`)
|
||||
handleCacheFailure(error, `Failed to restore ${cacheKey}`)
|
||||
return undefined
|
||||
}
|
||||
}
|
||||
@@ -231,16 +226,7 @@ export abstract class AbstractCache {
|
||||
try {
|
||||
return await cache.saveCache(cachePath, cacheKey)
|
||||
} catch (error) {
|
||||
if (error instanceof cache.ValidationError) {
|
||||
// Validation errors should fail the build action
|
||||
throw error
|
||||
} else if (error instanceof cache.ReserveCacheError) {
|
||||
// Reserve cache errors are expected if the artifact has been previously cached
|
||||
this.debug(error.message)
|
||||
} else {
|
||||
// Warn about any other error and continue
|
||||
core.warning(String(error))
|
||||
}
|
||||
handleCacheFailure(error, `Failed to save cache entry ${cacheKey}`)
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
|
@@ -1,4 +1,5 @@
|
||||
import * as core from '@actions/core'
|
||||
import * as cache from '@actions/cache'
|
||||
import * as crypto from 'crypto'
|
||||
import * as path from 'path'
|
||||
import * as fs from 'fs'
|
||||
@@ -39,6 +40,24 @@ export function hashFileNames(fileNames: string[]): string {
|
||||
return hashStrings(fileNames.map(x => x.replace(new RegExp(`\\${path.sep}`, 'g'), '/')))
|
||||
}
|
||||
|
||||
export function handleCacheFailure(error: unknown, message: string): void {
|
||||
if (error instanceof cache.ValidationError) {
|
||||
// Fail on cache validation errors
|
||||
throw error
|
||||
}
|
||||
if (error instanceof cache.ReserveCacheError) {
|
||||
// Reserve cache errors are expected if the artifact has been previously cached
|
||||
if (isCacheDebuggingEnabled()) {
|
||||
core.info(message)
|
||||
} else {
|
||||
core.debug(message)
|
||||
}
|
||||
} else {
|
||||
// Warn on all other errors
|
||||
core.warning(`${message}: ${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to delete a file or directory, waiting to allow locks to be released
|
||||
*/
|
||||
|
@@ -7,7 +7,7 @@ import * as cache from '@actions/cache'
|
||||
import * as toolCache from '@actions/tool-cache'
|
||||
|
||||
import * as gradlew from './gradlew'
|
||||
import {isCacheDisabled, isCacheReadOnly} from './cache-utils'
|
||||
import {handleCacheFailure, isCacheDisabled, isCacheReadOnly} from './cache-utils'
|
||||
|
||||
const gradleVersionsBaseUrl = 'https://services.gradle.org/versions'
|
||||
|
||||
@@ -109,11 +109,16 @@ async function downloadAndCacheGradleDistribution(versionInfo: GradleVersionInfo
|
||||
}
|
||||
|
||||
const cacheKey = `gradle-${versionInfo.version}`
|
||||
const restoreKey = await cache.restoreCache([downloadPath], cacheKey)
|
||||
if (restoreKey) {
|
||||
core.info(`Restored Gradle distribution ${cacheKey} from cache to ${downloadPath}`)
|
||||
return downloadPath
|
||||
try {
|
||||
const restoreKey = await cache.restoreCache([downloadPath], cacheKey)
|
||||
if (restoreKey) {
|
||||
core.info(`Restored Gradle distribution ${cacheKey} from cache to ${downloadPath}`)
|
||||
return downloadPath
|
||||
}
|
||||
} catch (error) {
|
||||
handleCacheFailure(error, `Restore Gradle distribution ${versionInfo.version} failed`)
|
||||
}
|
||||
|
||||
core.info(`Gradle distribution ${versionInfo.version} not found in cache. Will download.`)
|
||||
await downloadGradleDistribution(versionInfo, downloadPath)
|
||||
|
||||
@@ -121,11 +126,7 @@ async function downloadAndCacheGradleDistribution(versionInfo: GradleVersionInfo
|
||||
try {
|
||||
await cache.saveCache([downloadPath], cacheKey)
|
||||
} catch (error) {
|
||||
// Fail on validation errors or non-errors (the latter to keep Typescript happy)
|
||||
if (error instanceof cache.ValidationError || !(error instanceof Error)) {
|
||||
throw error
|
||||
}
|
||||
core.warning(error.message)
|
||||
handleCacheFailure(error, `Save Gradle distribution ${versionInfo.version} failed`)
|
||||
}
|
||||
}
|
||||
return downloadPath
|
||||
|
Reference in New Issue
Block a user