From 9d0de74673b17ec7f982589d2fa1f3be1793dc93 Mon Sep 17 00:00:00 2001 From: daz Date: Tue, 9 Apr 2024 10:51:09 -0600 Subject: [PATCH] Emit deprecation warnings for derecated inputs - Adds an upgrade-guide to assist with resolving deprecations - Emit a warning when deprecated features are used - List all deprecated features in Job Summary and link to upgrade guide --- docs/deprecation-upgrade-guide.md | 95 +++++++++++++++++++++++ sources/src/dependency-submission/main.ts | 3 + sources/src/deprecation-collector.ts | 54 +++++++++++++ sources/src/input-params.ts | 11 +++ sources/src/job-summary.ts | 25 +++++- sources/src/setup-gradle/main.ts | 3 + sources/src/setup-gradle/post.ts | 4 + 7 files changed, 194 insertions(+), 1 deletion(-) create mode 100644 docs/deprecation-upgrade-guide.md create mode 100644 sources/src/deprecation-collector.ts diff --git a/docs/deprecation-upgrade-guide.md b/docs/deprecation-upgrade-guide.md new file mode 100644 index 0000000..93aabca --- /dev/null +++ b/docs/deprecation-upgrade-guide.md @@ -0,0 +1,95 @@ +# Deprecation upgrade guide + +As these actions evolve, certain inputs, behaviour and usages are deprecated for removal. +Deprecated functionality will be fully supported during the current major release, and will be +removed in the next major release. +Users will receive a deprecation warning when they rely on deprecated functionality, +prompting them to update their workflows. + +## Deprecated in v3.x + +### Using the action to execute Gradle via the `arguments` parameter is deprecated + +The core functionality of the `setup-gradle` (and `gradle-build-action`) actions is to configure your +Gradle environment for GitHub Actions. Once the action has run, any subsequent Gradle executions will +benefit from caching, reporting and other features of the action. + +Using the `arguments` parameter to execute Gradle directly is not necessary to benefit from this action. +This input is deprecated, and will be removed in the `v4` major release of the action. + +To convert your workflows, replace any steps using the `arguments` parameter with 2 steps: one to `setup-gradle` and another that runs your Gradle build. + +For example, if your workflow looks like this: + +``` +steps: +- name: Assemble the project + uses: gradle/actions/setup-gradle@v3 + with: + arguments: 'assemble' + + - name: Run the tests + uses: gradle/actions/setup-gradle@v3 + with: + arguments: 'test' +``` + +Then replace this with a single call to `setup-gradle` together with separate `run` steps to execute your build. + +``` +- name: Setup Gradle + uses: gradle/actions/setup-gradle@v3 + +- name: Assemble the project + run: ./gradlew assemble + +- name: Run the tests + run: ./gradlew test +``` + +Using the action in this way gives you more control over how Gradle is executed, while still giving you +all of the benefits of the `setup-gradle` action. + +The `arguments` parameter is scheduled to be removed in `setup-gradle@v4`. + +Note: if you are using the `gradle-build-action`, [see here](#the-gradle-build-action-has-been-replaced-by-the-setup-gradle-action) for more details on how to migrate. + +### The `gradle-build-action` has been replaced by the `setup-gradle` action + +The `gradle-build-action` action has evolved, so that the core functionality is now to configure the +Gradle environment for GitHub Actions. For clarity and consistency with other action (eg `setup-java`, `setup-node`), the `gradle-build-action` has been replaced by the `setup-gradle` action. + +As of `v3.x`, the `setup-gradle` and `gradle-build-action` actions are functionally identical, +and are released with the same versions. + +To convert your workflows, simply replace: +``` + uses: gradle/gradle-build-action@v3 +``` +with +``` + uses: gradle/actions/setup-gradle@v3 +``` + +### The `build-scan-terms-of-service` input parameters have been renamed + +With recent releases of the `com.gradle.develocity` plugin, key input parameters have been renamed. +- `build-scan-terms-of-service-url` is now `build-scan-terms-of-use-url` +- `build-scan-terms-of-service-agree` is now `build-scan-terms-of-use-agree` + +The standard URL for the terms of use has also changed to https://gradle.com/help/legal-terms-of-use + +To convert your workflows, change: +``` + build-scan-publish: true + build-scan-terms-of-service-url: "https://gradle.com/terms-of-service" + build-scan-terms-of-service-agree: "yes" +``` + +to this: +``` + build-scan-publish: true + build-scan-terms-of-use-url: "https://gradle.com/help/legal-terms-of-use" + build-scan-terms-of-use-agree: "yes" +``` +These deprecated build-scan parameters are scheduled to be removed in `setup-gradle@v4` and `dependency-submission@v4`. diff --git a/sources/src/dependency-submission/main.ts b/sources/src/dependency-submission/main.ts index 73e5d0c..4d0d3c7 100644 --- a/sources/src/dependency-submission/main.ts +++ b/sources/src/dependency-submission/main.ts @@ -12,6 +12,7 @@ import { DependencyGraphOption, GradleExecutionConfig } from '../input-params' +import {saveDeprecationState} from '../deprecation-collector' /** * The main entry point for the action, called by Github Actions for the step. @@ -49,6 +50,8 @@ export async function run(): Promise { ) await dependencyGraph.complete(config) + + saveDeprecationState() } catch (error) { core.setFailed(String(error)) if (error instanceof Error && error.stack) { diff --git a/sources/src/deprecation-collector.ts b/sources/src/deprecation-collector.ts new file mode 100644 index 0000000..5cbc47e --- /dev/null +++ b/sources/src/deprecation-collector.ts @@ -0,0 +1,54 @@ +import * as core from '@actions/core' +import * as github from '@actions/github' + +const DEPRECATION_UPGRADE_PAGE = 'https://github.com/gradle/actions/blob/main/docs/deprecation-upgrade-guide.md' +const recordedDeprecations: Deprecation[] = [] + +export class Deprecation { + constructor(readonly message: string) {} + + getDocumentationLink(): string { + const deprecationAnchor = this.message + .toLowerCase() + .replace(/[^\w\s-]|_/g, '') + .replace(/ /g, '-') + return `${DEPRECATION_UPGRADE_PAGE}#${deprecationAnchor}` + } +} + +export function recordDeprecation(message: string): void { + if (!recordedDeprecations.some(deprecation => deprecation.message === message)) { + recordedDeprecations.push(new Deprecation(message)) + } +} + +export function getDeprecations(): Deprecation[] { + return recordedDeprecations +} + +export function emitDeprecationWarnings(): void { + if (recordedDeprecations.length > 0) { + core.warning( + `This job uses deprecated functionality from the '${github.context.action}' action. Consult the Job Summary for more details.` + ) + for (const deprecation of recordedDeprecations) { + core.info(`DEPRECATION: ${deprecation.message}. See ${deprecation.getDocumentationLink()}`) + } + } +} + +export function saveDeprecationState(): void { + core.saveState('deprecations', JSON.stringify(recordedDeprecations)) +} + +export function restoreDeprecationState(): void { + const stringRep = core.getState('deprecations') + if (stringRep === '') { + return + } + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + JSON.parse(stringRep).forEach((obj: any) => { + recordedDeprecations.push(new Deprecation(obj.message)) + }) +} diff --git a/sources/src/input-params.ts b/sources/src/input-params.ts index eb9ac04..757de18 100644 --- a/sources/src/input-params.ts +++ b/sources/src/input-params.ts @@ -1,6 +1,7 @@ import * as core from '@actions/core' import * as github from '@actions/github' import * as cache from '@actions/cache' +import * as deprecator from './deprecation-collector' import {SUMMARY_ENV_VAR} from '@actions/core/lib/summary' import {parseArgsStringToArgv} from 'string-argv' @@ -215,6 +216,11 @@ export class BuildScanConfig { if (newProp !== '') { return newProp } + const oldProp = core.getInput(oldPropName) + if (oldProp !== '') { + deprecator.recordDeprecation('The `build-scan-terms-of-service` input parameters have been renamed') + return oldProp + } return core.getInput(oldPropName) } } @@ -236,6 +242,11 @@ export class GradleExecutionConfig { getArguments(): string[] { const input = core.getInput('arguments') + if (input.length !== 0) { + deprecator.recordDeprecation( + 'Using the action to execute Gradle via the `arguments` parameter is deprecated' + ) + } return parseArgsStringToArgv(input) } diff --git a/sources/src/job-summary.ts b/sources/src/job-summary.ts index 52afc07..7e728a9 100644 --- a/sources/src/job-summary.ts +++ b/sources/src/job-summary.ts @@ -4,6 +4,7 @@ import {RequestError} from '@octokit/request-error' import {BuildResult} from './build-results' import {SummaryConfig, getGithubToken} from './input-params' +import {Deprecation, getDeprecations} from './deprecation-collector' export async function generateJobSummary( buildResults: BuildResult[], @@ -78,8 +79,30 @@ Note that this permission is never available for a workflow triggered from a rep } function renderSummaryTable(results: BuildResult[]): string { + return `${renderDeprecations()}\n${renderBuildResults(results)}` +} + +function renderDeprecations(): string { + const deprecations = getDeprecations() + if (deprecations.length === 0) { + return '' + } + return ` +

