Skip to content

Commit

Permalink
Merge branch 'master' into huijbers/event-bus-name
Browse files Browse the repository at this point in the history
  • Loading branch information
mergify[bot] authored Jan 3, 2022
2 parents 1cb8c07 + e1d7efa commit 48afd48
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 20 deletions.
19 changes: 19 additions & 0 deletions packages/aws-cdk/lib/util/npm.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { exec as _exec } from 'child_process';
import { promisify } from 'util';
import * as semver from 'semver';
import { debug } from '../../lib/logging';

const exec = promisify(_exec);

export async function getLatestVersionFromNpm(): Promise<string> {
const { stdout, stderr } = await exec('npm view aws-cdk version');
if (stderr && stderr.trim().length > 0) {
debug(`The 'npm view' command generated an error stream with content [${stderr.trim()}]`);
}
const latestVersion = stdout.trim();
if (!semver.valid(latestVersion)) {
throw new Error(`npm returned an invalid semver ${latestVersion}`);
}

return latestVersion;
}
41 changes: 23 additions & 18 deletions packages/aws-cdk/lib/version.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import { exec as _exec } from 'child_process';
import * as path from 'path';
import { promisify } from 'util';
import * as colors from 'colors/safe';
import * as fs from 'fs-extra';
import * as semver from 'semver';
import { debug, print } from '../lib/logging';
import { formatAsBanner } from '../lib/util/console-formatters';
import { cdkCacheDir } from './util/directories';
import { getLatestVersionFromNpm } from './util/npm';

const ONE_DAY_IN_SECONDS = 1 * 24 * 60 * 60;

const exec = promisify(_exec);
const UPGRADE_DOCUMENTATION_LINKS: Record<number, string> = {
1: 'https://docs.aws.amazon.com/cdk/v2/guide/migrating-v2.html',
};

export const DISPLAY_VERSION = `${versionNumber()} (build ${commit()})`;

Expand Down Expand Up @@ -79,14 +80,7 @@ export async function latestVersionIfHigher(currentVersion: string, cacheFile: V
return null;
}

const { stdout, stderr } = await exec('npm view aws-cdk version');
if (stderr && stderr.trim().length > 0) {
debug(`The 'npm view' command generated an error stream with content [${stderr.trim()}]`);
}
const latestVersion = stdout.trim();
if (!semver.valid(latestVersion)) {
throw new Error(`npm returned an invalid semver ${latestVersion}`);
}
const latestVersion = await getLatestVersionFromNpm();
const isNewer = semver.gt(latestVersion, currentVersion);
await cacheFile.update(latestVersion);

Expand All @@ -97,19 +91,30 @@ export async function latestVersionIfHigher(currentVersion: string, cacheFile: V
}
}

