feat: startup banner shows verion info

This commit is contained in:
Cheng Liu 2024-02-22 17:27:08 -08:00
parent 4f38fcb58e
commit 07b5dd4c76
No known key found for this signature in database
GPG key ID: EEC8452F7DB85CD6
10 changed files with 114 additions and 15 deletions

View file

@ -17,6 +17,7 @@
"git-repo-info": "~2.1.1",
"inversify": "~6.0.2",
"reflect-metadata": "~0.2.1",
"semver": "~7.6.0",
"yargs": "~17.7.2"
},
"devDependencies": {
@ -24,6 +25,7 @@
"@rushstack/heft-node-rig": "2.4.5",
"@types/heft-jest": "1.0.6",
"@types/node": "20.11.16",
"@types/semver": "7.5.7",
"@types/yargs": "17.0.32",
"eslint": "8.56.0",
"typescript": "~5.3.3"

View file

@ -8,6 +8,7 @@ import { CIHelpCommand } from './commands/ci-help';
import { GitVersionCompatibility } from '../logic/GitVersionCompatibility';
import { TelemetryService } from '../services/TelemetryService';
import { getCommandName } from './commands/util';
import { SparoStartupBanner } from './SparoStartupBanner';
import type { ILaunchOptions } from '../api/Sparo';
export class SparoCICommandLine {
@ -16,13 +17,14 @@ export class SparoCICommandLine {
private constructor() {}
public static async launchAsync(launchOptions: ILaunchOptions): Promise<void> {
await GitVersionCompatibility.ensureGitVersionAsync();
if (launchOptions.collectTelemetryAsync) {
const telemetryService: TelemetryService = await getFromContainerAsync(TelemetryService);
telemetryService.setCollectTelemetryFunction(launchOptions.collectTelemetryAsync);
}
GitVersionCompatibility.ensureGitVersion();
SparoStartupBanner.logBanner();
const sparoCI: SparoCICommandLine = new SparoCICommandLine();
await sparoCI.prepareCommandAsync();
await sparoCI.runAsync();

View file

@ -9,6 +9,7 @@ import { ICommand } from './commands/base';
import { GitVersionCompatibility } from '../logic/GitVersionCompatibility';
import { TelemetryService } from '../services/TelemetryService';
import { getCommandName } from './commands/util';
import { SparoStartupBanner } from './SparoStartupBanner';
import type { ILaunchOptions } from '../api/Sparo';
export class SparoCommandLine {
@ -17,13 +18,14 @@ export class SparoCommandLine {
private constructor() {}
public static async launchAsync(launchOptions: ILaunchOptions): Promise<void> {
await GitVersionCompatibility.ensureGitVersionAsync();
if (launchOptions.collectTelemetryAsync) {
const telemetryService: TelemetryService = await getFromContainerAsync(TelemetryService);
telemetryService.setCollectTelemetryFunction(launchOptions.collectTelemetryAsync);
}
GitVersionCompatibility.ensureGitVersion();
SparoStartupBanner.logBanner();
const sparo: SparoCommandLine = new SparoCommandLine();
await sparo.prepareCommandAsync();
await sparo.runAsync();

View file

@ -0,0 +1,30 @@
import * as semver from 'semver';
import { Colorize } from '@rushstack/terminal';
import { getFromContainer } from '../di/container';
import { TerminalService } from '../services/TerminalService';
import { SparoVersion } from '../logic/SparoVersion';
import { GitVersionCompatibility } from '../logic/GitVersionCompatibility';
export class SparoStartupBanner {
public static logBanner(): void {
const sparoVersion: string = SparoVersion.version;
const gitVersion: string = GitVersionCompatibility.getGitVersion().join('.');
const nodeVersion: string = this._formatNodeVersion();
const { terminal } = getFromContainer(TerminalService);
terminal.writeLine();
terminal.writeLine(Colorize.bold(`Sparo accelerator for Git ${sparoVersion}`));
terminal.writeLine(`Node.js version is ${nodeVersion}`);
terminal.writeLine(`Git version is ${gitVersion}`);
terminal.writeLine();
}
private static _formatNodeVersion(): string {
const nodeVersion: string = process.versions.node;
const nodeMajorVersion: number = semver.major(nodeVersion);
const isOddNumberedVersion: boolean = nodeMajorVersion % 2 !== 0;
const isLtsVersion: boolean = !!process.release.lts;
const nodeReleaseLabel: string = isOddNumberedVersion ? 'unstable' : isLtsVersion ? 'LTS' : 'pre-LTS';
return `${nodeVersion} (${nodeReleaseLabel})`;
}
}

View file

@ -50,6 +50,11 @@ export async function getFromContainerAsync<T>(clazz: Constructable<T>): Promise
return instance as T;
}
export function getFromContainer<T>(clazz: Constructable<T>): T {
const instance: T = defaultContainer.get<T & IAppClassInterface>(clazz);
return instance as T;
}
/**
* Register a class into dependency-injection container
* @example

View file

@ -1,25 +1,33 @@
import 'reflect-metadata';
import { getFromContainerAsync } from '../di/container';
import { getFromContainer } from '../di/container';
import { GitService } from '../services/GitService';
/**
* This class provides the useful function to check git version.
*/
export class GitVersionCompatibility {
private static _gitVersion: [number, number, number] | undefined;
private constructor() {}
public static async ensureGitVersionAsync(): Promise<void> {
const gitService: GitService = await getFromContainerAsync(GitService);
const gitVersion: [number, number, number] | undefined = gitService.getGitVersion();
if (!gitVersion) {
throw new Error(`Fail to get git version`);
}
const [major, minor, patch] = gitVersion;
public static ensureGitVersion(): void {
const [major, minor, patch] = GitVersionCompatibility.getGitVersion();
if (major < 2 || minor < 32) {
throw new Error(
`git version is too low. The minimal git version is >=2.32.0. Your git version is ${major}.${minor}.${patch}. Please upgrade git.`
);
}
}
public static getGitVersion(): [number, number, number] {
if (!GitVersionCompatibility._gitVersion) {
const gitService: GitService = getFromContainer(GitService);
const gitVersion: [number, number, number] | undefined = gitService.getGitVersion();
if (!gitVersion) {
throw new Error(`Fail to get git version`);
}
GitVersionCompatibility._gitVersion = gitVersion;
}
return GitVersionCompatibility._gitVersion as [number, number, number];
}
}

View file

@ -0,0 +1,42 @@
import * as path from 'path';
import { type IPackageJson, PackageJsonLookup } from '@rushstack/node-core-library';
export class SparoVersion {
private static __sparoLibPackageJson: IPackageJson | undefined = undefined;
private static __sparoLibPackageFolder: string | undefined = undefined;
private constructor() {}
/**
* The currently executing version of the "sparo-lib" library.
* This is the same as the Sparo tool version for that release.
*/
public static get version(): string {
return this._sparoLibPackageJson.version;
}
/**
* @internal
*/
public static get _sparoLibPackageJson(): IPackageJson {
SparoVersion._ensureOwnPackageJsonIsLoaded();
return SparoVersion.__sparoLibPackageJson!;
}
public static get _sparoLibPackageFolder(): string {
SparoVersion._ensureOwnPackageJsonIsLoaded();
return SparoVersion.__sparoLibPackageFolder!;
}
private static _ensureOwnPackageJsonIsLoaded(): void {
if (!SparoVersion.__sparoLibPackageJson) {
const packageJsonFilePath: string | undefined =
PackageJsonLookup.instance.tryGetPackageJsonFilePathFor(__dirname);
if (!packageJsonFilePath) {
throw new Error('Unable to locate the package.json file for this module');
}
SparoVersion.__sparoLibPackageFolder = path.dirname(packageJsonFilePath);
SparoVersion.__sparoLibPackageJson = PackageJsonLookup.instance.loadPackageJson(packageJsonFilePath);
}
}
}

View file

@ -21,7 +21,9 @@ export class ArgvService {
public async parseArgvAsync(): Promise<void> {
this._parsed = await this.yargsArgv
.help(false)
// --debug
.boolean('debug')
// --verbose
.boolean('verbose')
.middleware([this._terminalMiddleware])
.parseAsync();

View file

@ -17,12 +17,12 @@ export class TerminalService {
public setIsVerbose(value: boolean): void {
this._terminalProvider.verboseEnabled = value;
// verbose implies debug
this._terminalProvider.debugEnabled = value;
}
public setIsDebug(value: boolean): void {
this._terminalProvider.debugEnabled = value;
// debug implies verbose
this._terminalProvider.verboseEnabled = value;
}
public get terminal(): ITerminal {

View file

@ -50,6 +50,9 @@ importers:
reflect-metadata:
specifier: ~0.2.1
version: 0.2.1
semver:
specifier: ~7.6.0
version: 7.6.0
yargs:
specifier: ~17.7.2
version: 17.7.2
@ -66,6 +69,9 @@ importers:
'@types/node':
specifier: 20.11.16
version: 20.11.16
'@types/semver':
specifier: 7.5.7
version: 7.5.7
'@types/yargs':
specifier: 17.0.32
version: 17.0.32