Simplify version status reporting: drop the output and move the check back to post-job

This commit is contained in:
Vlad Chesnokov
2026-08-26 12:59:43 +02:00
parent dfc644bc4a
commit 78c57b83ad
14 changed files with 113 additions and 226 deletions
+1
View File
@@ -47,6 +47,7 @@ jobs:
other-integ-tests: other-integ-tests:
permissions: permissions:
contents: write contents: write
actions: read
needs: caching-integ-tests needs: caching-integ-tests
uses: ./.github/workflows/suite-integ-test-other.yml uses: ./.github/workflows/suite-integ-test-other.yml
concurrency: concurrency:
@@ -18,14 +18,27 @@ permissions:
contents: read contents: read
jobs: jobs:
report-version-status: report-outdated-versions:
runs-on: ubuntu-latest runs-on: ubuntu-latest
outputs:
maintenance-version: ${{ steps.maintenance-version.outputs.version }}
steps: steps:
- name: Checkout sources - name: Checkout sources
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Initialize integ-test - name: Initialize integ-test
uses: ./.github/actions/init-integ-test uses: ./.github/actions/init-integ-test
- name: Determine the maintenance-only Gradle version
id: maintenance-version
run: |
version=$(jq -r '
[.[].version | select(test("^[0-9]+\\.[0-9]+(\\.[0-9]+)?$"))] as $finals
| ($finals | map(split(".")[0] | tonumber) | max) as $latest
| [$finals[] | select((split(".")[0] | tonumber) == ($latest - 1))] | first
' sources/src/wrapper-validation/wrapper-checksums.json)
echo "Newest release in the maintenance-only line: $version"
echo "version=$version" >> "$GITHUB_OUTPUT"
- name: Setup Gradle with an end-of-life version - name: Setup Gradle with an end-of-life version
uses: ./setup-gradle uses: ./setup-gradle
with: with:
@@ -36,25 +49,46 @@ jobs:
working-directory: .github/workflow-samples/no-wrapper working-directory: .github/workflow-samples/no-wrapper
run: gradle help "-DgradleVersionCheck=7.6.4" run: gradle help "-DgradleVersionCheck=7.6.4"
- name: Setup Gradle with the current version - name: Setup Gradle with the maintenance-only version
uses: ./setup-gradle uses: ./setup-gradle
with: with:
gradle-version: current gradle-version: ${{ steps.maintenance-version.outputs.version }}
- name: Build with the current version - name: Build with the maintenance-only version
id: build-current
working-directory: .github/workflow-samples/no-wrapper working-directory: .github/workflow-samples/no-wrapper
run: gradle help run: gradle help "-DgradleVersionCheck=${{ steps.maintenance-version.outputs.version }}"
- name: Check the end-of-life version was reported as 'eol' verify-annotations:
if: ${{ steps.build-end-of-life.outputs.gradle-version-status != 'eol' }} needs: report-outdated-versions
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 runs-on: ubuntu-latest
with: permissions:
script: | contents: read
core.setFailed("Expected Gradle 7.6.4 to be reported as 'eol', but was '${{ steps.build-end-of-life.outputs.gradle-version-status }}'") actions: read
steps:
- name: Check the support-status annotations were emitted
env:
GH_TOKEN: ${{ github.token }}
MAINTENANCE_VERSION: ${{ needs.report-outdated-versions.outputs.maintenance-version }}
run: |
set -euo pipefail
- name: Check the current version was reported as 'active' job_id=$(gh api \
if: ${{ steps.build-current.outputs.gradle-version-status != 'active' }} "/repos/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}/attempts/${GITHUB_RUN_ATTEMPT}/jobs" \
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 --paginate --jq '.jobs[] | select(.name | endswith("report-outdated-versions")) | .id')
with: if [ -z "$job_id" ]; then
script: | echo "Could not find the 'report-outdated-versions' Job in this workflow run"
core.setFailed("Expected the current Gradle version to be reported as 'active', but was '${{ steps.build-current.outputs.gradle-version-status }}'") exit 1
fi
gh api --allow-escape-sequences "/repos/${GITHUB_REPOSITORY}/actions/jobs/${job_id}/logs" > job.log
# The runner renders '::warning::'/'::notice::' commands into the log as '##[warning]'/'##[notice]'.
assert_logged() {
if ! grep -qF -- "$1" job.log; then
echo "Expected the Job log to contain: $1"
echo "Annotations found instead:"
grep -E '##\[(warning|notice)\]' job.log || echo "(none)"
exit 1
fi
}
assert_logged "##[warning]Gradle 7.6.4 has reached end-of-life"
assert_logged "##[notice]Gradle ${MAINTENANCE_VERSION} is in maintenance-only support"
@@ -29,6 +29,9 @@ jobs:
DEVELOCITY_ACCESS_KEY: ${{ secrets.DV_SOLUTIONS_ACCESS_KEY }} DEVELOCITY_ACCESS_KEY: ${{ secrets.DV_SOLUTIONS_ACCESS_KEY }}
gradle-support-status: gradle-support-status:
permissions:
contents: read
actions: read
uses: ./.github/workflows/integ-test-gradle-support-status.yml uses: ./.github/workflows/integ-test-gradle-support-status.yml
with: with:
skip-dist: ${{ inputs.skip-dist }} skip-dist: ${{ inputs.skip-dist }}
-3
View File
@@ -156,6 +156,3 @@ outputs:
gradle-version: gradle-version:
type: string type: string
gradle-version-status:
type: string
+1 -5
View File
@@ -229,11 +229,7 @@ outputs:
description: Path to the GitHub Dependency Graph snapshot file generated by a Gradle build. Note that this output applies to a Step executing Gradle, not to the `setup-gradle` Step itself. description: Path to the GitHub Dependency Graph snapshot file generated by a Gradle build. Note that this output applies to a Step executing Gradle, not to the `setup-gradle` Step itself.
gradle-version: gradle-version:
description: Version of Gradle that was setup by the action description: Version of Gradle that was setup by the action
gradle-version-status:
description: |
Support status of the Gradle version that executed the build, following
https://docs.gradle.org/current/userguide/feature_lifecycle.html:
'active', 'maintenance' or 'eol'
runs: runs:
using: 'node24' using: 'node24'
main: '../dist/dependency-submission/main/index.js' main: '../dist/dependency-submission/main/index.js'
-3
View File
@@ -179,6 +179,3 @@ outputs:
gradle-version: gradle-version:
type: string type: string
gradle-version-status:
type: string
+1 -5
View File
@@ -246,11 +246,7 @@ outputs:
description: Path to the GitHub Dependency Graph snapshot file generated by a Gradle build. Note that this output applies to a Step executing Gradle, not to the `setup-gradle` Step itself. description: Path to the GitHub Dependency Graph snapshot file generated by a Gradle build. Note that this output applies to a Step executing Gradle, not to the `setup-gradle` Step itself.
gradle-version: gradle-version:
description: Version of Gradle that was setup by the action description: Version of Gradle that was setup by the action
gradle-version-status:
description: |
Support status of the Gradle version that executed the build, following
https://docs.gradle.org/current/userguide/feature_lifecycle.html:
'active', 'maintenance' or 'eol'
runs: runs:
using: 'node24' using: 'node24'
main: '../dist/setup-gradle/main/index.js' main: '../dist/setup-gradle/main/index.js'
-1
View File
@@ -6,7 +6,6 @@ export interface BuildResult {
get rootProjectDir(): string get rootProjectDir(): string
get requestedTasks(): string get requestedTasks(): string
get gradleVersion(): string get gradleVersion(): string
get versionStatus(): string | undefined
get gradleHomeDir(): string get gradleHomeDir(): string
get buildFailed(): boolean get buildFailed(): boolean
get configCacheHit(): boolean get configCacheHit(): boolean
+14 -16
View File
@@ -1,13 +1,13 @@
import * as core from '@actions/core' import * as core from '@actions/core'
import {BuildResult} from './build-results'
import {GradleVersion} from './execution/gradle-version' import {GradleVersion} from './execution/gradle-version'
import wrapperChecksums from './wrapper-validation/wrapper-checksums.json' import wrapperChecksums from './wrapper-validation/wrapper-checksums.json'
const FEATURE_LIFECYCLE_DOC = 'https://docs.gradle.org/current/userguide/feature_lifecycle.html' const FEATURE_LIFECYCLE_DOC = 'https://docs.gradle.org/current/userguide/feature_lifecycle.html#eol_support'
const LATEST_RELEASED_MAJOR = determineLatestReleasedMajor(wrapperChecksums.map(entry => entry.version)) const LATEST_RELEASED_MAJOR = determineLatestReleasedMajor(wrapperChecksums.map(entry => entry.version))
const LATEST_MAJOR_VERSION_ENV = 'GRADLE_ACTIONS_LATEST_GRADLE_MAJOR'
export type SupportStatus = 'active' | 'maintenance' | 'eol'
export function determineLatestReleasedMajor(versions: string[]): number | undefined { export function determineLatestReleasedMajor(versions: string[]): number | undefined {
const releasedMajors = versions const releasedMajors = versions
@@ -17,27 +17,25 @@ export function determineLatestReleasedMajor(versions: string[]): number | undef
return releasedMajors.length > 0 ? Math.max(...releasedMajors) : undefined return releasedMajors.length > 0 ? Math.max(...releasedMajors) : undefined
} }
export function exportLatestReleasedMajor(): void { export function getSupportStatus(version: GradleVersion, latestMajor: number): SupportStatus {
if (LATEST_RELEASED_MAJOR !== undefined) { switch (Math.max(0, latestMajor - version.major)) {
core.exportVariable(LATEST_MAJOR_VERSION_ENV, LATEST_RELEASED_MAJOR) case 0:
return 'active'
case 1:
return 'maintenance'
default:
return 'eol'
} }
} }
export function reportSupportStatus(buildResults: BuildResult[]): void { export function reportSupportStatus(gradleVersions: string[]): void {
if (LATEST_RELEASED_MAJOR === undefined) { if (LATEST_RELEASED_MAJOR === undefined) {
return return
} }
const statusByVersion = new Map<string, string>() for (const gradleVersion of new Set(gradleVersions)) {
for (const {gradleVersion, versionStatus} of buildResults) {
if (versionStatus) {
statusByVersion.set(gradleVersion, versionStatus)
}
}
for (const [gradleVersion, status] of statusByVersion) {
const version = new GradleVersion(gradleVersion) const version = new GradleVersion(gradleVersion)
switch (status) { switch (getSupportStatus(version, LATEST_RELEASED_MAJOR)) {
case 'eol': case 'eol':
core.warning(eolMessage(version, LATEST_RELEASED_MAJOR), {title: 'Gradle version at end-of-life'}) core.warning(eolMessage(version, LATEST_RELEASED_MAJOR), {title: 'Gradle version at end-of-life'})
break break
@@ -15,7 +15,6 @@ settingsEvaluated { settings ->
spec.getParameters().getRequestedTasks().set(gradle.startParameter.taskNames.join(" ")) spec.getParameters().getRequestedTasks().set(gradle.startParameter.taskNames.join(" "))
spec.getParameters().getGradleHomeDir().set(gradle.gradleHomeDir.absolutePath) spec.getParameters().getGradleHomeDir().set(gradle.gradleHomeDir.absolutePath)
spec.getParameters().getInvocationId().set(gradle.ext.invocationId) spec.getParameters().getInvocationId().set(gradle.ext.invocationId)
spec.getParameters().getVersionStatus().set(gradle.ext.gradleVersionStatus ?: "")
}) })
gradle.services.get(BuildEventListenerRegistryInternal).onOperationCompletion(projectTracker) gradle.services.get(BuildEventListenerRegistryInternal).onOperationCompletion(projectTracker)
@@ -31,7 +30,6 @@ abstract class BuildResultsRecorder implements BuildService<BuildResultsRecorder
Property<String> getRequestedTasks() Property<String> getRequestedTasks()
Property<String> getGradleHomeDir() Property<String> getGradleHomeDir()
Property<String> getInvocationId() Property<String> getInvocationId()
Property<String> getVersionStatus()
} }
void started(BuildOperationDescriptor buildOperation, OperationStartEvent startEvent) {} void started(BuildOperationDescriptor buildOperation, OperationStartEvent startEvent) {}
@@ -51,16 +49,6 @@ 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 @Override
public void close() { public void close() {
def buildResults = [ def buildResults = [
@@ -68,17 +56,11 @@ abstract class BuildResultsRecorder implements BuildService<BuildResultsRecorder
rootProjectDir: getParameters().getRootProjectDir().get(), rootProjectDir: getParameters().getRootProjectDir().get(),
requestedTasks: getParameters().getRequestedTasks().get(), requestedTasks: getParameters().getRequestedTasks().get(),
gradleVersion: GradleVersion.current().version, gradleVersion: GradleVersion.current().version,
versionStatus: getParameters().getVersionStatus().getOrElse("") ?: null,
gradleHomeDir: getParameters().getGradleHomeDir().get(), gradleHomeDir: getParameters().getGradleHomeDir().get(),
buildFailed: buildFailed, buildFailed: buildFailed,
configCacheHit: configCacheHit 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 runnerTempDir = System.getProperty("RUNNER_TEMP") ?: System.getenv("RUNNER_TEMP")
def githubActionStep = System.getProperty("GITHUB_ACTION") ?: System.getenv("GITHUB_ACTION") def githubActionStep = System.getProperty("GITHUB_ACTION") ?: System.getenv("GITHUB_ACTION")
if (!runnerTempDir || !githubActionStep) { if (!runnerTempDir || !githubActionStep) {
@@ -5,7 +5,6 @@ import org.gradle.util.GradleVersion
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
def SKIP_BUILD_CAPTURE = "GRADLE_ACTIONS_SKIP_BUILD_RESULT_CAPTURE" 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_PLUGIN_ID = "com.gradle.build-scan"
def BUILD_SCAN_EXTENSION = "buildScan" def BUILD_SCAN_EXTENSION = "buildScan"
def DEVELOCITY_PLUGIN_ID = "com.gradle.develocity" def DEVELOCITY_PLUGIN_ID = "com.gradle.develocity"
@@ -24,8 +23,6 @@ if (isTopLevelBuild) {
def resultsWriter = new ResultsWriter() def resultsWriter = new ResultsWriter()
def version = GradleVersion.current().baseVersion def version = GradleVersion.current().baseVersion
gradle.ext.gradleVersionStatus = supportStatusOf(version, System.getenv(LATEST_GRADLE_MAJOR_ENV))
def atLeastGradle3 = version >= GradleVersion.version("3.0") def atLeastGradle3 = version >= GradleVersion.version("3.0")
def atLeastGradle6 = version >= GradleVersion.version("6.0") def atLeastGradle6 = version >= GradleVersion.version("6.0")
def atLeastGradle7 = version >= GradleVersion.version("7.0") def atLeastGradle7 = version >= GradleVersion.version("7.0")
@@ -87,46 +84,13 @@ def captureUsingBuildService(invocationId) {
apply from: 'gradle-actions.build-result-capture-service.plugin.groovy' 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) { void captureUsingBuildFinished(gradle, String invocationId, ResultsWriter resultsWriter) {
gradle.buildFinished { result -> gradle.buildFinished { result ->
def versionStatus = gradle.ext.gradleVersionStatus
if (versionStatus) {
setStepOutput("gradle-version-status", versionStatus)
}
def buildResults = [ def buildResults = [
rootProjectName: rootProject.name, rootProjectName: rootProject.name,
rootProjectDir: rootProject.projectDir.absolutePath, rootProjectDir: rootProject.projectDir.absolutePath,
requestedTasks: gradle.startParameter.taskNames.join(" "), requestedTasks: gradle.startParameter.taskNames.join(" "),
gradleVersion: GradleVersion.current().version, gradleVersion: GradleVersion.current().version,
versionStatus: versionStatus,
gradleHomeDir: gradle.gradleHomeDir.absolutePath, gradleHomeDir: gradle.gradleHomeDir.absolutePath,
buildFailed: result.failure != null, buildFailed: result.failure != null,
configCacheHit: false configCacheHit: false
@@ -146,7 +110,13 @@ void captureUsingBuildScanPublished(buildScanExtension, String invocationId, Res
] ]
resultsWriter.writeToResultsFile("build-scans", invocationId, scanResults) resultsWriter.writeToResultsFile("build-scans", invocationId, scanResults)
setStepOutput("build-scan-url", buildScan.buildScanUri.toString()) 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}")
}
} }
onError { error -> onError { error ->
+2 -3
View File
@@ -19,7 +19,7 @@ import {
} from './configuration' } from './configuration'
import * as wrapperValidator from './wrapper-validation/wrapper-validator' import * as wrapperValidator from './wrapper-validation/wrapper-validator'
import {initializeGradleUserHome} from './gradle-user-home' import {initializeGradleUserHome} from './gradle-user-home'
import {exportLatestReleasedMajor, reportSupportStatus} from './gradle-support-status' import {reportSupportStatus} from './gradle-support-status'
const GRADLE_SETUP_VAR = 'GRADLE_BUILD_ACTION_SETUP_COMPLETED' const GRADLE_SETUP_VAR = 'GRADLE_BUILD_ACTION_SETUP_COMPLETED'
const GRADLE_USER_HOME = 'GRADLE_USER_HOME' const GRADLE_USER_HOME = 'GRADLE_USER_HOME'
@@ -47,7 +47,6 @@ export async function setup(
core.saveState(GRADLE_USER_HOME, gradleUserHome) core.saveState(GRADLE_USER_HOME, gradleUserHome)
initializeGradleUserHome(userHome, gradleUserHome, cacheConfig.getCacheEncryptionKey()) initializeGradleUserHome(userHome, gradleUserHome, cacheConfig.getCacheEncryptionKey())
exportLatestReleasedMajor()
// Exchange the long-lived access key(s) for short-lived tokens, resolving the token for the // 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. // configured Develocity server and retaining it for the post-action (save) step.
@@ -91,7 +90,7 @@ export async function complete(
markBuildResultsProcessed() markBuildResultsProcessed()
reportSupportStatus(buildResults) reportSupportStatus(buildResults.map(result => result.gradleVersion))
core.info('Completed post-action step') core.info('Completed post-action step')
@@ -6,7 +6,6 @@ import static org.junit.Assume.assumeTrue
class TestBuildResultRecorder extends BaseInitScriptTest { class TestBuildResultRecorder extends BaseInitScriptTest {
def initScript = 'gradle-actions.build-result-capture.init.gradle' def initScript = 'gradle-actions.build-result-capture.init.gradle'
String latestGradleMajor
def "produces build results file for build with #testGradleVersion"() { def "produces build results file for build with #testGradleVersion"() {
assumeTrue testGradleVersion.compatibleWithCurrentJvm assumeTrue testGradleVersion.compatibleWithCurrentJvm
@@ -270,63 +269,6 @@ task expectFailure {
testGradleVersion << SETTINGS_PLUGIN_VERSIONS testGradleVersion << SETTINGS_PLUGIN_VERSIONS
} }
def "captures version status '#expectedStatus' when the latest released major is #latestMajor"() {
assumeTrue GRADLE_8_X.compatibleWithCurrentJvm
when:
latestGradleMajor = latestMajor
run(GRADLE_8_X.gradleVersion)
then:
assertVersionStatus(expectedStatus)
where:
latestMajor | expectedStatus
'7' | 'active'
'8' | 'active'
'9' | 'maintenance'
'10' | 'eol'
'13' | 'eol'
}
def "captures version status for #testGradleVersion"() {
assumeTrue testGradleVersion.compatibleWithCurrentJvm
when:
latestGradleMajor = '9'
run(testGradleVersion.gradleVersion)
then:
assertVersionStatus(expectedStatus)
where:
testGradleVersion | expectedStatus
GRADLE_6_X | 'eol'
GRADLE_7_X | 'eol'
GRADLE_8_X | 'maintenance'
}
def "captures no version status when the action did not supply the latest released major"() {
assumeTrue GRADLE_8_X.compatibleWithCurrentJvm
when:
run(GRADLE_8_X.gradleVersion)
then:
assertVersionStatus(null)
}
def "captures no version status when the latest released major is not a number"() {
assumeTrue GRADLE_8_X.compatibleWithCurrentJvm
when:
latestGradleMajor = 'not-a-number'
run(GRADLE_8_X.gradleVersion)
then:
assertVersionStatus(null)
}
def run(def args = ['help'], def gradleVersion) { def run(def args = ['help'], def gradleVersion) {
return run(args, initScript, gradleVersion, jvmArgs, envVars) return run(args, initScript, gradleVersion, jvmArgs, envVars)
} }
@@ -336,26 +278,17 @@ task expectFailure {
} }
def getJvmArgs() { def getJvmArgs() {
def jvmArgs = [ [
"-DRUNNER_TEMP=${testProjectDir.absolutePath}".toString(), "-DRUNNER_TEMP=${testProjectDir.absolutePath}".toString(),
"-DGITHUB_ACTION=github-step-id".toString() "-DGITHUB_ACTION=github-step-id".toString()
] ]
if (latestGradleMajor != null) {
jvmArgs << "-DGRADLE_ACTIONS_LATEST_GRADLE_MAJOR=${latestGradleMajor}".toString()
}
jvmArgs
} }
def getEnvVars() { def getEnvVars() {
def envVars = [ [
RUNNER_TEMP: testProjectDir.absolutePath, RUNNER_TEMP: testProjectDir.absolutePath,
GITHUB_ACTION: 'github-step-id', GITHUB_ACTION: 'github-step-id'
GITHUB_OUTPUT: githubOutputFile.absolutePath
] ]
if (latestGradleMajor != null) {
envVars.GRADLE_ACTIONS_LATEST_GRADLE_MAJOR = latestGradleMajor
}
envVars
} }
void assertResults(String task, TestGradleVersion testGradleVersion, boolean hasFailure, boolean configCacheHit = false) { void assertResults(String task, TestGradleVersion testGradleVersion, boolean hasFailure, boolean configCacheHit = false) {
@@ -375,24 +308,6 @@ task expectFailure {
assert scanResults['buildScanFailed'] == scanUploadFailed assert scanResults['buildScanFailed'] == scanUploadFailed
} }
void assertVersionStatus(String expectedStatus) {
def results = new JsonSlurper().parse(buildResultFile)
assert results['versionStatus'] == expectedStatus
if (expectedStatus == null) {
assert !githubOutput.contains('gradle-version-status')
} else {
assert githubOutput.contains("gradle-version-status=${expectedStatus}")
}
}
private File getGithubOutputFile() {
new File(testProjectDir, 'github-output')
}
private String getGithubOutput() {
githubOutputFile.exists() ? githubOutputFile.text : ''
}
private File getBuildResultFile() { private File getBuildResultFile() {
def buildResultsDir = new File(testProjectDir, '.gradle-actions/build-results') def buildResultsDir = new File(testProjectDir, '.gradle-actions/build-results')
assert buildResultsDir.directory assert buildResultsDir.directory
+29 -29
View File
@@ -1,23 +1,22 @@
import {beforeEach, describe, expect, it, jest} from '@jest/globals' import {beforeEach, describe, expect, it, jest} from '@jest/globals'
import {BuildResult} from '../../src/build-results'
// Mock @actions/core // Mock @actions/core
const mockWarning = jest.fn<(message: string, properties?: {title?: string}) => void>() const mockWarning = jest.fn<(message: string, properties?: {title?: string}) => void>()
const mockNotice = jest.fn<(message: string, properties?: {title?: string}) => void>() const mockNotice = jest.fn<(message: string, properties?: {title?: string}) => void>()
const mockExportVariable = jest.fn<(name: string, value: string | number) => void>()
jest.unstable_mockModule('@actions/core', () => ({ jest.unstable_mockModule('@actions/core', () => ({
warning: mockWarning, warning: mockWarning,
notice: mockNotice, notice: mockNotice
exportVariable: mockExportVariable
})) }))
const {determineLatestReleasedMajor, exportLatestReleasedMajor, reportSupportStatus} = const {determineLatestReleasedMajor, getSupportStatus, reportSupportStatus} =
await import('../../src/gradle-support-status') await import('../../src/gradle-support-status')
const {GradleVersion} = await import('../../src/execution/gradle-version')
import wrapperChecksums from '../../src/wrapper-validation/wrapper-checksums.json'
function build(gradleVersion: string, versionStatus?: string): BuildResult { const latestReleasedMajor = determineLatestReleasedMajor(wrapperChecksums.map(entry => entry.version))
return {gradleVersion, versionStatus} as BuildResult const MAINTENANCE_VERSION = `${(latestReleasedMajor ?? 0) - 1}.0`
}
const DOC = 'https://docs.gradle.org/current/userguide/feature_lifecycle.html#eol_support'
describe('determineLatestReleasedMajor', () => { describe('determineLatestReleasedMajor', () => {
it('ignores pre-releases and snapshots of an unreleased major', () => { it('ignores pre-releases and snapshots of an unreleased major', () => {
@@ -46,11 +45,17 @@ describe('determineLatestReleasedMajor', () => {
}) })
}) })
describe('exportLatestReleasedMajor', () => { describe('getSupportStatus', () => {
it('exports the boundary the init script needs to classify the running version', () => { it.each(['10.0.0', '10.4.2', '11.0.0-milestone-1', '12.0.0'])('treats %s as active', version => {
exportLatestReleasedMajor() expect(getSupportStatus(new GradleVersion(version), 10)).toBe('active')
})
expect(mockExportVariable).toHaveBeenCalledWith('GRADLE_ACTIONS_LATEST_GRADLE_MAJOR', expect.any(Number)) it.each(['9.0.0', '9.6.1', '9.7.0-rc-2'])('treats %s as maintenance-only', version => {
expect(getSupportStatus(new GradleVersion(version), 10)).toBe('maintenance')
})
it.each(['8.14', '8.0.2', '7.6.4', '4.10.3', '1.0'])('treats %s as end-of-life', version => {
expect(getSupportStatus(new GradleVersion(version), 10)).toBe('eol')
}) })
}) })
@@ -59,43 +64,38 @@ describe('reportSupportStatus', () => {
jest.clearAllMocks() jest.clearAllMocks()
}) })
it('warns about a version recorded as end-of-life', () => { it('warns about an end-of-life version', () => {
reportSupportStatus([build('7.6.4', 'eol')]) reportSupportStatus(['7.6.4'])
expect(mockNotice).not.toHaveBeenCalled() expect(mockNotice).not.toHaveBeenCalled()
expect(mockWarning).toHaveBeenCalledTimes(1) expect(mockWarning).toHaveBeenCalledTimes(1)
const [message, properties] = mockWarning.mock.calls[0] const [message, properties] = mockWarning.mock.calls[0]
expect(message).toContain('Gradle 7.6.4 has reached end-of-life') expect(message).toContain('Gradle 7.6.4 has reached end-of-life')
expect(message).toContain('the 7.x release line') expect(message).toContain('the 7.x release line no longer receives bug fixes or security fixes')
expect(message).toContain(DOC)
expect(properties?.title).toBe('Gradle version at end-of-life') expect(properties?.title).toBe('Gradle version at end-of-life')
}) })
it('notices a version recorded as maintenance-only', () => { it('notices a maintenance-only version', () => {
reportSupportStatus([build('8.14', 'maintenance')]) reportSupportStatus([MAINTENANCE_VERSION])
expect(mockWarning).not.toHaveBeenCalled() expect(mockWarning).not.toHaveBeenCalled()
expect(mockNotice).toHaveBeenCalledTimes(1) expect(mockNotice).toHaveBeenCalledTimes(1)
const [message, properties] = mockNotice.mock.calls[0] const [message, properties] = mockNotice.mock.calls[0]
expect(message).toContain('Gradle 8.14 is in maintenance-only support') expect(message).toContain(`Gradle ${MAINTENANCE_VERSION} is in maintenance-only support`)
expect(message).toContain('receives critical bug fixes and security fixes only')
expect(properties?.title).toBe('Gradle version in maintenance') expect(properties?.title).toBe('Gradle version in maintenance')
}) })
it('says nothing about a version recorded as active', () => { it('says nothing about a version in the latest release line', () => {
reportSupportStatus([build('9.6.1', 'active')]) reportSupportStatus(['999.0.0'])
expect(mockWarning).not.toHaveBeenCalled()
expect(mockNotice).not.toHaveBeenCalled()
})
it('says nothing when the init script recorded no status', () => {
reportSupportStatus([build('7.6.4')])
expect(mockWarning).not.toHaveBeenCalled() expect(mockWarning).not.toHaveBeenCalled()
expect(mockNotice).not.toHaveBeenCalled() expect(mockNotice).not.toHaveBeenCalled()
}) })
it('annotates each distinct version once', () => { it('annotates each distinct version once', () => {
reportSupportStatus([build('7.6.4', 'eol'), build('4.10.3', 'eol'), build('7.6.4', 'eol')]) reportSupportStatus(['7.6.4', '4.10.3', '7.6.4'])
expect(mockWarning).toHaveBeenCalledTimes(2) expect(mockWarning).toHaveBeenCalledTimes(2)
}) })