Skip to content

Commit

Permalink
refactor: upgrade command links to upgrade-helper (#1879)
Browse files Browse the repository at this point in the history
The upgrade helper has a high failure rate. Linking the user to the
upgrade helper is the best way to deprecate this feature.
  • Loading branch information
blakef authored May 11, 2023
1 parent 78a1742 commit 5774e6a
Show file tree
Hide file tree
Showing 12 changed files with 115 additions and 1,290 deletions.
8 changes: 7 additions & 1 deletion packages/cli-doctor/src/commands/__tests__/info.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,13 @@ import info from '../info';
import {logger} from '@react-native-community/cli-tools';
import loadConfig from '@react-native-community/cli-config';

jest.mock('@react-native-community/cli-config');
jest.mock('@react-native-community/cli-config', () => ({
__esModule: true,
default: () => ({
project: {},
root: '.',
}),
}));

beforeEach(() => {
jest.resetAllMocks();
Expand Down
86 changes: 61 additions & 25 deletions packages/cli-tools/src/releaseChecker/getLatestRelease.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,38 @@ import {fetch} from '../fetch';
import logger from '../logger';

export type Release = {
version: string;
// The current stable release
stable: string;
// The current candidate release. These are only populated if the latest release is a candidate release.
candidate?: string;
changelogUrl: string;
diffUrl: string;
};

interface DiffPurge {
name: string;
zipball_url: string;
tarball_url: string;
commit: {
sha: string;
url: string;
};
node_id: string;
}

function isDiffPurgeEntry(data: any): data is DiffPurge {
return (
[
data.name,
data.zipball_url,
data.tarball_url,
data.commit?.sha,
data.commit?.url,
data.node_id,
].indexOf(false) === -1
);
}

/**
* Checks via GitHub API if there is a newer stable React Native release and,
* if it exists, returns the release data.
Expand Down Expand Up @@ -49,17 +76,15 @@ export default async function getLatestRelease(

logger.debug('Checking for newer releases on GitHub');
const eTag = cacheManager.get(name, 'eTag');
const latestVersion = await getLatestRnDiffPurgeVersion(name, eTag);
logger.debug(`Latest release: ${latestVersion}`);
const {stable, candidate} = await getLatestRnDiffPurgeVersion(name, eTag);
logger.debug(`Latest release: ${stable} (${candidate})`);

if (
semver.compare(latestVersion, currentVersion) === 1 &&
!semver.prerelease(latestVersion)
) {
if (semver.compare(stable, currentVersion) >= 0) {
return {
version: latestVersion,
changelogUrl: buildChangelogUrl(latestVersion),
diffUrl: buildDiffUrl(currentVersion),
stable,
candidate,
changelogUrl: buildChangelogUrl(stable),
diffUrl: buildDiffUrl(stable),

This comment has been minimized.

Copy link
@kraenhansen

kraenhansen Dec 22, 2023

Contributor

This looks like a copy-paste error to me - it should have been:

diffUrl: buildDiffUrl(currentVersion),

With this change, the following is printed to my terminal:

info React Native v0.73.1 is now available (your project is running on v0.73.0).
info Changelog: https://github.com/facebook/react-native/releases/tag/v0.73.1
info Diff: https://react-native-community.github.io/upgrade-helper/?from=0.73.1
info For more info, check out "https://reactnative.dev/docs/upgrading?os=macos".

But I'd expect the diff URL should have been from=0.73.0.

cc @blakef @thymikee

This comment has been minimized.

Copy link
@kraenhansen

kraenhansen Dec 22, 2023

Contributor

I created #2231 to correct this 👍

};
}
} catch (e) {
Expand All @@ -79,13 +104,18 @@ function buildDiffUrl(version: string) {
return `https://react-native-community.github.io/upgrade-helper/?from=${version}`;
}

type LatestVersions = {
candidate?: string;
stable: string;
};

/**
* Returns the most recent React Native version available to upgrade to.
*/
async function getLatestRnDiffPurgeVersion(
name: string,
eTag?: string,
): Promise<string> {
): Promise<LatestVersions> {
const options = {
// https://developer.github.com/v3/#user-agent-required
headers: {'User-Agent': 'React-Native-CLI'} as Headers,
Expand All @@ -100,32 +130,38 @@ async function getLatestRnDiffPurgeVersion(
options,
);

const result: LatestVersions = {stable: '0.0.0'};

// Remote is newer.
if (status === 200) {
const body: Array<any> = data;
const latestVersion = body[0].name.substring(8);
const body: DiffPurge[] = data.filter(isDiffPurgeEntry);
const eTagHeader = headers.get('eTag');

// Update cache only if newer release is stable.
if (!semver.prerelease(latestVersion) && eTagHeader) {
logger.debug(`Saving ${eTagHeader} to cache`);
cacheManager.set(name, 'eTag', eTagHeader);
cacheManager.set(name, 'latestVersion', latestVersion);
for (let {name: version} of body) {
if (!result.candidate && version.includes('-rc')) {
result.candidate = version.substring(8);
continue;
}
if (!version.includes('-rc')) {
result.stable = version.substring(8);
if (eTagHeader) {
logger.debug(`Saving ${eTagHeader} to cache`);
cacheManager.set(name, 'eTag', eTagHeader);
cacheManager.set(name, 'latestVersion', result.stable);
}
return result;
}
}

return latestVersion;
return result;
}

// Cache is still valid.
if (status === 304) {
const latestVersion = cacheManager.get(name, 'latestVersion');
if (latestVersion) {
return latestVersion;
}
result.stable = cacheManager.get(name, 'latestVersion') ?? result.stable;
}

// Should be returned only if something went wrong.
return '0.0.0';
return result;
}

type Headers = {
Expand Down
22 changes: 14 additions & 8 deletions packages/cli-tools/src/releaseChecker/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,21 @@ const getReactNativeVersion = (projectRoot: string): string | undefined =>
* Logs out a message if the user's version is behind a stable version of React Native
*/
export async function logIfUpdateAvailable(projectRoot: string): Promise<void> {
const hasUpdate = await latest(projectRoot);
if (hasUpdate) {
printNewRelease(hasUpdate.name, hasUpdate.upgrade, hasUpdate.current);
const versions = await latest(projectRoot);
if (!versions?.upgrade) {
return;
}
if (semver.gt(versions.upgrade.stable, versions.current)) {
printNewRelease(versions.name, versions.upgrade, versions.current);
}
}

type Update = {
upgrade: Release;
// Only populated if an upgrade is available
upgrade?: Release;
// The project's package's current version
current: string;
// The project's package's name
name: string;
};

Expand All @@ -39,13 +45,13 @@ export async function latest(projectRoot: string): Promise<Update | undefined> {
return;
}
const {name} = require(path.join(projectRoot, 'package.json'));
const latestRelease = await getLatestRelease(name, currentVersion);
const upgrade = await getLatestRelease(name, currentVersion);

if (latestRelease) {
if (upgrade) {
return {
name,
current: currentVersion,
upgrade: latestRelease,
upgrade,
};
}
} catch (e) {
Expand All @@ -57,7 +63,7 @@ export async function latest(projectRoot: string): Promise<Update | undefined> {
);
logger.debug(e as any);
}
return undefined;
return;
}

/**
Expand Down
2 changes: 1 addition & 1 deletion packages/cli-tools/src/releaseChecker/printNewRelease.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export default function printNewRelease(
currentVersion: string,
) {
logger.info(
`React Native v${latestRelease.version} is now available (your project is running on v${currentVersion}).`,
`React Native v${latestRelease.stable} is now available (your project is running on v${currentVersion}).`,
);
logger.info(`Changelog: ${chalk.dim.underline(latestRelease.changelogUrl)}`);
logger.info(`Diff: ${chalk.dim.underline(latestRelease.diffUrl)}`);
Expand Down

This file was deleted.

This file was deleted.

Loading

0 comments on commit 5774e6a

Please sign in to comment.