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

Feature: Check for latest version and show message in CLI #822

Merged
merged 16 commits into from
Sep 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
713 changes: 710 additions & 3 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions packages/cli-dashboard/src/dummyData/PSAT_DATA.js
Original file line number Diff line number Diff line change
Expand Up @@ -11739,4 +11739,5 @@ export default {
},
},
dateTime: '24 July, 2024, 12:12:04pm Asia/Calcutta',
psatVersion: '0.10.1-1',
};
3 changes: 3 additions & 0 deletions packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,18 +50,21 @@
"@google-psat/common": "*",
"@google-psat/i18n": "*",
"@google-psat/library-detection": "*",
"boxen": "^8.0.1",
"chalk": "^5.3.0",
"commander": "^10.0.1",
"fs-extra": "^11.1.1",
"promptly": "^3.2.0",
"sitemapper": "^3.1.8",
"spinnies": "^0.5.1",
"update-notifier": "^7.3.0",
"xml2js": "^0.6.2"
},
"devDependencies": {
"@types/fs-extra": "^11.0.1",
"@types/node": "^20.2.3",
"@types/promptly": "^3.0.2",
"@types/update-notifier": "^6.0.8",
"@types/xml2js": "^0.4.14",
"coffee": "^5.5.1",
"tsc-watch": "^6.0.4",
Expand Down
7 changes: 6 additions & 1 deletion packages/cli/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@
} from './utils';
import { redLogger } from './utils/coloredLoggers';
import saveResultsAsHTML from './utils/saveResultAsHTML';
import checkLatestVersion from './utils/checkLatestVersion';
import packageJson from '../package.json';

events.EventEmitter.defaultMaxListeners = 15;

Expand All @@ -67,7 +69,7 @@

program
.name(isFromNPMRegistry ? 'psat' : 'npm run cli')
.version('0.10.1')
.version(packageJson.version)
.usage(
isFromNPMRegistry ? '[website-url] [option]' : '[website-url] -- [options]'
)
Expand Down Expand Up @@ -158,6 +160,8 @@
const concurrency = program.opts().concurrency;
const waitTime = program.opts().wait;

await checkLatestVersion();

const numArgs: number = [
Boolean(url),
Boolean(sitemapUrl),
Expand Down Expand Up @@ -250,7 +254,7 @@
'Done analyzing cookies!'
);

let technologyAnalysisData: any = null;

Check warning on line 257 in packages/cli/src/index.ts

View workflow job for this annotation

GitHub Actions / Lint

Unexpected any. Specify a different type

