Skip to content

Commit

Permalink
feat: use @oclif/core v4 (#824)
Browse files Browse the repository at this point in the history
Co-authored-by: Eric Willhoit <ewillhoit@salesforce.com>
  • Loading branch information
mdonnalley and iowillhoit authored May 31, 2024
1 parent b083be9 commit d0d8c4b
Show file tree
Hide file tree
Showing 5 changed files with 266 additions and 56 deletions.
7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@
"bugs": "https://github.com/oclif/plugin-update/issues",
"dependencies": {
"@inquirer/select": "^2.3.4",
"@oclif/core": "^3.26.6",
"@oclif/core": "^4.0.0-beta.13",
"chalk": "^5",
"debug": "^4.3.1",
"filesize": "^6.1.0",
"got": "^13",
"semver": "^7.6.0",
"tar-fs": "^2.1.1"
"tar-fs": "^2.1.1",
"tty-table": "^4.2.3"
},
"devDependencies": {
"@commitlint/config-conventional": "^19",
Expand All @@ -38,7 +39,7 @@
"oclif": "^4",
"prettier": "^3.2.5",
"shx": "^0.3.4",
"sinon": "^17",
"sinon": "^18.0.0",
"strip-ansi": "^7.1.0",
"ts-node": "^10.9.2",
"typescript": "^5.4.5"
Expand Down
22 changes: 16 additions & 6 deletions src/commands/update.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import select from '@inquirer/select'
import {Args, Command, Flags, ux} from '@oclif/core'
import {basename} from 'node:path'
import {sort} from 'semver'
import TtyTable from 'tty-table'

import {Updater} from '../update.js'

Expand Down Expand Up @@ -57,14 +58,23 @@ export default class UpdateCommand extends Command {
const updater = new Updater(this.config)
if (flags.available) {
const [index, localVersions] = await Promise.all([updater.fetchVersionIndex(), updater.findLocalVersions()])
const allVersions = sort(Object.keys(index)).reverse()

const table = allVersions.map((version) => {
const location = localVersions.find((l) => basename(l).startsWith(version)) || index[version]
return {location, version}
})
// eslint-disable-next-line new-cap
const t = TtyTable(
[
{align: 'left', value: 'Location'},
{align: 'left', value: 'Version'},
],
sort(Object.keys(index))
.reverse()
.map((version) => {
const location = localVersions.find((l) => basename(l).startsWith(version)) || index[version]
return [location, version]
}),
{compact: true},
)

ux.table(table, {location: {}, version: {}})
ux.stdout(t.render())
return
}

Expand Down
27 changes: 15 additions & 12 deletions src/update.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {Config, Interfaces, ux} from '@oclif/core'
import chalk from 'chalk'
import makeDebug from 'debug'
import fileSize from 'filesize'
import {got} from 'got'
import {Stats, existsSync} from 'node:fs'
Expand All @@ -9,6 +10,8 @@ import {basename, dirname, join} from 'node:path'
import {Extractor} from './tar.js'
import {ls, wait} from './util.js'

const debug = makeDebug('oclif:update')

const filesize = (n: number): string => {
const [num, suffix] = fileSize(n, {output: 'array'})
return Number.parseFloat(num).toFixed(1) + ` ${suffix}`
Expand Down Expand Up @@ -93,8 +96,8 @@ export class Updater {

await this.config.runHook('update', {channel, version})
ux.action.stop()
ux.log()
ux.log(
ux.stdout()
ux.stdout(
`Updating to a specific version will not update the channel. If autoupdate is enabled, the CLI will eventually be updated back to ${channel}.`,
)
} else {
Expand All @@ -114,7 +117,7 @@ export class Updater {

await this.touch()
await this.tidy()
ux.debug('done')
debug('done')
}

private async createBin(version: string): Promise<void> {
Expand Down Expand Up @@ -177,7 +180,7 @@ ${binPathEnvVar}="\$DIR/${bin}" ${redirectedEnvVar}=1 "$DIR/../${version}/bin/${

// removes any unused CLIs
private async tidy(): Promise<void> {
ux.debug('tidy')
debug('tidy')
try {
const root = this.clientRoot
if (!existsSync(root)) return
Expand Down Expand Up @@ -206,7 +209,7 @@ ${binPathEnvVar}="\$DIR/${bin}" ${redirectedEnvVar}=1 "$DIR/../${version}/bin/${
// touch the client so it won't be tidied up right away
try {
const p = join(this.clientRoot, this.config.version)
ux.debug('touching client at', p)
debug('touching client at', p)
if (!existsSync(p)) return
return utimes(p, new Date(), new Date())
} catch (error: unknown) {
Expand Down Expand Up @@ -273,7 +276,7 @@ const notUpdatable = (config: Config): boolean => {
ux.warn(instructions)
// once the spinner stops, it'll eat this blank line
// https://github.com/oclif/core/issues/799
ux.log()
ux.stdout()
}

return true
Expand All @@ -283,7 +286,7 @@ const notUpdatable = (config: Config): boolean => {
}

const composeS3SubDir = (config: Config): string => {
let s3SubDir = config.pjson.oclif.update.s3.folder || ''
let s3SubDir = config.pjson.oclif.update?.s3?.folder || ''
if (s3SubDir !== '' && s3SubDir.slice(-1) !== '/') s3SubDir = `${s3SubDir}/`
return s3SubDir
}
Expand Down Expand Up @@ -336,17 +339,17 @@ const debounce = async (cacheDir: string): Promise<void> => {
if (m > new Date()) {
const msg = `waiting until ${m.toISOString()} to update`
if (output) {
ux.debug(msg)
debug(msg)
} else {
ux.log(msg)
ux.stdout(msg)
output = true
}

await wait(60 * 1000) // wait 1 minute
return debounce(cacheDir)
}

ux.log('time to update')
ux.stdout('time to update')
}

const setChannel = async (channel: string, dataDir: string): Promise<void> =>
Expand Down Expand Up @@ -442,9 +445,9 @@ const determineCurrentVersion = async (clientBin: string, version: string): Prom
return matches ? matches[1] : version
} catch (error) {
if (error instanceof Error) {
ux.debug(error.name, error.message)
debug(error.name, error.message)
} else if (typeof error === 'string') {
ux.debug(error)
debug(error)
}
}

Expand Down
35 changes: 18 additions & 17 deletions test/update.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import {got} from 'got'
import nock from 'nock'
import {existsSync} from 'node:fs'
import {mkdir, rm, symlink, writeFile} from 'node:fs/promises'
import * as path from 'node:path'
import path from 'node:path'
import zlib from 'node:zlib'
import {createSandbox} from 'sinon'
import sinon from 'sinon'
import stripAnsi from 'strip-ansi'

import {Extractor} from '../src/tar.js'
Expand Down Expand Up @@ -48,18 +48,19 @@ describe('update plugin', () => {
let collector: OutputCollectors
let clientRoot: string

const sandbox = createSandbox()

beforeEach(async () => {
config = await loadConfig({root: path.join(process.cwd(), 'examples', 's3-update-example-cli')})
config.binPath = config.binPath || config.bin
collector = {stderr: [], stdout: []}
sandbox.stub(ux, 'log').callsFake((line) => collector.stdout.push(line || ''))
sandbox.stub(ux, 'warn').callsFake((line) => collector.stderr.push(line ? `${line}` : ''))
sandbox.stub(ux.action, 'start').callsFake((line) => collector.stdout.push(line || ''))
sandbox.stub(ux.action, 'stop').callsFake((line) => collector.stdout.push(line || ''))
sinon.stub(ux, 'stdout').callsFake((lines) => {
const arr = Array.isArray(lines) ? lines : [lines ?? '']
collector.stdout.push(...arr)
})
sinon.stub(ux, 'warn').callsFake((line) => collector.stderr.push(line ? `${line}` : ''))
sinon.stub(ux.action, 'start').callsFake((line) => collector.stdout.push(line || ''))
sinon.stub(ux.action, 'stop').callsFake((line) => collector.stdout.push(line || ''))
// @ts-expect-error because private method
sandbox.stub(Updater.prototype, 'refreshConfig').resolves()
sinon.stub(Updater.prototype, 'refreshConfig').resolves()
})

afterEach(async () => {
Expand All @@ -69,7 +70,7 @@ describe('update plugin', () => {
await rm(clientRoot, {force: true, recursive: true})
}

sandbox.restore()
sinon.restore()
})

it('should not update - already on same version', async () => {
Expand Down Expand Up @@ -99,7 +100,7 @@ describe('update plugin', () => {
await mkdir(path.join(`${newVersionPath}.partial.11111`, 'bin'), {recursive: true})
await writeFile(path.join(`${newVersionPath}.partial.11111`, 'bin', 'example-cli'), '../2.0.1/bin', 'utf8')

sandbox.stub(Extractor, 'extract').resolves()
sinon.stub(Extractor, 'extract').resolves()

const gzContents = zlib.gzipSync(' ')

Expand Down Expand Up @@ -134,7 +135,7 @@ describe('update plugin', () => {
)
const indexRegex = new RegExp(`example-cli-${config.platform}-${config.arch}-tar-gz.json`)

sandbox.stub(Extractor, 'extract').resolves()
sinon.stub(Extractor, 'extract').resolves()

const gzContents = zlib.gzipSync(' ')

Expand Down Expand Up @@ -163,7 +164,7 @@ describe('update plugin', () => {
})

it('will get the correct channel and use default registry', async () => {
const request = sandbox.spy(got, 'get')
const request = sinon.spy(got, 'get')
const hash = 'f289627'
config.pjson.name = '@oclif/plugin-update'
clientRoot = await setupClientRoot({config})
Expand All @@ -177,7 +178,7 @@ describe('update plugin', () => {
)
const indexRegex = new RegExp(`example-cli-${config.platform}-${config.arch}-tar-gz.json`)

sandbox.stub(Extractor, 'extract').resolves()
sinon.stub(Extractor, 'extract').resolves()

const gzContents = zlib.gzipSync(' ')

Expand Down Expand Up @@ -205,7 +206,7 @@ describe('update plugin', () => {
expect(request.firstCall.args[0]).to.include('https://registry.npmjs.org/@oclif/plugin-update')
})
it('will get the correct channel and use a custom registry', async () => {
const request = sandbox.spy(got, 'get')
const request = sinon.spy(got, 'get')
const hash = 'f289627'
config.pjson.name = '@oclif/plugin-update'
config.npmRegistry = 'https://myCustomRegistry.com'
Expand All @@ -220,7 +221,7 @@ describe('update plugin', () => {
)
const indexRegex = new RegExp(`example-cli-${config.platform}-${config.arch}-tar-gz.json`)

sandbox.stub(Extractor, 'extract').resolves()
sinon.stub(Extractor, 'extract').resolves()

const gzContents = zlib.gzipSync(' ')

Expand Down Expand Up @@ -276,7 +277,7 @@ describe('update plugin', () => {
await mkdir(path.join(`${newVersionPath}.partial.11111`, 'bin'), {recursive: true})
await writeFile(path.join(`${newVersionPath}.partial.11111`, 'bin', 'example-cli'), '../2.0.1/bin', 'utf8')
await writeFile(path.join(newVersionPath, 'bin', 'example-cli'), '../2.0.1/bin', 'utf8')
sandbox.stub(Extractor, 'extract').resolves()
sinon.stub(Extractor, 'extract').resolves()

const gzContents = zlib.gzipSync(' ')

Expand Down
Loading

0 comments on commit d0d8c4b

Please sign in to comment.