From 5560d6ab8bca5db96ca41c4e8c581b4dfa0a3931 Mon Sep 17 00:00:00 2001 From: Robert DeLuca Date: Wed, 3 Apr 2019 17:21:37 -0500 Subject: [PATCH] feat: Add `healthcheck` command (#122) * Implement healthcheck command * Update ci cache key This should fix the following error in CI: ``` error computing cache key: template: cacheKey:1:47: executing "cacheKey" at : error calling checksum: open /home/circleci/cli/yarn.lock: no such file or directory ``` This is because we don't actually have a yarn lock file * Make the linter happy * Extend `Command`, remove `percyWillRun`. --- .circleci/config.yml | 2 +- src/commands/health-check.ts | 31 ++++++++++++++++++ src/utils/health-checker.ts | 3 +- test/commands/health-check.test.ts | 52 ++++++++++++++++++++++++++++++ 4 files changed, 86 insertions(+), 2 deletions(-) create mode 100644 src/commands/health-check.ts create mode 100644 test/commands/health-check.test.ts diff --git a/.circleci/config.yml b/.circleci/config.yml index 1400df67..f658c0df 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -12,7 +12,7 @@ jobs: - checkout - restore_cache: &restore_cache keys: - - v1-yarn-{{checksum ".circleci/config.yml"}}-{{ checksum "yarn.lock"}} + - v1-yarn-{{checksum ".circleci/config.yml"}}-{{ checksum "package-lock.json"}} - v1-yarn-{{checksum ".circleci/config.yml"}} - run: .circleci/greenkeeper - run: yarn add -D nyc@11 @oclif/nyc-config@1 mocha-junit-reporter@1 diff --git a/src/commands/health-check.ts b/src/commands/health-check.ts new file mode 100644 index 00000000..b34a23d1 --- /dev/null +++ b/src/commands/health-check.ts @@ -0,0 +1,31 @@ +import {Command, flags} from '@oclif/command' +import * as colors from 'colors' +import Constants from '../services/constants' +import healthCheck from '../utils/health-checker' + +export default class HealthCheck extends Command { + static description = 'Determines if the Percy Agent process is currently running' + static hidden = true + + static flags = { + port: flags.integer({ + char: 'p', + default: Constants.PORT, + description: 'port', + }), + } + + static examples = [ + '$ percy healthcheck', + '$ percy healthcheck --port 6884', + ] + + async run() { + const {flags} = this.parse(HealthCheck) + const port = flags.port as number + + await healthCheck(port, { + shouldRetry: () => false, + }) + } +} diff --git a/src/utils/health-checker.ts b/src/utils/health-checker.ts index 4253e785..b41ef356 100644 --- a/src/utils/health-checker.ts +++ b/src/utils/health-checker.ts @@ -2,13 +2,14 @@ import Axios from 'axios' import * as retryAxios from 'retry-axios' import logger from './logger' -async function healthCheck(port: number) { +async function healthCheck(port: number, retryOptions?: object) { const healthcheckUrl = `http://localhost:${port}/percy/healthcheck` const retryConfig = { retry: 5, // with exponential back off retryDelay: 500, shouldRetry: () => true, + ...retryOptions, } const interceptorId = retryAxios.attach() diff --git a/test/commands/health-check.test.ts b/test/commands/health-check.test.ts new file mode 100644 index 00000000..63489185 --- /dev/null +++ b/test/commands/health-check.test.ts @@ -0,0 +1,52 @@ +import * as chai from 'chai' +import {describe} from 'mocha' +import * as nock from 'nock' +import HealthCheck from '../../src/commands/health-check' +import {captureStdErr, captureStdOut} from '../helpers/stdout' + +const expect = chai.expect + +describe('Health check', () => { + describe('when agent is running', () => { + beforeEach(() => { + nock(/localhost/).get('/percy/healthcheck').reply(200) + }) + + afterEach(() => { + nock.cleanAll() + }) + + it('messages that agent is ready', async () => { + const stdout = await captureStdOut(async () => HealthCheck.run([])) + + expect(stdout).to.contain('[percy] percy is ready.') + }) + }) + + describe('when agent is not running', () => { + beforeEach(() => { + nock(/localhost/).get('/percy/healthcheck').reply(500) + }) + + afterEach(() => { + nock.cleanAll() + }) + + it('messages that agent is not ready', async () => { + const errorStdout = await captureStdErr(async () => HealthCheck.run([])) + + expect(errorStdout).to + .contain('[percy] Failed to establish a connection with http://localhost:5338/percy/healthcheck') + }) + + it('properly passes the port', async () => { + const port = '5899' + const errorStdout = await captureStdErr(async () => + HealthCheck.run(['--port', port]), + ) + + expect(errorStdout).to + .contain('[percy] Failed to establish a connection with http://localhost:5899/percy/healthcheck') + }) + }) +})