if (shouldDoTechnologyAnalysis) {
spinnies.add('technology-spinner', {
Expand Down Expand Up @@ -283,6 +287,7 @@
};
return {
pageUrl: _url,
psatVersion: packageJson.version, // For adding in downloaded JSON file.
technologyData: technologyAnalysisData ? technologyAnalysisData[ind] : [],
cookieData: cookieAnalysisAndFetchedResourceData[ind].cookieData,
libraryMatches: detectedMatchingSignatures ?? [],
Expand Down
65 changes: 65 additions & 0 deletions packages/cli/src/utils/checkLatestVersion.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* Copyright 2024 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* External dependencies.
*/
import updateNotifier from 'update-notifier';
import boxen from 'boxen';
import chalk from 'chalk';

/**
* Internal dependencies.
*/
import packageJson from '../../package.json';

/**
* Check latest version and show message.
*/
const checkLatestVersion = async () => {
// The update-notifier package doesn't display an update message on the first run, which isn't what we want.
// However, we wanted to leverage its other functionalities, so we check for updates manually.
const notifier = updateNotifier({
pkg: packageJson,
updateCheckInterval: 1000 * 60 * 60 * 24 * 7 * 365 * 50, // Large number to prevent check.
shouldNotifyInNpmScript: true,
});

// @todo Cache result somehow to prevent it running everytime.
const info = await notifier.fetchInfo();

const message =
'Update available ' +
chalk.dim(info.current) +
chalk.reset(' → ') +
chalk.green(info.latest) +
' \nRun ' +
chalk.cyan('npm i -g @google-psat/cli') +
' to update';

if (info.type !== 'latest') {
console.log(
boxen(message, {
padding: 1,
margin: 1,
textAlignment: 'center',
borderColor: 'yellow',
borderStyle: 'round',
})
);
}
};

export default checkLatestVersion;
1 change: 1 addition & 0 deletions packages/cli/src/utils/saveReports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
*/
import { type CompleteJson } from '@google-psat/common';
import { ensureFile, writeFile } from 'fs-extra';

/**
* Internal dependencies.
*/
Expand Down
2 changes: 2 additions & 0 deletions packages/cli/src/utils/saveResultAsHTML.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import fs from 'fs';
* Internal dependencies
*/
import getOutputFilePath from './getOutputFilePath';
import packageJson from '../../package.json';

const isProduction = process.env.NODE_ENV === 'production';
/**
Expand Down Expand Up @@ -105,6 +106,7 @@ const saveResultsAsHTML = async (
translations: messages,
dateTime,
siteMapUrl: isSiteMap ? sitemapUrl : '',
psatVersion: packageJson.version,
})}</script>` +
htmlText.substring(htmlText.indexOf('</head>'));

Expand Down
94 changes: 94 additions & 0 deletions packages/cli/src/utils/tests/checkLatestVersion.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/*
* Copyright 2024 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* External dependencies.
*/
import updateNotifier from 'update-notifier';
import boxen from 'boxen';
import chalk from 'chalk';
import { noop } from '@google-psat/common';

/**
* Internal dependencies.
*/
import checkLatestVersion from '../checkLatestVersion';

jest.mock('update-notifier', () => jest.fn());
jest.mock('boxen', () => jest.fn());
jest.mock('chalk', () => ({
dim: jest.fn((text) => text),
reset: jest.fn((text) => text),
green: jest.fn((text) => text),
cyan: jest.fn((text) => text),
}));

describe('checkLatestVersion', () => {
let fetchInfoMock;

beforeEach(() => {
fetchInfoMock = jest.fn();

updateNotifier.mockReturnValue({
fetchInfo: fetchInfoMock,
});

jest.spyOn(console, 'log').mockImplementation(noop);
});

afterEach(() => {
jest.clearAllMocks();
});

it('should not show a message if the current version is the latest', async () => {
// Arrange
fetchInfoMock.mockResolvedValue({
current: '1.0.0',
latest: '1.0.0',
type: 'latest',
});

await checkLatestVersion();
expect(boxen).not.toHaveBeenCalled();
expect(console.log).not.toHaveBeenCalled();
});

it('should show a message if an update is available', async () => {
fetchInfoMock.mockResolvedValue({
current: '1.0.0',
latest: '2.0.0',
type: 'major',
});

const expectedMessage =
'Update available ' +
chalk.dim('1.0.0') +
chalk.reset(' → ') +
chalk.green('2.0.0') +
' \nRun ' +
chalk.cyan('npm i -g @google-psat/cli') +
' to update';

await checkLatestVersion();
expect(boxen).toHaveBeenCalledWith(expectedMessage, {
padding: 1,
margin: 1,
textAlignment: 'center',
borderColor: 'yellow',
borderStyle: 'round',
});
expect(console.log).toHaveBeenCalled();
});
});
3 changes: 2 additions & 1 deletion packages/cli/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
"moduleResolution": "node",
"outDir": "dist",
"declarationDir": "dist-types",
"composite": true
"composite": true,
"resolveJsonModule": true
},
"exclude": ["**/tests/**/*.ts", "dist/**", "dist-types/**"],
"references": [
Expand Down
4 changes: 4 additions & 0 deletions packages/extension/src/utils/downloadReport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,9 @@ export const generateDashboard = async (
const timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
const dateTime =
getCurrentDateAndTime('DD MMMM, YYYY, hh:mm:ssam/pm') + ' ' + timeZone;
const { version } = chrome?.runtime?.getManifest
? chrome.runtime.getManifest()
: { version: '' };

const code = `
window.PSAT_EXTENSION = true;
Expand All @@ -102,6 +105,7 @@ export const generateDashboard = async (
translations,
appliedFilters,
dateTime,
psatVersion: version,
})}`;

script.text = code;
Expand Down
14 changes: 11 additions & 3 deletions packages/report/src/dashboard/components/header/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,10 @@ import { PrivacySandboxColoredIcon } from '@google-psat/design-system';
interface HeaderProps {
url: string | undefined | null;
dateTime: string;
version: string;
}

const Header = ({ url, dateTime }: HeaderProps) => {
const Header = ({ url, dateTime, version }: HeaderProps) => {
// @ts-ignore - Global object.
const isExtension = globalThis?.PSAT_EXTENSION;

Expand All @@ -36,8 +37,15 @@ const Header = ({ url, dateTime }: HeaderProps) => {
<p className="text-xs mb-[1px]">{dateTime}</p>
</div>
</div>
<div className="flex items-center text-cente">
{isExtension ? 'PSAT Extension Analysis' : 'PSAT CLI Analysis'}
<div className="flex items-center">
<div>
<span className="block">
{isExtension ? 'PSAT Extension Analysis' : 'PSAT CLI Analysis'}
</span>
<span className="block text-right text-darkest-gray dark:text-white text-[11px]">
{version ? 'v' + version : ''}
</span>
</div>
</div>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ import { SidebarProvider, type SidebarItems } from '@google-psat/design-system';
/**
* Internal dependencies.
*/

import sidebarData from './sidebarData';
import Layout from './layout';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ import {
SiteBoundariesIcon,
SiteBoundariesIconWhite,
} from '@google-psat/design-system';

/**
* Internal dependencies.
*/

import { useContentStore } from '../stateProviders/contentStore';
import CookiesTab from '../tabs/cookies';
import SiteCookiesWithIssues from '../tabs/siteCookiesWithIssues';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ const AssembledCookiesLanding = ({
const filterOutput = useGlobalFiltering(cookies, query, clearQuery);

// @ts-ignore Using global variable.
const { dateTime } = globalThis?.PSAT_DATA || {};
const { dateTime, psatVersion } = globalThis?.PSAT_DATA || {};
const cookiesByKey = useMemo(() => {
return (
filterOutput.filteredData.reduce<TabCookies>((acc, cookie) => {
Expand Down Expand Up @@ -108,7 +108,7 @@ const AssembledCookiesLanding = ({

return (
<div className="h-full flex flex-col">
<Header url={url} dateTime={dateTime} />
<Header url={url} dateTime={dateTime} version={psatVersion} />
<div className="flex justify-center items-center flex-1 border-b border-gray-300 dark:border-quartz bg-anti-flash-white dark:bg-raisin-black">
<button
className="w-3 h-3 m-1 pl-1"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/**
* External dependencies
*/
Expand All @@ -27,6 +26,11 @@ import {
} from '@google-psat/common';
import { type TableFilter } from '@google-psat/design-system';

/**
* Internal dependencies.
*/
import packageJson from '../../../../../package.json';

const generateCSVFiles = (data: CompleteJson) => {
const allCookiesCSV = generateAllCookiesCSV(data);
let technologyDataCSV = null;
Expand Down Expand Up @@ -89,6 +93,7 @@ const generateHTMLFile = (
// @ts-ignore -- because this data will already be injected from cli or the extension.
dateTime: globalThis?.PSAT_DATA.dateTime,
hideDownloadButton: true,
psatVersion: packageJson.version,
};

let code = `window.PSAT_DATA = ${JSON.stringify(reportData)};`;
Expand Down
Loading