Skip to content

Commit

Permalink
feat: ✨ More config file options (#383)
Browse files Browse the repository at this point in the history
* feat: ✨ Add consmiconfig util

* feat: ✨♻️ Swap config service for config util

* fix: 🐛 Use passed config over creating new config service

* 🔥 Remove configuration service

* fix: ✅ Use expected arg for testing default config

Previously, the config service would mutate the default config object if a
config file could not be found. This caused a test to pass since the given
argument then mutated the default config object.

* feat: ✨ Update percy-client for .env support

* feat: ✨ Allow passing a config file path as a flag
  • Loading branch information
Wil Wilsman authored Oct 1, 2019
1 parent ae58f64 commit b9875a1
Show file tree
Hide file tree
Showing 14 changed files with 149 additions and 224 deletions.
3 changes: 0 additions & 3 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,6 @@ jobs:
- run:
name: Upload command test
command: yarn test-upload-command
- run:
name: Setup integration test .percy.yml
command: mv .ci.percy.yml .percy.yml
- run:
name: Integration tests
command: $NYC yarn test-integration
Expand Down
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"body-parser": "^1.18.3",
"colors": "^1.3.2",
"cors": "^2.8.4",
"cosmiconfig": "^5.2.1",
"cross-spawn": "^6.0.5",
"deepmerge": "^4.0.0",
"express": "^4.16.3",
Expand All @@ -34,7 +35,7 @@
"globby": "^10.0.1",
"image-size": "^0.8.2",
"js-yaml": "^3.13.1",
"percy-client": "^3.0.3",
"percy-client": "^3.1.0",
"puppeteer": "^1.13.0",
"retry-axios": "^1.0.1",
"winston": "^3.0.0"
Expand Down Expand Up @@ -144,7 +145,7 @@
"preversion": "yarn clean",
"test": "yarn build-client && PERCY_TOKEN=abc mocha --forbid-only \"test/**/*.test.ts\" --exclude \"test/percy-agent-client/**/*.test.ts\" --exclude \"test/integration/**/*\"",
"test-client": "karma start ./test/percy-agent-client/karma.conf.js",
"test-integration": "yarn build-client && node ./bin/run exec -h *.localtest.me -- mocha test/integration/**/*.test.ts",
"test-integration": "yarn build-client && node ./bin/run exec -h *.localtest.me -c .ci.percy.yml -- mocha test/integration/**/*.test.ts",
"test-snapshot-command": "./bin/run snapshot test/integration/test-static-site -b /dummy-base-url -i '(red-keep)' -s '\\.(html)$'",
"test-upload-command": "./bin/run upload test/integration/test-static-images",
"version": "oclif-dev readme && git add README.md",
Expand Down
8 changes: 6 additions & 2 deletions src/commands/exec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { flags } from '@oclif/command'
import * as spawn from 'cross-spawn'
import { DEFAULT_CONFIGURATION } from '../configuration/configuration'
import ConfigurationService from '../services/configuration-service'
import config from '../utils/configuration'
import PercyCommand from './percy-command'

export default class Exec extends PercyCommand {
Expand Down Expand Up @@ -30,6 +30,10 @@ export default class Exec extends PercyCommand {
default: DEFAULT_CONFIGURATION.agent.port,
description: 'port',
}),
'config': flags.string({
char: 'c',
description: 'Path to percy config file',
}),
}

async run() {
Expand All @@ -46,7 +50,7 @@ export default class Exec extends PercyCommand {
}

if (this.percyWillRun()) {
await this.start(flags)
await this.start(config(flags))
}

// Even if Percy will not run, continue to run the subprocess
Expand Down
5 changes: 2 additions & 3 deletions src/commands/percy-command.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Command } from '@oclif/command'
import * as winston from 'winston'
import { Configuration } from '../configuration/configuration'
import { AgentService } from '../services/agent-service'
import ConfigurationService from '../services/configuration-service'
import ProcessService from '../services/process-service'
import logger from '../utils/logger'

Expand Down Expand Up @@ -47,9 +47,8 @@ export default class PercyCommand extends Command {
this.logger.info('percy has started.')
}

