Skip to content

Commit

Permalink
feat: support parallelCount set parallel count, suppot first prop…
Browse files Browse the repository at this point in the history
…erty to install before all others
  • Loading branch information
Avivbens committed May 4, 2024
1 parent 701bc1b commit 0d117b5
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 24 deletions.
1 change: 1 addition & 0 deletions src/commands/install/config/apps-groups/mac.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export const MACOS: Readonly<IAppSetup[]> = [
description: 'Enable Touch ID for sudo (password needed)',
group: 'MacOS',
default: true,
first: true,
commands: () => [
'sudo -v',
'sudo cp -f /etc/pam.d/sudo_local.template /etc/pam.d/sudo_local',
Expand Down
73 changes: 50 additions & 23 deletions src/commands/install/install.command.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Listr, ListrTask } from 'listr2'
import { Command, CommandRunner, Option } from 'nest-commander'
import { cpus } from 'node:os'
import { arch as ARCH } from 'node:process'
import { arch as ARCH, exit } from 'node:process'
import ora from 'ora'
import { BREW_NON_ERRORS } from '@common/constants'
import { execPromise } from '@common/utils'
Expand Down Expand Up @@ -41,8 +41,24 @@ export class InstallCommand extends CommandRunner {
return true
}

@Option({
name: 'parallelCount',
flags: '-p --parallel-count <parallelCount>',
defaultValue: cpus().length / 2 + 1,
description: 'Amount of parallel processes for installation',
})
private parallelCount(count: string): number {
const parsed = Number(count)
if (isNaN(parsed)) {
this.logger.error('Parallel count should be a number')
exit(1)
}

return parsed
}

async run(inputs: string[], options: IInstallCommandOptions): Promise<void> {
const { noParallel } = options
const { noParallel, parallelCount } = options
await this.checkUpdateService.checkForUpdates()

try {
Expand All @@ -55,24 +71,30 @@ export class InstallCommand extends CommandRunner {

const toInstall = await MULTI_SELECT_APPS_PROMPT(uniqueTags)

const order = this.resolveDeps(toInstall).sort((a, b) => {
if (a.last) {
return 1
}
const resolvedDeps = this.resolveDeps(toInstall)

if (b.last) {
return -1
}
this.logger.debug(`Installing apps, resolvedDeps: ${resolvedDeps.map((app) => app.name).join(', ')}`)
this.logger.debug(`Current arch ${ARCH}`)

return 0
})
const firstApps = resolvedDeps.filter((app) => app.first)
const lastApps = resolvedDeps.filter((app) => app.last)
const restApps = resolvedDeps.filter((app) => !app.first && !app.last)

this.logger.debug(`Installing apps: ${order.map((app) => app.name).join(', ')}`)
if (noParallel) {
this.logger.debug('No parallel installation!')

this.logger.debug(`Current arch ${ARCH}`)
this.logger.debug(`Installing apps, firstApps: ${firstApps.map((app) => app.name).join(', ')}`)
for (const app of firstApps) {
await this.installApp(app)
}

if (noParallel) {
for (const app of order) {
this.logger.debug(`Installing apps, restApps: ${restApps.map((app) => app.name).join(', ')}`)
for (const app of restApps) {
await this.installApp(app)
}

this.logger.debug(`Installing apps, lastApps: ${lastApps.map((app) => app.name).join(', ')}`)
for (const app of lastApps) {
await this.installApp(app)
}

Expand All @@ -82,24 +104,29 @@ export class InstallCommand extends CommandRunner {
/**
* Parallel installation
*/
this.logger.log('Parallel installation is experimental!', 'yellow')
this.logger.log('Enter sudo password in order to have parallel installation', 'red-background')
this.logger.log(
'\n\n---------- Enter sudo password in order to have parallel installation ----------\n\n',
'red-background',
)
await execPromise(`sudo -v`)

const cpusAmount = cpus().length
const parallelProcessAmount = cpusAmount / 2 + 1
this.logger.debug(`Installing apps, firstApps: ${firstApps.map((app) => app.name).join(', ')}`)
for (const app of firstApps) {
await this.installApp(app)
}

const orderNoLast = order.filter((app) => !app.last)
const lastApps = order.filter((app) => app.last)
this.logger.debug(`Installing apps, restApps: ${restApps.map((app) => app.name).join(', ')}`)

const tasksChunks = this.generateParallelTasks(orderNoLast, parallelProcessAmount)
const tasksChunks = this.generateParallelTasks(restApps, parallelCount)

for (const tasks of tasksChunks) {
const spinners = new Listr(tasks, TASKS_CONFIG(parallelProcessAmount))
const spinners = new Listr(tasks, TASKS_CONFIG(parallelCount))

await spinners.run()
}

this.logger.debug(`Installing apps, lastApps: ${lastApps.map((app) => app.name).join(', ')}`)

for (const app of lastApps) {
await this.installApp(app)
}
Expand Down
6 changes: 6 additions & 0 deletions src/commands/install/models/install-command.options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,10 @@ export interface IInstallCommandOptions {
* @default false
*/
noParallel: boolean

/**
* Number of parallel install commands to run
* @default - (number of CPU cores) / 2 + 1
*/
parallelCount: number
}
6 changes: 6 additions & 0 deletions src/models/app-setup.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ export interface IAppSetup {
*/
paid?: boolean

/**
* @default false
* @description If true, the app will be installed first.
*/
first?: boolean

/**
* @default false
* @description If true, the app will be installed last. Cannot be a dependency!
Expand Down
2 changes: 1 addition & 1 deletion src/services/logger.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export class LoggerService {
}
public error(message: string, trace?) {
const generatedMessage = this.generateMessage(message)
console.error(`\x1b[31m${message}\x1b[0m`)
console.error(this.coloredMessage(message, 'red'))
appendFile(this.logPath, `ERROR | ${generatedMessage}\n`, { mode: 0o770 })
}
public warn(message: string) {
Expand Down

0 comments on commit 0d117b5

Please sign in to comment.