Deprecated usages of ${github.context.action}

+ + +

Gradle Build Results

` +} + +function getDeprecationHtml(deprecation: Deprecation): string { + return `${deprecation.message}` +} + +function renderBuildResults(results: BuildResult[]): string { if (results.length === 0) { - return 'No Gradle build results detected.' + return 'No Gradle build results detected.' } return ` diff --git a/sources/src/setup-gradle/main.ts b/sources/src/setup-gradle/main.ts index 19e8eff..21442c8 100644 --- a/sources/src/setup-gradle/main.ts +++ b/sources/src/setup-gradle/main.ts @@ -4,6 +4,7 @@ import * as setupGradle from '../setup-gradle' import * as gradle from '../execution/gradle' import * as dependencyGraph from '../dependency-graph' import {BuildScanConfig, CacheConfig, DependencyGraphConfig, GradleExecutionConfig} from '../input-params' +import {saveDeprecationState} from '../deprecation-collector' /** * The main entry point for the action, called by Github Actions for the step. @@ -22,6 +23,8 @@ export async function run(): Promise { config.getBuildRootDirectory(), config.getArguments() ) + + saveDeprecationState() } catch (error) { core.setFailed(String(error)) if (error instanceof Error && error.stack) { diff --git a/sources/src/setup-gradle/post.ts b/sources/src/setup-gradle/post.ts index d1b99ba..375219a 100644 --- a/sources/src/setup-gradle/post.ts +++ b/sources/src/setup-gradle/post.ts @@ -4,6 +4,7 @@ import * as dependencyGraph from '../dependency-graph' import {CacheConfig, DependencyGraphConfig, SummaryConfig} from '../input-params' import {PostActionJobFailure} from '../errors' +import {emitDeprecationWarnings, restoreDeprecationState} from '../deprecation-collector' // Catch and log any unhandled exceptions. These exceptions can leak out of the uploadChunk method in // @actions/toolkit when a failed upload closes the file descriptor causing any in-process reads to @@ -15,6 +16,9 @@ process.on('uncaughtException', e => handleFailure(e)) */ export async function run(): Promise { try { + restoreDeprecationState() + emitDeprecationWarnings() + if (await setupGradle.complete(new CacheConfig(), new SummaryConfig())) { // Only submit the dependency graphs once per job await dependencyGraph.complete(new DependencyGraphConfig())