async start(flags: any) {
async start(configuration: Configuration) {
if (this.percyWillRun()) {
const configuration = new ConfigurationService().applyFlags(flags)
await this.agentService.start(configuration)
this.logStart()

Expand Down
14 changes: 7 additions & 7 deletions src/commands/snapshot.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { flags } from '@oclif/command'
import { existsSync } from 'fs'
import { DEFAULT_CONFIGURATION } from '../configuration/configuration'
import ConfigurationService from '../services/configuration-service'
import StaticSnapshotService from '../services/static-snapshot-service'
import config from '../utils/configuration'
import logger from '../utils/logger'
import PercyCommand from './percy-command'

Expand Down Expand Up @@ -55,17 +55,17 @@ export default class Snapshot extends PercyCommand {
default: DEFAULT_CONFIGURATION.agent.port,
description: 'Port',
}),
'config': flags.string({
char: 'c',
description: 'Path to percy config file',
}),
}

async run() {
await super.run()

const { args, flags } = this.parse(Snapshot)

const configurationService = new ConfigurationService()
configurationService.applyFlags(flags)
configurationService.applyArgs(args)
const configuration = configurationService.configuration
const configuration = config(flags, args)

// exit gracefully if percy will not run
if (!this.percyWillRun()) { this.exit(0) }
Expand All @@ -85,7 +85,7 @@ export default class Snapshot extends PercyCommand {
}

// start agent service and attach process handlers
await this.start(flags)
await this.start(configuration)

const staticSnapshotService = new StaticSnapshotService(configuration['static-snapshots'])

Expand Down
10 changes: 7 additions & 3 deletions src/commands/start.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {flags} from '@oclif/command'
import { flags } from '@oclif/command'
import * as path from 'path'
import { DEFAULT_CONFIGURATION } from '../configuration/configuration'
import ConfigurationService from '../services/configuration-service'
import config from '../utils/configuration'
import healthCheck from '../utils/health-checker'
import PercyCommand from './percy-command'

Expand Down Expand Up @@ -34,6 +34,10 @@ export default class Start extends PercyCommand {
default: DEFAULT_CONFIGURATION.agent.port,
description: 'port',
}),
'config': flags.string({
char: 'c',
description: 'Path to percy config file',
}),
}

