mirror of
https://github.com/gradle/actions.git
synced 2026-09-10 19:28:33 +08:00
Report EOL and maintenance status for Gradle versions
This commit is contained in:
@@ -6,6 +6,7 @@ export interface BuildResult {
|
||||
get rootProjectDir(): string
|
||||
get requestedTasks(): string
|
||||
get gradleVersion(): string
|
||||
get versionStatus(): string | undefined
|
||||
get gradleHomeDir(): string
|
||||
get buildFailed(): boolean
|
||||
get configCacheHit(): boolean
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
export class GradleVersion {
|
||||
static PATTERN = /((\d+)(\.\d+)+)(-([a-z]+)-(\w+))?(-(SNAPSHOT|\d{14}([-+]\d{4})?))?/
|
||||
|
||||
major: number
|
||||
versionPart: string
|
||||
stagePart: string
|
||||
snapshotPart: string
|
||||
|
||||
constructor(readonly version: string) {
|
||||
const matcher = GradleVersion.PATTERN.exec(version)
|
||||
if (!matcher) {
|
||||
throw new Error(`'${version}' is not a valid Gradle version string (examples: '1.0', '1.0-rc-1')`)
|
||||
}
|
||||
|
||||
this.major = Number(matcher[2])
|
||||
this.versionPart = matcher[1]
|
||||
this.stagePart = matcher[4]
|
||||
this.snapshotPart = matcher[7]
|
||||
}
|
||||
|
||||
isFinalRelease(): boolean {
|
||||
return !this.stagePart && !this.snapshotPart
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import which from 'which'
|
||||
import * as semver from 'semver'
|
||||
import * as provisioner from './provision'
|
||||
import * as gradlew from './gradlew'
|
||||
import {GradleVersion} from './gradle-version'
|
||||
|
||||
export async function provisionAndMaybeExecute(
|
||||
gradleVersion: string,
|
||||
@@ -90,22 +91,3 @@ export function parseGradleVersionFromOutput(output: string): string | undefined
|
||||
const versionString = output.match(regex)?.[1]
|
||||
return versionString
|
||||
}
|
||||
|
||||
class GradleVersion {
|
||||
static PATTERN = /((\d+)(\.\d+)+)(-([a-z]+)-(\w+))?(-(SNAPSHOT|\d{14}([-+]\d{4})?))?/
|
||||
|
||||
versionPart: string
|
||||
stagePart: string
|
||||
snapshotPart: string
|
||||
|
||||
constructor(readonly version: string) {
|
||||
const matcher = GradleVersion.PATTERN.exec(version)
|
||||
if (!matcher) {
|
||||
throw new Error(`'${version}' is not a valid Gradle version string (examples: '1.0', '1.0-rc-1')`)
|
||||
}
|
||||
|
||||
this.versionPart = matcher[1]
|
||||
this.stagePart = matcher[4]
|
||||
this.snapshotPart = matcher[7]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
import * as core from '@actions/core'
|
||||
|
||||
import {BuildResult} from './build-results'
|
||||
import {GradleVersion} from './execution/gradle-version'
|
||||
import wrapperChecksums from './wrapper-validation/wrapper-checksums.json'
|
||||
|
||||
const FEATURE_LIFECYCLE_DOC = 'https://docs.gradle.org/current/userguide/feature_lifecycle.html'
|
||||
|
||||
const LATEST_RELEASED_MAJOR = determineLatestReleasedMajor(wrapperChecksums.map(entry => entry.version))
|
||||
const LATEST_MAJOR_VERSION_ENV = 'GRADLE_ACTIONS_LATEST_GRADLE_MAJOR'
|
||||
|
||||
export function determineLatestReleasedMajor(versions: string[]): number | undefined {
|
||||
const releasedMajors = versions
|
||||
.map(version => new GradleVersion(version))
|
||||
.filter(parsed => parsed.isFinalRelease())
|
||||
.map(parsed => parsed.major)
|
||||
return releasedMajors.length > 0 ? Math.max(...releasedMajors) : undefined
|
||||
}
|
||||
|
||||
export function exportLatestReleasedMajor(): void {
|
||||
if (LATEST_RELEASED_MAJOR !== undefined) {
|
||||
core.exportVariable(LATEST_MAJOR_VERSION_ENV, LATEST_RELEASED_MAJOR)
|
||||
}
|
||||
}
|
||||
|
||||
export function reportSupportStatus(buildResults: BuildResult[]): void {
|
||||
if (LATEST_RELEASED_MAJOR === undefined) {
|
||||
return
|
||||
}
|
||||
|
||||
const statusByVersion = new Map<string, string>()
|
||||
for (const {gradleVersion, versionStatus} of buildResults) {
|
||||
if (versionStatus) {
|
||||
statusByVersion.set(gradleVersion, versionStatus)
|
||||
}
|
||||
}
|
||||
|
||||
for (const [gradleVersion, status] of statusByVersion) {
|
||||
const version = new GradleVersion(gradleVersion)
|
||||
switch (status) {
|
||||
case 'eol':
|
||||
core.warning(eolMessage(version, LATEST_RELEASED_MAJOR), {title: 'Gradle version at end-of-life'})
|
||||
break
|
||||
case 'maintenance':
|
||||
core.notice(maintenanceMessage(version, LATEST_RELEASED_MAJOR), {
|
||||
title: 'Gradle version in maintenance'
|
||||
})
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function eolMessage(version: GradleVersion, latestMajor: number): string {
|
||||
return `Gradle ${version.version} has reached end-of-life: the ${version.major}.x release line no longer receives bug fixes or security fixes. Gradle ${latestMajor}.x is the current release line, and upgrading is recommended. See ${FEATURE_LIFECYCLE_DOC}`
|
||||
}
|
||||
|
||||
function maintenanceMessage(version: GradleVersion, latestMajor: number): string {
|
||||
return `Gradle ${version.version} is in maintenance-only support: the ${version.major}.x release line receives critical bug fixes and security fixes only, and reaches end-of-life when Gradle ${latestMajor + 1} is released. Consider upgrading to Gradle ${latestMajor}.x. See ${FEATURE_LIFECYCLE_DOC}`
|
||||
}
|
||||
+18
@@ -15,6 +15,7 @@ settingsEvaluated { settings ->
|
||||
spec.getParameters().getRequestedTasks().set(gradle.startParameter.taskNames.join(" "))
|
||||
spec.getParameters().getGradleHomeDir().set(gradle.gradleHomeDir.absolutePath)
|
||||
spec.getParameters().getInvocationId().set(gradle.ext.invocationId)
|
||||
spec.getParameters().getVersionStatus().set(gradle.ext.gradleVersionStatus ?: "")
|
||||
})
|
||||
|
||||
gradle.services.get(BuildEventListenerRegistryInternal).onOperationCompletion(projectTracker)
|
||||
@@ -30,6 +31,7 @@ abstract class BuildResultsRecorder implements BuildService<BuildResultsRecorder
|
||||
Property<String> getRequestedTasks()
|
||||
Property<String> getGradleHomeDir()
|
||||
Property<String> getInvocationId()
|
||||
Property<String> getVersionStatus()
|
||||
}
|
||||
|
||||
void started(BuildOperationDescriptor buildOperation, OperationStartEvent startEvent) {}
|
||||
@@ -49,6 +51,16 @@ abstract class BuildResultsRecorder implements BuildService<BuildResultsRecorder
|
||||
}
|
||||
}
|
||||
|
||||
private static void setStepOutput(String name, String value) {
|
||||
def githubOutput = System.getenv("GITHUB_OUTPUT")
|
||||
if (githubOutput) {
|
||||
new File(githubOutput) << "${name}=${value}\n"
|
||||
} else {
|
||||
// Retained for compatibility with older GHES versions
|
||||
println("::set-output name=${name}::${value}")
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
def buildResults = [
|
||||
@@ -56,11 +68,17 @@ abstract class BuildResultsRecorder implements BuildService<BuildResultsRecorder
|
||||
rootProjectDir: getParameters().getRootProjectDir().get(),
|
||||
requestedTasks: getParameters().getRequestedTasks().get(),
|
||||
gradleVersion: GradleVersion.current().version,
|
||||
versionStatus: getParameters().getVersionStatus().getOrElse("") ?: null,
|
||||
gradleHomeDir: getParameters().getGradleHomeDir().get(),
|
||||
buildFailed: buildFailed,
|
||||
configCacheHit: configCacheHit
|
||||
]
|
||||
|
||||
def versionStatus = getParameters().getVersionStatus().getOrElse("")
|
||||
if (versionStatus) {
|
||||
setStepOutput("gradle-version-status", versionStatus)
|
||||
}
|
||||
|
||||
def runnerTempDir = System.getProperty("RUNNER_TEMP") ?: System.getenv("RUNNER_TEMP")
|
||||
def githubActionStep = System.getProperty("GITHUB_ACTION") ?: System.getenv("GITHUB_ACTION")
|
||||
if (!runnerTempDir || !githubActionStep) {
|
||||
|
||||
@@ -5,6 +5,7 @@ import org.gradle.util.GradleVersion
|
||||
import org.slf4j.LoggerFactory
|
||||
|
||||
def SKIP_BUILD_CAPTURE = "GRADLE_ACTIONS_SKIP_BUILD_RESULT_CAPTURE"
|
||||
def LATEST_GRADLE_MAJOR_ENV = "GRADLE_ACTIONS_LATEST_GRADLE_MAJOR"
|
||||
def BUILD_SCAN_PLUGIN_ID = "com.gradle.build-scan"
|
||||
def BUILD_SCAN_EXTENSION = "buildScan"
|
||||
def DEVELOCITY_PLUGIN_ID = "com.gradle.develocity"
|
||||
@@ -23,6 +24,8 @@ if (isTopLevelBuild) {
|
||||
def resultsWriter = new ResultsWriter()
|
||||
def version = GradleVersion.current().baseVersion
|
||||
|
||||
gradle.ext.gradleVersionStatus = supportStatusOf(version, System.getenv(LATEST_GRADLE_MAJOR_ENV))
|
||||
|
||||
def atLeastGradle3 = version >= GradleVersion.version("3.0")
|
||||
def atLeastGradle6 = version >= GradleVersion.version("6.0")
|
||||
def atLeastGradle7 = version >= GradleVersion.version("7.0")
|
||||
@@ -84,13 +87,46 @@ def captureUsingBuildService(invocationId) {
|
||||
apply from: 'gradle-actions.build-result-capture-service.plugin.groovy'
|
||||
}
|
||||
|
||||
String supportStatusOf(version, String latestGradleMajor) {
|
||||
def latestMajor = latestGradleMajor?.find(/^\d+$/)?.toInteger()
|
||||
def currentMajor = version.version.find(/^\d+/)?.toInteger()
|
||||
if (!latestMajor || !currentMajor) {
|
||||
return null
|
||||
}
|
||||
|
||||
switch (Math.max(0, latestMajor - currentMajor)) {
|
||||
case 0:
|
||||
return "active"
|
||||
case 1:
|
||||
return "maintenance"
|
||||
default:
|
||||
return "eol"
|
||||
}
|
||||
}
|
||||
|
||||
void setStepOutput(String name, String value) {
|
||||
def githubOutput = System.getenv("GITHUB_OUTPUT")
|
||||
if (githubOutput) {
|
||||
new File(githubOutput) << "${name}=${value}\n"
|
||||
} else {
|
||||
// Retained for compatibility with older GHES versions
|
||||
println("::set-output name=${name}::${value}")
|
||||
}
|
||||
}
|
||||
|
||||
void captureUsingBuildFinished(gradle, String invocationId, ResultsWriter resultsWriter) {
|
||||
gradle.buildFinished { result ->
|
||||
def versionStatus = gradle.ext.gradleVersionStatus
|
||||
if (versionStatus) {
|
||||
setStepOutput("gradle-version-status", versionStatus)
|
||||
}
|
||||
|
||||
def buildResults = [
|
||||
rootProjectName: rootProject.name,
|
||||
rootProjectDir: rootProject.projectDir.absolutePath,
|
||||
requestedTasks: gradle.startParameter.taskNames.join(" "),
|
||||
gradleVersion: GradleVersion.current().version,
|
||||
versionStatus: versionStatus,
|
||||
gradleHomeDir: gradle.gradleHomeDir.absolutePath,
|
||||
buildFailed: result.failure != null,
|
||||
configCacheHit: false
|
||||
@@ -110,13 +146,7 @@ void captureUsingBuildScanPublished(buildScanExtension, String invocationId, Res
|
||||
]
|
||||
resultsWriter.writeToResultsFile("build-scans", invocationId, scanResults)
|
||||
|
||||
def githubOutput = System.getenv("GITHUB_OUTPUT")
|
||||
if (githubOutput) {
|
||||
new File(githubOutput) << "build-scan-url=${buildScan.buildScanUri}\n"
|
||||
} else {
|
||||
// Retained for compatibility with older GHES versions
|
||||
println("::set-output name=build-scan-url::${buildScan.buildScanUri}")
|
||||
}
|
||||
setStepOutput("build-scan-url", buildScan.buildScanUri.toString())
|
||||
}
|
||||
|
||||
onError { error ->
|
||||
|
||||
@@ -19,6 +19,7 @@ import {
|
||||
} from './configuration'
|
||||
import * as wrapperValidator from './wrapper-validation/wrapper-validator'
|
||||
import {initializeGradleUserHome} from './gradle-user-home'
|
||||
import {exportLatestReleasedMajor, reportSupportStatus} from './gradle-support-status'
|
||||
|
||||
const GRADLE_SETUP_VAR = 'GRADLE_BUILD_ACTION_SETUP_COMPLETED'
|
||||
const GRADLE_USER_HOME = 'GRADLE_USER_HOME'
|
||||
@@ -46,6 +47,7 @@ export async function setup(
|
||||
core.saveState(GRADLE_USER_HOME, gradleUserHome)
|
||||
|
||||
initializeGradleUserHome(userHome, gradleUserHome, cacheConfig.getCacheEncryptionKey())
|
||||
exportLatestReleasedMajor()
|
||||
|
||||
// Exchange the long-lived access key(s) for short-lived tokens, resolving the token for the
|
||||
// configured Develocity server and retaining it for the post-action (save) step.
|
||||
@@ -89,6 +91,8 @@ export async function complete(
|
||||
|
||||
markBuildResultsProcessed()
|
||||
|
||||
reportSupportStatus(buildResults)
|
||||
|
||||
core.info('Completed post-action step')
|
||||
|
||||
return true
|
||||
|
||||
Reference in New Issue
Block a user