export async function displayVersionMessage(): Promise<void> {
function getMajorVersionUpgradeMessage(currentVersion: string): string | void {
const currentMajorVersion = semver.major(currentVersion);
if (UPGRADE_DOCUMENTATION_LINKS[currentMajorVersion]) {
return `Information about upgrading from version ${currentMajorVersion}.x to version ${currentMajorVersion + 1}.x is available here: ${UPGRADE_DOCUMENTATION_LINKS[currentMajorVersion]}`;
}
}

function getVersionMessage(currentVersion: string, laterVersion: string): string[] {
return [
`Newer version of CDK is available [${colors.green(laterVersion as string)}]`,
getMajorVersionUpgradeMessage(currentVersion),
'Upgrade recommended (npm install -g aws-cdk)',
].filter(Boolean) as string[];
}

export async function displayVersionMessage(currentVersion = versionNumber(), versionCheckCache?: VersionCheckTTL): Promise<void> {
if (!process.stdout.isTTY || process.env.CDK_DISABLE_VERSION_CHECK) {
return;
}

try {
const versionCheckCache = new VersionCheckTTL();
const laterVersion = await latestVersionIfHigher(versionNumber(), versionCheckCache);
const laterVersion = await latestVersionIfHigher(currentVersion, versionCheckCache ?? new VersionCheckTTL());
if (laterVersion) {
const bannerMsg = formatAsBanner([
`Newer version of CDK is available [${colors.green(laterVersion as string)}]`,
'Upgrade recommended (npm install -g aws-cdk)',
]);
const bannerMsg = formatAsBanner(getVersionMessage(currentVersion, laterVersion));
bannerMsg.forEach((e) => print(e));
}
} catch (err) {
Expand Down
57 changes: 55 additions & 2 deletions packages/aws-cdk/test/version.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { promisify } from 'util';
import * as fs from 'fs-extra';
import * as sinon from 'sinon';
import * as logging from '../lib/logging';
import * as npm from '../lib/util/npm';
import { latestVersionIfHigher, VersionCheckTTL, displayVersionMessage } from '../lib/version';

jest.setTimeout(10_000);
Expand Down Expand Up @@ -77,9 +78,61 @@ test('No Version specified for storage in the TTL file', async () => {
});

test('Skip version check if environment variable is set', async () => {
process.stdout.isTTY = true;
process.env.CDK_DISABLE_VERSION_CHECK = '1';
sinon.stub(process, 'stdout').value({ ...process.stdout, isTTY: true });
sinon.stub(process, 'env').value({ ...process.env, CDK_DISABLE_VERSION_CHECK: '1' });
const printStub = sinon.stub(logging, 'print');
await displayVersionMessage();
expect(printStub.called).toEqual(false);
});

describe('version message', () => {
let previousIsTty: true | undefined;
beforeAll(() => {
previousIsTty = process.stdout.isTTY;
process.stdout.isTTY = true;
});

afterAll(() => {
process.stdout.isTTY = previousIsTty;
});

test('Prints a message when a new version is available', async () => {
// Given the current version is 1.0.0 and the latest version is 1.1.0
const currentVersion = '1.0.0';
jest.spyOn(npm, 'getLatestVersionFromNpm').mockResolvedValue('1.1.0');
const printSpy = jest.spyOn(logging, 'print');

// When displayVersionMessage is called
await displayVersionMessage(currentVersion, new VersionCheckTTL(tmpfile(), 0));

// Then the new version message is printed to stdout
expect(printSpy).toHaveBeenCalledWith(expect.stringContaining('1.1.0'));
});

test('Includes major upgrade documentation when available', async() => {
// Given the current version is 1.0.0 and the latest version is 2.0.0
const currentVersion = '1.0.0';
jest.spyOn(npm, 'getLatestVersionFromNpm').mockResolvedValue('2.0.0');
const printSpy = jest.spyOn(logging, 'print');

// When displayVersionMessage is called
await displayVersionMessage(currentVersion, new VersionCheckTTL(tmpfile(), 0));

// Then the V1 -> V2 documentation is printed
expect(printSpy).toHaveBeenCalledWith(expect.stringContaining('Information about upgrading from version 1.x to version 2.x is available here: https://docs.aws.amazon.com/cdk/v2/guide/migrating-v2.html'));
});

test('Does not include major upgrade documentation when unavailable', async() => {
// Given current version is 99.0.0 and the latest version is 100.0.0
const currentVersion = '99.0.0';
jest.spyOn(npm, 'getLatestVersionFromNpm').mockResolvedValue('100.0.0');
const printSpy = jest.spyOn(logging, 'print');

// When displayVersionMessage is called
await displayVersionMessage(currentVersion, new VersionCheckTTL(tmpfile(), 0));

// Then no upgrade documentation is printed
expect(printSpy).toHaveBeenCalledWith(expect.stringContaining('100.0.0'));
expect(printSpy).not.toHaveBeenCalledWith(expect.stringContaining('Information about upgrading from 99.x to 100.x'));
});
});

0 comments on commit 48afd48

Please sign in to comment.