async run() {
Expand All @@ -47,7 +51,7 @@ export default class Start extends PercyCommand {
if (flags.detached) {
this.runDetached(flags)
} else {
await this.start(flags)
await this.start(config(flags))
}

await healthCheck(flags.port!)
Expand Down
18 changes: 9 additions & 9 deletions src/commands/stop.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import {flags} from '@oclif/command'
import { flags } from '@oclif/command'
import Axios from 'axios'
import {DEFAULT_CONFIGURATION} from '../configuration/configuration'
import {STOP_PATH} from '../services/agent-service-constants'
import ConfigurationService from '../services/configuration-service'
import {logError} from '../utils/logger'
import { DEFAULT_CONFIGURATION } from '../configuration/configuration'
import { STOP_PATH } from '../services/agent-service-constants'
import config from '../utils/configuration'
import { logError } from '../utils/logger'
import PercyCommand from './percy-command'

export default class Stop extends PercyCommand {
Expand All @@ -29,18 +29,18 @@ export default class Stop extends PercyCommand {
// If Percy is disabled or is missing a token, gracefully exit here
if (!this.percyWillRun()) { this.exit(0) }

const {flags} = this.parse(Stop)
const configuration = new ConfigurationService().applyFlags(flags).agent
const { flags } = this.parse(Stop)
const configuration = config(flags)

if (this.processService.isRunning()) {
await this.postToRunningAgent(STOP_PATH, configuration.port)
await this.postToRunningAgent(STOP_PATH, configuration.agent.port)
} else {
this.logger.warn('percy is already stopped.')
}
}

private async postToRunningAgent(path: string, port: number) {
await Axios(`http://localhost:${port}${path}`, {method: 'POST'})
await Axios(`http://localhost:${port}${path}`, { method: 'POST' })
.catch((error: any) => {
if (error.message === 'socket hang up') { // We expect a hangup
this.logger.info('percy stopped.')
Expand Down
12 changes: 6 additions & 6 deletions src/commands/upload.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Command, flags } from '@oclif/command'
import { DEFAULT_CONFIGURATION } from '../configuration/configuration'
import ConfigurationService from '../services/configuration-service'
import ImageSnapshotService from '../services/image-snapshot-service'
import config from '../utils/configuration'

export default class Upload extends Command {
static description = 'Upload a directory containing static snapshot images.'
Expand Down Expand Up @@ -29,6 +29,10 @@ export default class Upload extends Command {
description: 'Glob or comma-seperated string of globs for matching the files and directories to ignore.',
default: DEFAULT_CONFIGURATION['image-snapshots'].ignore,
}),
config: flags.string({
char: 'c',
description: 'Path to percy config file',
}),
}

percyToken: string = process.env.PERCY_TOKEN || ''
Expand All @@ -45,11 +49,7 @@ export default class Upload extends Command {
}

const { args, flags } = this.parse(Upload)

const configurationService = new ConfigurationService()
configurationService.applyFlags(flags)
configurationService.applyArgs(args)
const configuration = configurationService.configuration
const configuration = config(flags, args)

// upload snapshot images
const imageSnapshotService = new ImageSnapshotService(configuration['image-snapshots'])
Expand Down
25 changes: 13 additions & 12 deletions src/services/agent-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ import { Server } from 'http'
import * as os from 'os'
import * as path from 'path'
import { Configuration } from '../configuration/configuration'
import { SnapshotConfiguration } from '../configuration/snapshot-configuration'
import { SnapshotOptions } from '../percy-agent-client/snapshot-options'
import logger, { createFileLogger, profile } from '../utils/logger'
import { HEALTHCHECK_PATH, SNAPSHOT_PATH, STOP_PATH } from './agent-service-constants'
import BuildService from './build-service'
import ConfigurationService from './configuration-service'
import Constants from './constants'
import ProcessService from './process-service'
import SnapshotService from './snapshot-service'
Expand All @@ -21,15 +21,16 @@ export class AgentService {
private readonly app: express.Application
private readonly publicDirectory: string = `${__dirname}/../../dist/public`
private snapshotCreationPromises: any[] = []
private snapshotConfig: SnapshotConfiguration | any = {}
private server: Server | null = null
private buildId: number | null = null

constructor() {
this.app = express()

this.app.use(cors())
this.app.use(bodyParser.urlencoded({extended: true}))
this.app.use(bodyParser.json({limit: '50mb'}))
this.app.use(bodyParser.urlencoded({ extended: true }))
this.app.use(bodyParser.json({ limit: '50mb' }))
this.app.use(express.static(this.publicDirectory))

this.app.post(SNAPSHOT_PATH, this.handleSnapshot.bind(this))
Expand All @@ -40,6 +41,7 @@ export class AgentService {
}

async start(configuration: Configuration) {
this.snapshotConfig = configuration.snapshot
this.buildId = await this.buildService.create()

if (this.buildId !== null) {
Expand Down Expand Up @@ -91,19 +93,18 @@ export class AgentService {
snapshotLogger.debug(`-> environmentInfo: ${request.body.environmentInfo}`)
snapshotLogger.debug(`-> domSnapshot: ${domSnapshotLog}`)

if (!this.snapshotService) { return response.json({success: false}) }
if (!this.snapshotService) { return response.json({ success: false }) }

const configuration = new ConfigurationService().configuration
// trim the string of whitespace and concat per-snapshot CSS with the globally specified CSS
const percySpecificCSS = configuration.snapshot['percy-css'].concat(request.body.percyCSS || '').trim()
const percySpecificCSS = this.snapshotConfig['percy-css'].concat(request.body.percyCSS || '').trim()
const hasWidths = !!request.body.widths && request.body.widths.length
const snapshotOptions: SnapshotOptions = {
percyCSS: percySpecificCSS,
widths: hasWidths ? request.body.widths : configuration.snapshot.widths,
widths: hasWidths ? request.body.widths : this.snapshotConfig.widths,
enableJavaScript: request.body.enableJavaScript != null
? request.body.enableJavaScript
: configuration.snapshot['enable-javascript'],
minHeight: request.body.minHeight || configuration.snapshot['min-height'],
: this.snapshotConfig['enable-javascript'],
minHeight: request.body.minHeight || this.snapshotConfig['min-height'],
}

let domSnapshot = request.body.domSnapshot
Expand Down Expand Up @@ -149,16 +150,16 @@ export class AgentService {
logger.info(`snapshot taken: '${request.body.name}'`)

profile('agentService.handleSnapshot')
return response.json({success: true})
return response.json({ success: true })
}

private async handleStop(_: express.Request, response: express.Response) {
await this.stop()
new ProcessService().kill()
return response.json({success: true})
return response.json({ success: true })
}

private async handleHealthCheck(_: express.Request, response: express.Response) {
return response.json({success: true})
return response.json({ success: true })
}
}
85 changes: 0 additions & 85 deletions src/services/configuration-service.ts

This file was deleted.

Loading

0 comments on commit b9875a1

Please sign in to comment.