Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(cli): show warning when using deprecated version #102

Open
wants to merge 9 commits into
base: main
Choose a base branch
from

Conversation

tttol
Copy link
Contributor

@tttol tttol commented Feb 23, 2025

Fixes aws/aws-cdk#298

What I changed

Show the warning message when Toolkit uses deprecated version of aws-cdk. The message is like below.

You are using deprecated version(aws-cdk@X.X.X): This version has been deprecated

Additional information

  • I'm new to aws-cdk.
  • I didn't submit PR to aws-cdk-cli-testing because I think that integration test is not needed in my change. But I am not confident in my judgment. Please let me know if additional integration tests are needed.

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license

@tttol tttol changed the title chore(cli):show warning when using deprecated version chore(cli): show warning when using deprecated version Feb 23, 2025

export async function checkIfDeprecated(version: string): Promise<string | null> {
try {
const { stdout, stderr } = await exec(`npm view aws-cdk@${version} deprecated --silent`, { timeout: 3000 });
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you work this into the existing version check in some way? (it may be that you will need to change that existing check to return information about more than 1 version at a time).

I'd like to avoid doing unnecessary calls to NPM.

Copy link
Contributor Author

@tttol tttol Feb 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rix0rrr
It's true that my implementation results in unnecessary NPM calls. But I couldn't find the logic of version check in existing source code. Which logic/file are you referring when you said work this into the existing version check?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

@tttol tttol Mar 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rix0rrr
Do you mean that calling checkIfDeprecated out of if (laterVersion) block is better?
Ref: https://github.com/aws/aws-cdk-cli/blob/main/packages/aws-cdk/lib/cli/version.ts#L125

    try {
      const laterVersion = await latestVersionIfHigher(currentVersion, versionCheckCache ?? new VersionCheckTTL());
+    const deprecationMessage = await checkIfDeprecated(currentVersion);
+    if (deprecationMessage) {
+      info(`You are using deprecated version(aws-cdk@${currentVersion}): ${deprecationMessage}`);
+    }
      if (laterVersion) {
        const versionMessage = await getVersionMessage(currentVersion, laterVersion);

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean I don't want 2 calls to npm view. I would like a single call to npm view to return both bits of information:

  • What is the latest version?
  • Is the current version deprecated?

It might be that that is not possible, but I would like that to be researched and confirmed first.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's somewhat possible to get this with a single request:

The downside is that this is a very large response object. Individual versions or latest can be fetched as well:


It might be prudent to change this feature over to use https calls anyway, to be less reliant on the npm binary. If we download the huge file, we definitely need to cache the result. Making two smaller https requests in parallel migh be faster, not sure. Probably still want to have a cache of sort or at least ensure this isn't checked all the time.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rix0rrr @mrgrain
Thank you for your advice. I will try to retrieve the latest version and deprecation message in a single npm viewcall.

$ npm view aws-cdk@1.204.0 deprecated name --json        
{
  "deprecated": "AWS CDK v1 has reached End-of-Support on 2023-06-01.\nThis package is no longer being updated, and users should migrate to AWS CDK v2.\n\nFor more information on how to migrate, see https://docs.aws.amazon.com/cdk/v2/guide/migrating-v2.html",
  "name": "aws-cdk"
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm. I don't think this single npm view call will be able to retrieve both bits of information.

I guess the best solution would be then to do 2 parallel calls to npm view for both bits of information, and run them in parallel with await Promise.all().

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Heyyy that's what you did 😆

@tttol tttol requested a review from rix0rrr March 2, 2025 21:10
- Refactored version checking logic to use `execNpmView` for retrieving package metadata
- Updated version message generation to handle deprecated versions and upgrade recommendations
- Simplified npm utility functions to return parsed JSON from npm view command
- Updated tests to mock new npm view behavior and improve test coverage
auto-merge was automatically disabled March 10, 2025 20:16

Head branch was pushed to by a user without write access

@tttol tttol marked this pull request as draft March 10, 2025 20:39
Comment on lines 10 to 12
.catch(err => {
throw new ToolkitError(`Failed to fetch latest version info: ${err.message}`);
}),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not super up on Promises syntax. Is catch with a throw inside the right way to do this?

Where are these errors handled?

Copy link
Contributor Author

@tttol tttol Mar 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is catch with a throw inside the right way to do this?

It’s not the wrong way in TypeScript, but this implementation is a little confusing. I used a single catch to handle all thrown exceptions.

const latestVersion = await getLatestVersionFromNpm();
const isNewer = semver.gt(latestVersion, currentVersion);
const packageInfo = await execNpmView(currentVersion);
const latestVersion = packageInfo.latestVersion;
await cacheFile.update(latestVersion);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should probably stick both fields into the cachefile? Both latestVersion and deprecated?

The entire packageInfo object therefore.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed the logic to cache the entire packageInfo.

Comment on lines +96 to 98
if (semver.eq(latestVersion, currentVersion)) {
return [];
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is only correct if you assume the latest pointer never points to a deprecated version. If that's something you assume, you should put it in a comment.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added the comment 👍

}

const versionMessage = [
`${chalk.red(packageInfo.deprecated as string)}`,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will this string ever be empty so that the filter below removes it? I have a feeling it would contain ANSI escape characters without characters in between? Have you tested?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exactly. I changed it to check if packageInfo.deprecated is undefined before calling chalk.red.

@tttol tttol marked this pull request as ready for review March 11, 2025 22:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Toolkit: warn/error in case toolkit is using a deprecated version
3 participants