Skip to content

Commit

Permalink
test: sf integration
Browse files Browse the repository at this point in the history
  • Loading branch information
mdonnalley committed Oct 6, 2023
1 parent 15cf4bf commit 140561a
Show file tree
Hide file tree
Showing 6 changed files with 351 additions and 39 deletions.
31 changes: 29 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,32 @@ on:
workflow_dispatch:

jobs:
unit-tests:
uses: oclif/github-workflows/.github/workflows/unitTest.yml@main
yarn-lockfile-check:
uses: salesforcecli/github-workflows/.github/workflows/lockFileCheck.yml@main
linux-unit-tests:
needs: yarn-lockfile-check
uses: salesforcecli/github-workflows/.github/workflows/unitTestsLinux.yml@main
windows-unit-tests:
needs: linux-unit-tests
uses: salesforcecli/github-workflows/.github/workflows/unitTestsWindows.yml@main
sf-integration:
needs: linux-unit-tests
strategy:
matrix:
node_version: [lts/*, latest]
os: [ubuntu-latest, windows-latest]
exclude:
- node_version: lts/*
os: windows-latest

fail-fast: false
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node_version }}
cache: yarn
- uses: salesforcecli/github-workflows/.github/actions/yarnInstallWithRetries@main
- run: yarn build
- run: yarn test:integration:sf
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,15 @@
"@types/node": "^18",
"@types/semver": "^7.5.0",
"@types/supports-color": "^7.2.0",
"@types/tar-fs": "^2.0.2",
"chai": "^4.3.7",
"commitlint": "^17.7.2",
"eslint": "^8.49.0",
"eslint-config-oclif": "^5.0.0",
"eslint-config-oclif-typescript": "^2.0.1",
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-perfectionist": "^2.1.0",
"got": "^13.0.0",
"husky": "^8.0.3",
"lint-staged": "^14.0.1",
"mocha": "^10.2.0",
Expand Down Expand Up @@ -80,6 +82,7 @@
"lint": "eslint . --ext .ts",
"pretest": "yarn build --noEmit && tsc -p test --noEmit",
"test": "mocha --forbid-only \"test/**/*.test.ts\"",
"test:integration:sf": "mocha --forbid-only \"test/integration/sf.integration.ts\" --timeout 90000",
"posttest": "yarn lint",
"prepack": "yarn build && oclif manifest . && oclif lock",
"prepare": "husky install",
Expand Down
8 changes: 4 additions & 4 deletions src/tar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import {join} from 'node:path'

import {touch} from './util.js'
const debug = makeDebug('oclif-update')
import crypto from 'node:crypto'
import zlib from 'node:zlib'
import {extract as tarExtract} from 'tar-fs'

const ignore = (_: any, header: any) => {
switch (header.type) {
Expand All @@ -31,9 +34,6 @@ async function extract(stream: NodeJS.ReadableStream, basename: string, output:
debug(`extracting to ${tmp}`)
try {
await new Promise((resolve, reject) => {
const zlib = require('node:zlib')
const tar = require('tar-fs')
const crypto = require('node:crypto')
let shaValidated = false
let extracted = false
const check = () => shaValidated && extracted && resolve(null)
Expand All @@ -53,7 +53,7 @@ async function extract(stream: NodeJS.ReadableStream, basename: string, output:
})
} else shaValidated = true

const extract = tar.extract(tmp, {ignore})
const extract = tarExtract(tmp, {ignore})
extract.on('error', reject)
extract.on('finish', () => {
extracted = true
Expand Down
48 changes: 18 additions & 30 deletions src/update.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {HTTP} from 'http-call'
import throttle from 'lodash.throttle'
import {Stats, existsSync} from 'node:fs'
import {mkdir, readFile, readdir, rm, stat, symlink, utimes, writeFile} from 'node:fs/promises'
import * as path from 'node:path'
import {basename, dirname, join} from 'node:path'

import {Extractor} from './tar.js'
import {ls, wait} from './util.js'
Expand All @@ -31,8 +31,8 @@ export class Updater {
private readonly clientRoot: string

constructor(private config: Config) {
this.clientRoot = config.scopedEnvVar('OCLIF_CLIENT_HOME') || path.join(config.dataDir, 'client')
this.clientBin = path.join(this.clientRoot, 'bin', config.windows ? `${config.bin}.cmd` : config.bin)
this.clientRoot = config.scopedEnvVar('OCLIF_CLIENT_HOME') || join(config.dataDir, 'client')
this.clientBin = join(this.clientRoot, 'bin', config.windows ? `${config.bin}.cmd` : config.bin)
}

public async fetchVersionIndex(): Promise<Updater.VersionIndex> {
Expand All @@ -55,7 +55,7 @@ export class Updater {
const dirOrFiles = await readdir(this.clientRoot)
return dirOrFiles
.filter((dirOrFile) => dirOrFile !== 'bin' && dirOrFile !== 'current')
.map((f) => path.join(this.clientRoot, f))
.map((f) => join(this.clientRoot, f))
}

public async runUpdate(options: Updater.Options): Promise<void> {
Expand Down Expand Up @@ -129,7 +129,7 @@ export class Updater {
const {bin, windows} = this.config
const binPathEnvVar = this.config.scopedEnvVarKey('BINPATH')
const redirectedEnvVar = this.config.scopedEnvVarKey('REDIRECTED')
await mkdir(path.dirname(dst), {recursive: true})
await mkdir(dirname(dst), {recursive: true})

if (windows) {
const body = `@echo off
Expand Down Expand Up @@ -160,8 +160,8 @@ ${binPathEnvVar}="\$DIR/${bin}" ${redirectedEnvVar}=1 "$DIR/../${version}/bin/${
`
/* eslint-enable no-useless-escape */
await writeFile(dst, body, {mode: 0o755})
await rm(path.join(this.clientRoot, 'current'), {force: true, recursive: true})
await symlink(`./${version}`, path.join(this.clientRoot, 'current'))
await rm(join(this.clientRoot, 'current'), {force: true, recursive: true})
await symlink(`./${version}`, join(this.clientRoot, 'current'))
}
}

Expand All @@ -175,11 +175,11 @@ ${binPathEnvVar}="\$DIR/${bin}" ${redirectedEnvVar}=1 "$DIR/../${version}/bin/${

private async findLocalVersion(version: string): Promise<string | undefined> {
const versions = await this.findLocalVersions()
return versions.map((file) => path.basename(file)).find((file) => file.startsWith(version))
return versions.map((file) => basename(file)).find((file) => file.startsWith(version))
}

private async refreshConfig(version: string): Promise<void> {
this.config = (await Config.load({root: path.join(this.clientRoot, version)})) as Config
this.config = (await Config.load({root: join(this.clientRoot, version)})) as Config
}

// removes any unused CLIs
Expand All @@ -191,7 +191,7 @@ ${binPathEnvVar}="\$DIR/${bin}" ${redirectedEnvVar}=1 "$DIR/../${version}/bin/${
const files = await ls(root)

const isNotSpecial = (fPath: string, version: string): boolean =>
!['bin', 'current', version].includes(path.basename(fPath))
!['bin', 'current', version].includes(basename(fPath))

const isOld = (fStat: Stats): boolean => {
const {mtime} = fStat
Expand All @@ -204,8 +204,6 @@ ${binPathEnvVar}="\$DIR/${bin}" ${redirectedEnvVar}=1 "$DIR/../${version}/bin/${
.filter((f) => isNotSpecial(this.config.version, f.path) && isOld(f.stat))
.map((f) => rm(f.path, {force: true, recursive: true})),
)

await logChop(this.config.errlog)
} catch (error: any) {
ux.warn(error)
}
Expand All @@ -214,7 +212,7 @@ ${binPathEnvVar}="\$DIR/${bin}" ${redirectedEnvVar}=1 "$DIR/../${version}/bin/${
private async touch(): Promise<void> {
// touch the client so it won't be tidied up right away
try {
const p = path.join(this.clientRoot, this.config.version)
const p = join(this.clientRoot, this.config.version)
ux.debug('touching client at', p)
if (!existsSync(p)) return
return utimes(p, new Date(), new Date())
Expand All @@ -238,7 +236,7 @@ ${binPathEnvVar}="\$DIR/${bin}" ${redirectedEnvVar}=1 "$DIR/../${version}/bin/${
)

await ensureClientDir(this.clientRoot)
const output = path.join(this.clientRoot, updated)
const output = join(this.clientRoot, updated)

if (force || !existsSync(output)) await downloadAndExtract(output, manifest, channel, this.config)

Expand Down Expand Up @@ -306,7 +304,7 @@ const fetchManifest = async (s3Key: string, config: Config): Promise<Interfaces.
const s3VersionIndexKey = (config: Config): string => {
const {arch, bin} = config
const s3SubDir = composeS3SubDir(config)
return path.join(s3SubDir, 'versions', `${bin}-${determinePlatform(config)}-${arch}-tar-gz.json`)
return join(s3SubDir, 'versions', `${bin}-${determinePlatform(config)}-${arch}-tar-gz.json`)
}

const determinePlatform = (config: Config): Interfaces.PlatformTypes =>
Expand All @@ -315,13 +313,13 @@ const determinePlatform = (config: Config): Interfaces.PlatformTypes =>
const s3ChannelManifestKey = (channel: string, config: Config): string => {
const {arch, bin} = config
const s3SubDir = composeS3SubDir(config)
return path.join(s3SubDir, 'channels', channel, `${bin}-${determinePlatform(config)}-${arch}-buildmanifest`)
return join(s3SubDir, 'channels', channel, `${bin}-${determinePlatform(config)}-${arch}-buildmanifest`)
}

const s3VersionManifestKey = ({config, hash, version}: {config: Config; hash: string; version: string}): string => {
const {arch, bin} = config
const s3SubDir = composeS3SubDir(config)
return path.join(
return join(
s3SubDir,
'versions',
version,
Expand All @@ -333,7 +331,7 @@ const s3VersionManifestKey = ({config, hash, version}: {config: Config; hash: st
// when autoupdating, wait until the CLI isn't active
const debounce = async (cacheDir: string): Promise<void> => {
let output = false
const lastrunfile = path.join(cacheDir, 'lastrun')
const lastrunfile = join(cacheDir, 'lastrun')
const m = await mtime(lastrunfile)
m.setHours(m.getHours() + 1)
if (m > new Date()) {
Expand All @@ -353,7 +351,7 @@ const debounce = async (cacheDir: string): Promise<void> => {
}

const setChannel = async (channel: string, dataDir: string): Promise<void> =>
writeFile(path.join(dataDir, 'channel'), channel, 'utf8')
writeFile(join(dataDir, 'channel'), channel, 'utf8')

const fetchChannelManifest = async (channel: string, config: Config): Promise<Interfaces.S3Manifest> => {
const s3Key = s3ChannelManifestKey(channel, config)
Expand Down Expand Up @@ -420,7 +418,7 @@ const downloadAndExtract = async (
}

const determineChannel = async ({config, version}: {config: Config; version?: string}): Promise<string> => {
const channelPath = path.join(config.dataDir, 'channel')
const channelPath = join(config.dataDir, 'channel')

// eslint-disable-next-line unicorn/no-await-expression-member
const channel = existsSync(channelPath) ? (await readFile(channelPath, 'utf8')).trim() : 'stable'
Expand Down Expand Up @@ -451,13 +449,3 @@ const determineCurrentVersion = async (clientBin: string, version: string): Prom

return version
}

const logChop = async (errlogPath: string): Promise<void> => {
try {
ux.debug('log chop')
const logChopper = require('log-chopper').default
await logChopper.chop(errlogPath)
} catch (error: any) {
ux.debug(error.message)
}
}
Loading

0 comments on commit 140561a

Please sign in to comment.