ci(docs-infra): rename 'upload-server' to 'preview-server' (#25554)
The server no longer has files uploaded to it. Instead it is more accurate to refer to it as dealing with "previews" of PRs. PR Close #25554
This commit is contained in:

committed by
Jason Aden

parent
860b79289f
commit
2acf369664
@ -13,7 +13,7 @@ export const AIO_NGINX_PORT_HTTP = +getEnvVar('AIO_NGINX_PORT_HTTP');
|
||||
export const AIO_NGINX_PORT_HTTPS = +getEnvVar('AIO_NGINX_PORT_HTTPS');
|
||||
export const AIO_SIGNIFICANT_FILES_PATTERN = getEnvVar('AIO_SIGNIFICANT_FILES_PATTERN');
|
||||
export const AIO_TRUSTED_PR_LABEL = getEnvVar('AIO_TRUSTED_PR_LABEL');
|
||||
export const AIO_UPLOAD_HOSTNAME = getEnvVar('AIO_UPLOAD_HOSTNAME');
|
||||
export const AIO_UPLOAD_PORT = +getEnvVar('AIO_UPLOAD_PORT');
|
||||
export const AIO_UPLOAD_MAX_SIZE = +getEnvVar('AIO_UPLOAD_MAX_SIZE');
|
||||
export const AIO_PREVIEW_SERVER_HOSTNAME = getEnvVar('AIO_PREVIEW_SERVER_HOSTNAME');
|
||||
export const AIO_PREVIEW_SERVER_PORT = +getEnvVar('AIO_PREVIEW_SERVER_PORT');
|
||||
export const AIO_ARTIFACT_MAX_SIZE = +getEnvVar('AIO_ARTIFACT_MAX_SIZE');
|
||||
export const AIO_WWW_USER = getEnvVar('AIO_WWW_USER');
|
||||
|
@ -1,5 +1,5 @@
|
||||
import {assert, assertNotMissingOrEmpty} from '../common/utils';
|
||||
import {GithubApi} from './github-api';
|
||||
import {assert, assertNotMissingOrEmpty} from './utils';
|
||||
|
||||
export interface PullRequest {
|
||||
number: number;
|
||||
|
@ -1,5 +1,5 @@
|
||||
import {assertNotMissingOrEmpty} from '../common/utils';
|
||||
import {GithubApi} from './github-api';
|
||||
import {assertNotMissingOrEmpty} from './utils';
|
||||
|
||||
export interface Team {
|
||||
id: number;
|
||||
|
@ -7,7 +7,7 @@ import * as shell from 'shelljs';
|
||||
import {HIDDEN_DIR_PREFIX} from '../common/constants';
|
||||
import {assertNotMissingOrEmpty, computeShortSha, createLogger} from '../common/utils';
|
||||
import {ChangedPrVisibilityEvent, CreatedBuildEvent} from './build-events';
|
||||
import {UploadError} from './upload-error';
|
||||
import {PreviewServerError} from './preview-error';
|
||||
|
||||
// Classes
|
||||
export class BuildCreator extends EventEmitter {
|
||||
@ -36,7 +36,7 @@ export class BuildCreator extends EventEmitter {
|
||||
then(([prDirExisted, shaDirExisted]) => {
|
||||
if (shaDirExisted) {
|
||||
const publicOrNot = isPublic ? 'public' : 'non-public';
|
||||
throw new UploadError(409, `Request to overwrite existing ${publicOrNot} directory: ${shaDir}`);
|
||||
throw new PreviewServerError(409, `Request to overwrite existing ${publicOrNot} directory: ${shaDir}`);
|
||||
}
|
||||
|
||||
dirToRemoveOnError = prDirExisted ? shaDir : prDir;
|
||||
@ -52,8 +52,8 @@ export class BuildCreator extends EventEmitter {
|
||||
shell.rm('-rf', dirToRemoveOnError);
|
||||
}
|
||||
|
||||
if (!(err instanceof UploadError)) {
|
||||
err = new UploadError(500, `Error while uploading to directory: ${shaDir}\n${err}`);
|
||||
if (!(err instanceof PreviewServerError)) {
|
||||
err = new PreviewServerError(500, `Error while creating preview at: ${shaDir}\n${err}`);
|
||||
}
|
||||
|
||||
throw err;
|
||||
@ -71,7 +71,8 @@ export class BuildCreator extends EventEmitter {
|
||||
return false;
|
||||
} else if (targetVisPrDirExisted) {
|
||||
// Error: Directories for both visibilities exist.
|
||||
throw new UploadError(409, `Request to move '${otherVisPrDir}' to existing directory '${targetVisPrDir}'.`);
|
||||
throw new PreviewServerError(409,
|
||||
`Request to move '${otherVisPrDir}' to existing directory '${targetVisPrDir}'.`);
|
||||
}
|
||||
|
||||
// Visibility change: Moving `otherVisPrDir` to `targetVisPrDir`.
|
||||
@ -82,8 +83,8 @@ export class BuildCreator extends EventEmitter {
|
||||
then(() => true);
|
||||
}).
|
||||
catch(err => {
|
||||
if (!(err instanceof UploadError)) {
|
||||
err = new UploadError(500, `Error while making PR ${pr} ${makePublic ? 'public' : 'hidden'}.\n${err}`);
|
||||
if (!(err instanceof PreviewServerError)) {
|
||||
err = new PreviewServerError(500, `Error while making PR ${pr} ${makePublic ? 'public' : 'hidden'}.\n${err}`);
|
||||
}
|
||||
|
||||
throw err;
|
@ -5,7 +5,7 @@ import {mkdir} from 'shelljs';
|
||||
import {promisify} from 'util';
|
||||
import {CircleCiApi} from '../common/circle-ci-api';
|
||||
import {assert, assertNotMissingOrEmpty, computeArtifactDownloadPath, createLogger} from '../common/utils';
|
||||
import {UploadError} from '../upload-server/upload-error';
|
||||
import {PreviewServerError} from './preview-error';
|
||||
|
||||
export interface GithubInfo {
|
||||
org: string;
|
||||
@ -58,7 +58,7 @@ export class BuildRetriever {
|
||||
const url = await this.api.getBuildArtifactUrl(buildNum, artifactPath);
|
||||
const response = await fetch(url, {size: this.downloadSizeLimit});
|
||||
if (response.status !== 200) {
|
||||
throw new UploadError(response.status, `Error ${response.status} - ${response.statusText}`);
|
||||
throw new PreviewServerError(response.status, `Error ${response.status} - ${response.statusText}`);
|
||||
}
|
||||
const buffer = await response.buffer();
|
||||
mkdir('-p', dirname(outPath));
|
||||
@ -68,7 +68,7 @@ export class BuildRetriever {
|
||||
} catch (error) {
|
||||
this.logger.warn(error);
|
||||
const status = (error.type === 'max-size') ? 413 : 500;
|
||||
throw new UploadError(status, `CircleCI artifact download failed (${error.message || error})`);
|
||||
throw new PreviewServerError(status, `CircleCI artifact download failed (${error.message || error})`);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
// Imports
|
||||
import {AIO_DOWNLOADS_DIR} from '../common/constants';
|
||||
import {
|
||||
AIO_ARTIFACT_MAX_SIZE,
|
||||
AIO_ARTIFACT_PATH,
|
||||
AIO_BUILDS_DIR,
|
||||
AIO_CIRCLE_CI_TOKEN,
|
||||
@ -9,26 +10,25 @@ import {
|
||||
AIO_GITHUB_REPO,
|
||||
AIO_GITHUB_TEAM_SLUGS,
|
||||
AIO_GITHUB_TOKEN,
|
||||
AIO_PREVIEW_SERVER_HOSTNAME,
|
||||
AIO_PREVIEW_SERVER_PORT,
|
||||
AIO_SIGNIFICANT_FILES_PATTERN,
|
||||
AIO_TRUSTED_PR_LABEL,
|
||||
AIO_UPLOAD_HOSTNAME,
|
||||
AIO_UPLOAD_MAX_SIZE,
|
||||
AIO_UPLOAD_PORT,
|
||||
} from '../common/env-variables';
|
||||
import {UploadServerFactory} from './upload-server-factory';
|
||||
import {PreviewServerFactory} from './preview-server-factory';
|
||||
|
||||
// Run
|
||||
_main();
|
||||
|
||||
// Functions
|
||||
function _main(): void {
|
||||
UploadServerFactory
|
||||
PreviewServerFactory
|
||||
.create({
|
||||
buildArtifactPath: AIO_ARTIFACT_PATH,
|
||||
buildsDir: AIO_BUILDS_DIR,
|
||||
circleCiToken: AIO_CIRCLE_CI_TOKEN,
|
||||
domainName: AIO_DOMAIN_NAME,
|
||||
downloadSizeLimit: AIO_UPLOAD_MAX_SIZE,
|
||||
downloadSizeLimit: AIO_ARTIFACT_MAX_SIZE,
|
||||
downloadsDir: AIO_DOWNLOADS_DIR,
|
||||
githubOrg: AIO_GITHUB_ORGANIZATION,
|
||||
githubRepo: AIO_GITHUB_REPO,
|
||||
@ -37,5 +37,5 @@ function _main(): void {
|
||||
significantFilesPattern: AIO_SIGNIFICANT_FILES_PATTERN,
|
||||
trustedPrLabel: AIO_TRUSTED_PR_LABEL,
|
||||
})
|
||||
.listen(AIO_UPLOAD_PORT, AIO_UPLOAD_HOSTNAME);
|
||||
.listen(AIO_PREVIEW_SERVER_PORT, AIO_PREVIEW_SERVER_HOSTNAME);
|
||||
}
|
@ -1,8 +1,8 @@
|
||||
// Classes
|
||||
export class UploadError extends Error {
|
||||
export class PreviewServerError extends Error {
|
||||
// Constructor
|
||||
constructor(public status: number = 500, message?: string) {
|
||||
super(message);
|
||||
Object.setPrototypeOf(this, UploadError.prototype);
|
||||
Object.setPrototypeOf(this, PreviewServerError.prototype);
|
||||
}
|
||||
}
|
@ -16,7 +16,7 @@ import {respondWithError, throwRequestError} from './utils';
|
||||
const AIO_PREVIEW_JOB = 'aio_preview';
|
||||
|
||||
// Interfaces - Types
|
||||
export interface UploadServerConfig {
|
||||
export interface PreviewServerConfig {
|
||||
downloadsDir: string;
|
||||
downloadSizeLimit: number;
|
||||
buildArtifactPath: string;
|
||||
@ -31,12 +31,12 @@ export interface UploadServerConfig {
|
||||
trustedPrLabel: string;
|
||||
}
|
||||
|
||||
const logger = createLogger('UploadServer');
|
||||
const logger = createLogger('PreviewServer');
|
||||
|
||||
// Classes
|
||||
export class UploadServerFactory {
|
||||
export class PreviewServerFactory {
|
||||
// Methods - Public
|
||||
public static create(cfg: UploadServerConfig): http.Server {
|
||||
public static create(cfg: PreviewServerConfig): http.Server {
|
||||
assertNotMissingOrEmpty('domainName', cfg.domainName);
|
||||
|
||||
const circleCiApi = new CircleCiApi(cfg.githubOrg, cfg.githubRepo, cfg.circleCiToken);
|
||||
@ -46,9 +46,9 @@ export class UploadServerFactory {
|
||||
|
||||
const buildRetriever = new BuildRetriever(circleCiApi, cfg.downloadSizeLimit, cfg.downloadsDir);
|
||||
const buildVerifier = new BuildVerifier(prs, teams, cfg.githubTeamSlugs, cfg.trustedPrLabel);
|
||||
const buildCreator = UploadServerFactory.createBuildCreator(prs, cfg.buildsDir, cfg.domainName);
|
||||
const buildCreator = PreviewServerFactory.createBuildCreator(prs, cfg.buildsDir, cfg.domainName);
|
||||
|
||||
const middleware = UploadServerFactory.createMiddleware(buildRetriever, buildVerifier, buildCreator, cfg);
|
||||
const middleware = PreviewServerFactory.createMiddleware(buildRetriever, buildVerifier, buildCreator, cfg);
|
||||
const httpServer = http.createServer(middleware as any);
|
||||
|
||||
httpServer.on('listening', () => {
|
||||
@ -60,7 +60,7 @@ export class UploadServerFactory {
|
||||
}
|
||||
|
||||
public static createMiddleware(buildRetriever: BuildRetriever, buildVerifier: BuildVerifier,
|
||||
buildCreator: BuildCreator, cfg: UploadServerConfig): express.Express {
|
||||
buildCreator: BuildCreator, cfg: PreviewServerConfig): express.Express {
|
||||
const middleware = express();
|
||||
const jsonParser = bodyParser.json();
|
||||
|
||||
@ -149,7 +149,7 @@ export class UploadServerFactory {
|
||||
middleware.all('*', req => throwRequestError(404, 'Unknown resource', req));
|
||||
middleware.use((err: any, _req: any, res: express.Response, _next: any) => {
|
||||
const statusText = http.STATUS_CODES[err.status] || '???';
|
||||
logger.error(`Upload error: ${err.status} - ${statusText}:`, err.message);
|
||||
logger.error(`Preview server error: ${err.status} - ${statusText}:`, err.message);
|
||||
respondWithError(res, err);
|
||||
});
|
||||
|
@ -1,6 +1,6 @@
|
||||
import * as express from 'express';
|
||||
import {promisify} from 'util';
|
||||
import {UploadError} from './upload-error';
|
||||
import {PreviewServerError} from './preview-error';
|
||||
|
||||
/**
|
||||
* Update the response to report that an error has occurred.
|
||||
@ -8,8 +8,8 @@ import {UploadError} from './upload-error';
|
||||
* @param err The error that needs to be reported.
|
||||
*/
|
||||
export async function respondWithError(res: express.Response, err: any): Promise<void> {
|
||||
if (!(err instanceof UploadError)) {
|
||||
err = new UploadError(500, String((err && err.message) || err));
|
||||
if (!(err instanceof PreviewServerError)) {
|
||||
err = new PreviewServerError(500, String((err && err.message) || err));
|
||||
}
|
||||
|
||||
res.status(err.status);
|
||||
@ -25,5 +25,5 @@ export async function respondWithError(res: express.Response, err: any): Promise
|
||||
export function throwRequestError(status: number, error: string, req: express.Request): never {
|
||||
const message = `${error} in request: ${req.method} ${req.originalUrl}` +
|
||||
(!req.body ? '' : ` ${JSON.stringify(req.body)}`);
|
||||
throw new UploadError(status, message);
|
||||
throw new PreviewServerError(status, message);
|
||||
}
|
@ -6,9 +6,9 @@ import {createLogger, getEnvVar} from '../common/utils';
|
||||
import {BuildNums, PrNums, SHA} from './constants';
|
||||
|
||||
// We are using the `nock` library to fake responses from REST requests, when testing.
|
||||
// This is necessary, because the test upload-server runs as a separate node process to
|
||||
// This is necessary, because the test preview-server runs as a separate node process to
|
||||
// the test harness, so we do not have direct access to the code (e.g. for mocking).
|
||||
// (See also 'lib/verify-setup/start-test-upload-server.ts'.)
|
||||
// (See also 'lib/verify-setup/start-test-preview-server.ts'.)
|
||||
|
||||
// Each of the potential requests to an external API (e.g. Github or CircleCI) are mocked
|
||||
// below and return a suitable response. This is quite complicated to setup since the
|
||||
|
@ -266,7 +266,7 @@ describe(`nginx`, () => {
|
||||
});
|
||||
|
||||
|
||||
it('should pass requests through to the upload server', done => {
|
||||
it('should pass requests through to the preview server', done => {
|
||||
h.runCmd(`curl -iLX POST ${scheme}://${host}/circle-build`).
|
||||
then(h.verifyResponse(400, /Incorrect body content. Expected JSON/)).
|
||||
then(done);
|
||||
@ -304,7 +304,7 @@ describe(`nginx`, () => {
|
||||
});
|
||||
|
||||
|
||||
it('should pass requests through to the upload server', done => {
|
||||
it('should pass requests through to the preview server', done => {
|
||||
const cmdPrefix = `curl -iLX POST --header "Content-Type: application/json"`;
|
||||
|
||||
const cmd1 = `${cmdPrefix} ${url}`;
|
||||
|
@ -1,16 +1,16 @@
|
||||
// Imports
|
||||
import * as fs from 'fs';
|
||||
import {join} from 'path';
|
||||
import {AIO_UPLOAD_HOSTNAME, AIO_UPLOAD_PORT, AIO_WWW_USER} from '../common/env-variables';
|
||||
import {AIO_PREVIEW_SERVER_HOSTNAME, AIO_PREVIEW_SERVER_PORT, AIO_WWW_USER} from '../common/env-variables';
|
||||
import {computeShortSha} from '../common/utils';
|
||||
import {ALT_SHA, BuildNums, PrNums, SHA, SIMILAR_SHA} from './constants';
|
||||
import {helper as h, makeCurl, payload} from './helper';
|
||||
import {customMatchers} from './jasmine-custom-matchers';
|
||||
|
||||
// Tests
|
||||
describe('upload-server', () => {
|
||||
const hostname = AIO_UPLOAD_HOSTNAME;
|
||||
const port = AIO_UPLOAD_PORT;
|
||||
describe('preview-server', () => {
|
||||
const hostname = AIO_PREVIEW_SERVER_HOSTNAME;
|
||||
const port = AIO_PREVIEW_SERVER_PORT;
|
||||
const host = `http://${hostname}:${port}`;
|
||||
|
||||
beforeEach(() => jasmine.DEFAULT_TIMEOUT_INTERVAL = 5000);
|
||||
@ -122,7 +122,7 @@ describe('upload-server', () => {
|
||||
|
||||
describe(`for ${label} builds`, () => {
|
||||
|
||||
it('should extract the contents of the uploaded file', async () => {
|
||||
it('should extract the contents of the build artifact', async () => {
|
||||
await curl(payload(build))
|
||||
.then(h.verifyResponse(statusCode));
|
||||
expect(h.readBuildFile(prNum, SHA, 'index.html', isPublic))
|
||||
@ -148,7 +148,7 @@ describe('upload-server', () => {
|
||||
expect({ prNum, isPublic }).toExistAsABuild();
|
||||
});
|
||||
|
||||
it('should delete the uploaded file', async () => {
|
||||
it('should delete the build artifact file', async () => {
|
||||
await curl(payload(build))
|
||||
.then(h.verifyResponse(statusCode));
|
||||
expect({ prNum, SHA }).not.toExistAsAnArtifact();
|
@ -25,7 +25,7 @@ h.runForAllSupportedSchemes((scheme, port) => describe(`integration (on ${scheme
|
||||
|
||||
describe('for a new/non-existing PR', () => {
|
||||
|
||||
it('should be able to upload and serve a public build', async () => {
|
||||
it('should be able to create and serve a public preview', async () => {
|
||||
const BUILD = BuildNums.TRUST_CHECK_ACTIVE_TRUSTED_USER;
|
||||
const PR = PrNums.TRUST_CHECK_ACTIVE_TRUSTED_USER;
|
||||
|
||||
@ -44,7 +44,7 @@ h.runForAllSupportedSchemes((scheme, port) => describe(`integration (on ${scheme
|
||||
});
|
||||
|
||||
|
||||
it('should be able to upload but not serve a hidden build', async () => {
|
||||
it('should be able to create but not serve a hidden preview', async () => {
|
||||
const BUILD = BuildNums.TRUST_CHECK_UNTRUSTED;
|
||||
const PR = PrNums.TRUST_CHECK_UNTRUSTED;
|
||||
|
||||
@ -59,7 +59,7 @@ h.runForAllSupportedSchemes((scheme, port) => describe(`integration (on ${scheme
|
||||
});
|
||||
|
||||
|
||||
it('should reject an upload if verification fails', async () => {
|
||||
it('should reject if verification fails', async () => {
|
||||
const BUILD = BuildNums.TRUST_CHECK_ERROR;
|
||||
const PR = PrNums.TRUST_CHECK_ERROR;
|
||||
|
||||
@ -82,7 +82,7 @@ h.runForAllSupportedSchemes((scheme, port) => describe(`integration (on ${scheme
|
||||
|
||||
describe('for an existing PR', () => {
|
||||
|
||||
it('should be able to upload and serve a public build', async () => {
|
||||
it('should be able to create and serve a public preview', async () => {
|
||||
const BUILD = BuildNums.TRUST_CHECK_ACTIVE_TRUSTED_USER;
|
||||
const PR = PrNums.TRUST_CHECK_ACTIVE_TRUSTED_USER;
|
||||
|
||||
@ -108,7 +108,7 @@ h.runForAllSupportedSchemes((scheme, port) => describe(`integration (on ${scheme
|
||||
});
|
||||
|
||||
|
||||
it('should be able to upload but not serve a hidden build', async () => {
|
||||
it('should be able to create but not serve a hidden preview', async () => {
|
||||
const BUILD = BuildNums.TRUST_CHECK_UNTRUSTED;
|
||||
const PR = PrNums.TRUST_CHECK_UNTRUSTED;
|
||||
|
||||
@ -129,7 +129,7 @@ h.runForAllSupportedSchemes((scheme, port) => describe(`integration (on ${scheme
|
||||
});
|
||||
|
||||
|
||||
it('should reject an upload if verification fails', async () => {
|
||||
it('should reject if verification fails', async () => {
|
||||
const BUILD = BuildNums.TRUST_CHECK_ERROR;
|
||||
const PR = PrNums.TRUST_CHECK_ERROR;
|
||||
|
||||
@ -144,7 +144,7 @@ h.runForAllSupportedSchemes((scheme, port) => describe(`integration (on ${scheme
|
||||
});
|
||||
|
||||
|
||||
it('should not be able to overwrite an existing public build', async () => {
|
||||
it('should not be able to overwrite an existing public preview', async () => {
|
||||
const BUILD = BuildNums.TRUST_CHECK_ACTIVE_TRUSTED_USER;
|
||||
const PR = PrNums.TRUST_CHECK_ACTIVE_TRUSTED_USER;
|
||||
|
||||
@ -165,7 +165,7 @@ h.runForAllSupportedSchemes((scheme, port) => describe(`integration (on ${scheme
|
||||
});
|
||||
|
||||
|
||||
it('should not be able to overwrite an existing hidden build', async () => {
|
||||
it('should not be able to overwrite an existing hidden preview', async () => {
|
||||
const BUILD = BuildNums.TRUST_CHECK_UNTRUSTED;
|
||||
const PR = PrNums.TRUST_CHECK_UNTRUSTED;
|
||||
h.createDummyBuild(PR, SHA, false);
|
||||
|
@ -1,2 +1,2 @@
|
||||
import '../upload-server';
|
||||
import '../preview-server';
|
||||
import './mock-external-apis';
|
@ -5,10 +5,10 @@ import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import * as shell from 'shelljs';
|
||||
import {SHORT_SHA_LEN} from '../../lib/common/constants';
|
||||
import {BuildCreator} from '../../lib/upload-server/build-creator';
|
||||
import {ChangedPrVisibilityEvent, CreatedBuildEvent} from '../../lib/upload-server/build-events';
|
||||
import {UploadError} from '../../lib/upload-server/upload-error';
|
||||
import {expectToBeUploadError} from './helpers';
|
||||
import {BuildCreator} from '../../lib/preview-server/build-creator';
|
||||
import {ChangedPrVisibilityEvent, CreatedBuildEvent} from '../../lib/preview-server/build-events';
|
||||
import {PreviewServerError} from '../../lib/preview-server/preview-error';
|
||||
import {expectToBePreviewServerError} from './helpers';
|
||||
|
||||
// Tests
|
||||
describe('BuildCreator', () => {
|
||||
@ -134,7 +134,7 @@ describe('BuildCreator', () => {
|
||||
|
||||
|
||||
it('should abort and skip further operations if changing the PR\'s visibility fails', done => {
|
||||
const mockError = new UploadError(543, 'Test');
|
||||
const mockError = new PreviewServerError(543, 'Test');
|
||||
bcUpdatePrVisibilitySpy.and.callFake(() => Promise.reject(mockError));
|
||||
|
||||
bc.create(pr, sha, archive, isPublic).catch(err => {
|
||||
@ -154,7 +154,7 @@ describe('BuildCreator', () => {
|
||||
existsValues[shaDir] = true;
|
||||
bc.create(pr, sha, archive, isPublic).catch(err => {
|
||||
const publicOrNot = isPublic ? 'public' : 'non-public';
|
||||
expectToBeUploadError(err, 409, `Request to overwrite existing ${publicOrNot} directory: ${shaDir}`);
|
||||
expectToBePreviewServerError(err, 409, `Request to overwrite existing ${publicOrNot} directory: ${shaDir}`);
|
||||
expect(shellMkdirSpy).not.toHaveBeenCalled();
|
||||
expect(bcExtractArchiveSpy).not.toHaveBeenCalled();
|
||||
expect(bcEmitSpy).not.toHaveBeenCalled();
|
||||
@ -171,7 +171,7 @@ describe('BuildCreator', () => {
|
||||
|
||||
bc.create(pr, sha, archive, isPublic).catch(err => {
|
||||
const publicOrNot = isPublic ? 'public' : 'non-public';
|
||||
expectToBeUploadError(err, 409, `Request to overwrite existing ${publicOrNot} directory: ${shaDir}`);
|
||||
expectToBePreviewServerError(err, 409, `Request to overwrite existing ${publicOrNot} directory: ${shaDir}`);
|
||||
expect(shellMkdirSpy).not.toHaveBeenCalled();
|
||||
expect(bcExtractArchiveSpy).not.toHaveBeenCalled();
|
||||
expect(bcEmitSpy).not.toHaveBeenCalled();
|
||||
@ -222,20 +222,20 @@ describe('BuildCreator', () => {
|
||||
});
|
||||
|
||||
|
||||
it('should reject with an UploadError', done => {
|
||||
it('should reject with an PreviewServerError', done => {
|
||||
// tslint:disable-next-line: no-string-throw
|
||||
shellMkdirSpy.and.callFake(() => { throw 'Test'; });
|
||||
bc.create(pr, sha, archive, isPublic).catch(err => {
|
||||
expectToBeUploadError(err, 500, `Error while uploading to directory: ${shaDir}\nTest`);
|
||||
expectToBePreviewServerError(err, 500, `Error while creating preview at: ${shaDir}\nTest`);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
it('should pass UploadError instances unmodified', done => {
|
||||
shellMkdirSpy.and.callFake(() => { throw new UploadError(543, 'Test'); });
|
||||
it('should pass PreviewServerError instances unmodified', done => {
|
||||
shellMkdirSpy.and.callFake(() => { throw new PreviewServerError(543, 'Test'); });
|
||||
bc.create(pr, sha, archive, isPublic).catch(err => {
|
||||
expectToBeUploadError(err, 543, 'Test');
|
||||
expectToBePreviewServerError(err, 543, 'Test');
|
||||
done();
|
||||
});
|
||||
});
|
||||
@ -376,7 +376,8 @@ describe('BuildCreator', () => {
|
||||
it('should abort and skip further operations if both directories exist', done => {
|
||||
bcExistsSpy.and.returnValue(true);
|
||||
bc.updatePrVisibility(pr, makePublic).catch(err => {
|
||||
expectToBeUploadError(err, 409, `Request to move '${oldPrDir}' to existing directory '${newPrDir}'.`);
|
||||
expectToBePreviewServerError(err, 409,
|
||||
`Request to move '${oldPrDir}' to existing directory '${newPrDir}'.`);
|
||||
expect(shellMvSpy).not.toHaveBeenCalled();
|
||||
expect(bcListShasByDate).not.toHaveBeenCalled();
|
||||
expect(bcEmitSpy).not.toHaveBeenCalled();
|
||||
@ -407,20 +408,21 @@ describe('BuildCreator', () => {
|
||||
});
|
||||
|
||||
|
||||
it('should reject with an UploadError', done => {
|
||||
it('should reject with an PreviewServerError', done => {
|
||||
// tslint:disable-next-line: no-string-throw
|
||||
shellMvSpy.and.callFake(() => { throw 'Test'; });
|
||||
bc.updatePrVisibility(pr, makePublic).catch(err => {
|
||||
expectToBeUploadError(err, 500, `Error while making PR ${pr} ${makePublic ? 'public' : 'hidden'}.\nTest`);
|
||||
expectToBePreviewServerError(err, 500,
|
||||
`Error while making PR ${pr} ${makePublic ? 'public' : 'hidden'}.\nTest`);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
it('should pass UploadError instances unmodified', done => {
|
||||
shellMvSpy.and.callFake(() => { throw new UploadError(543, 'Test'); });
|
||||
it('should pass PreviewServerError instances unmodified', done => {
|
||||
shellMvSpy.and.callFake(() => { throw new PreviewServerError(543, 'Test'); });
|
||||
bc.updatePrVisibility(pr, makePublic).catch(err => {
|
||||
expectToBeUploadError(err, 543, 'Test');
|
||||
expectToBePreviewServerError(err, 543, 'Test');
|
||||
done();
|
||||
});
|
||||
});
|
||||
@ -528,7 +530,7 @@ describe('BuildCreator', () => {
|
||||
});
|
||||
|
||||
|
||||
it('should delete the uploaded file on success', done => {
|
||||
it('should delete the build artifact file on success', done => {
|
||||
(bc as any).extractArchive('input/file', 'output/dir').
|
||||
then(() => expect(shellRmSpy).toHaveBeenCalledWith('-f', 'input/file')).
|
||||
then(done);
|
||||
@ -568,7 +570,7 @@ describe('BuildCreator', () => {
|
||||
});
|
||||
|
||||
|
||||
it('should abort and reject if it fails to remove the uploaded file', done => {
|
||||
it('should abort and reject if it fails to remove the build artifact file', done => {
|
||||
(bc as any).extractArchive('foo', 'bar').catch((err: any) => {
|
||||
expect(shellChmodSpy).toHaveBeenCalled();
|
||||
expect(shellRmSpy).toHaveBeenCalled();
|
@ -1,5 +1,5 @@
|
||||
// Imports
|
||||
import {ChangedPrVisibilityEvent, CreatedBuildEvent} from '../../lib/upload-server/build-events';
|
||||
import {ChangedPrVisibilityEvent, CreatedBuildEvent} from '../../lib/preview-server/build-events';
|
||||
|
||||
// Tests
|
||||
describe('ChangedPrVisibilityEvent', () => {
|
@ -1,7 +1,7 @@
|
||||
import * as fs from 'fs';
|
||||
import * as nock from 'nock';
|
||||
import {BuildInfo, CircleCiApi} from '../../lib/common/circle-ci-api';
|
||||
import {BuildRetriever} from '../../lib/upload-server/build-retriever';
|
||||
import {BuildRetriever} from '../../lib/preview-server/build-retriever';
|
||||
|
||||
describe('BuildRetriever', () => {
|
||||
const MAX_DOWNLOAD_SIZE = 10000;
|
@ -2,7 +2,7 @@
|
||||
import {GithubApi} from '../../lib/common/github-api';
|
||||
import {GithubPullRequests, PullRequest} from '../../lib/common/github-pull-requests';
|
||||
import {GithubTeams} from '../../lib/common/github-teams';
|
||||
import {BuildVerifier} from '../../lib/upload-server/build-verifier';
|
||||
import {BuildVerifier} from '../../lib/preview-server/build-verifier';
|
||||
|
||||
// Tests
|
||||
describe('BuildVerifier', () => {
|
@ -0,0 +1,11 @@
|
||||
import {PreviewServerError} from '../../lib/preview-server/preview-error';
|
||||
|
||||
export const expectToBePreviewServerError = (actual: PreviewServerError, status?: number, message?: string) => {
|
||||
expect(actual).toEqual(jasmine.any(PreviewServerError));
|
||||
if (status != null) {
|
||||
expect(actual.status).toBe(status);
|
||||
}
|
||||
if (message != null) {
|
||||
expect(actual.message).toBe(message);
|
||||
}
|
||||
};
|
@ -0,0 +1,39 @@
|
||||
// Imports
|
||||
import {PreviewServerError} from '../../lib/preview-server/preview-error';
|
||||
|
||||
// Tests
|
||||
describe('PreviewServerError', () => {
|
||||
let err: PreviewServerError;
|
||||
|
||||
beforeEach(() => err = new PreviewServerError(999, 'message'));
|
||||
|
||||
|
||||
it('should extend Error', () => {
|
||||
expect(err).toEqual(jasmine.any(PreviewServerError));
|
||||
expect(err).toEqual(jasmine.any(Error));
|
||||
|
||||
expect(Object.getPrototypeOf(err)).toBe(PreviewServerError.prototype);
|
||||
});
|
||||
|
||||
|
||||
it('should have a \'status\' property', () => {
|
||||
expect(err.status).toBe(999);
|
||||
});
|
||||
|
||||
|
||||
it('should have a \'message\' property', () => {
|
||||
expect(err.message).toBe('message');
|
||||
});
|
||||
|
||||
|
||||
it('should have a 500 \'status\' by default', () => {
|
||||
expect(new PreviewServerError().status).toBe(500);
|
||||
});
|
||||
|
||||
|
||||
it('should have an empty \'message\' by default', () => {
|
||||
expect(new PreviewServerError().message).toBe('');
|
||||
expect(new PreviewServerError(999).message).toBe('');
|
||||
});
|
||||
|
||||
});
|
@ -7,11 +7,11 @@ import {CircleCiApi} from '../../lib/common/circle-ci-api';
|
||||
import {GithubApi} from '../../lib/common/github-api';
|
||||
import {GithubPullRequests} from '../../lib/common/github-pull-requests';
|
||||
import {GithubTeams} from '../../lib/common/github-teams';
|
||||
import {BuildCreator} from '../../lib/upload-server/build-creator';
|
||||
import {ChangedPrVisibilityEvent, CreatedBuildEvent} from '../../lib/upload-server/build-events';
|
||||
import {BuildRetriever, GithubInfo} from '../../lib/upload-server/build-retriever';
|
||||
import {BuildVerifier} from '../../lib/upload-server/build-verifier';
|
||||
import {UploadServerConfig, UploadServerFactory} from '../../lib/upload-server/upload-server-factory';
|
||||
import {BuildCreator} from '../../lib/preview-server/build-creator';
|
||||
import {ChangedPrVisibilityEvent, CreatedBuildEvent} from '../../lib/preview-server/build-events';
|
||||
import {BuildRetriever, GithubInfo} from '../../lib/preview-server/build-retriever';
|
||||
import {BuildVerifier} from '../../lib/preview-server/build-verifier';
|
||||
import {PreviewServerConfig, PreviewServerFactory} from '../../lib/preview-server/preview-server-factory';
|
||||
|
||||
interface CircleCiWebHookPayload {
|
||||
payload: {
|
||||
@ -23,8 +23,8 @@ interface CircleCiWebHookPayload {
|
||||
}
|
||||
|
||||
// Tests
|
||||
describe('uploadServerFactory', () => {
|
||||
const defaultConfig: UploadServerConfig = {
|
||||
describe('PreviewServerFactory', () => {
|
||||
const defaultConfig: PreviewServerConfig = {
|
||||
buildArtifactPath: 'artifact/path.zip',
|
||||
buildsDir: 'builds/dir',
|
||||
circleCiToken: 'CIRCLE_CI_TOKEN',
|
||||
@ -40,8 +40,8 @@ describe('uploadServerFactory', () => {
|
||||
};
|
||||
|
||||
// Helpers
|
||||
const createUploadServer = (partialConfig: Partial<UploadServerConfig> = {}) =>
|
||||
UploadServerFactory.create({...defaultConfig, ...partialConfig});
|
||||
const createPreviewServer = (partialConfig: Partial<PreviewServerConfig> = {}) =>
|
||||
PreviewServerFactory.create({...defaultConfig, ...partialConfig});
|
||||
|
||||
beforeEach(() => {
|
||||
spyOn(console, 'error');
|
||||
@ -53,64 +53,64 @@ describe('uploadServerFactory', () => {
|
||||
let usfCreateMiddlewareSpy: jasmine.Spy;
|
||||
|
||||
beforeEach(() => {
|
||||
usfCreateMiddlewareSpy = spyOn(UploadServerFactory, 'createMiddleware').and.callThrough();
|
||||
usfCreateMiddlewareSpy = spyOn(PreviewServerFactory, 'createMiddleware').and.callThrough();
|
||||
});
|
||||
|
||||
|
||||
it('should throw if \'buildsDir\' is missing or empty', () => {
|
||||
expect(() => createUploadServer({buildsDir: ''})).
|
||||
expect(() => createPreviewServer({buildsDir: ''})).
|
||||
toThrowError('Missing or empty required parameter \'buildsDir\'!');
|
||||
});
|
||||
|
||||
|
||||
it('should throw if \'domainName\' is missing or empty', () => {
|
||||
expect(() => createUploadServer({domainName: ''})).
|
||||
expect(() => createPreviewServer({domainName: ''})).
|
||||
toThrowError('Missing or empty required parameter \'domainName\'!');
|
||||
});
|
||||
|
||||
|
||||
it('should throw if \'githubToken\' is missing or empty', () => {
|
||||
expect(() => createUploadServer({githubToken: ''})).
|
||||
expect(() => createPreviewServer({githubToken: ''})).
|
||||
toThrowError('Missing or empty required parameter \'githubToken\'!');
|
||||
});
|
||||
|
||||
|
||||
it('should throw if \'githubOrg\' is missing or empty', () => {
|
||||
expect(() => createUploadServer({githubOrg: ''})).
|
||||
expect(() => createPreviewServer({githubOrg: ''})).
|
||||
toThrowError('Missing or empty required parameter \'githubOrg\'!');
|
||||
});
|
||||
|
||||
|
||||
it('should throw if \'githubTeamSlugs\' is missing or empty', () => {
|
||||
expect(() => createUploadServer({githubTeamSlugs: []})).
|
||||
expect(() => createPreviewServer({githubTeamSlugs: []})).
|
||||
toThrowError('Missing or empty required parameter \'allowedTeamSlugs\'!');
|
||||
});
|
||||
|
||||
|
||||
it('should throw if \'githubRepo\' is missing or empty', () => {
|
||||
expect(() => createUploadServer({githubRepo: ''})).
|
||||
expect(() => createPreviewServer({githubRepo: ''})).
|
||||
toThrowError('Missing or empty required parameter \'githubRepo\'!');
|
||||
});
|
||||
|
||||
|
||||
it('should throw if \'trustedPrLabel\' is missing or empty', () => {
|
||||
expect(() => createUploadServer({trustedPrLabel: ''})).
|
||||
expect(() => createPreviewServer({trustedPrLabel: ''})).
|
||||
toThrowError('Missing or empty required parameter \'trustedPrLabel\'!');
|
||||
});
|
||||
|
||||
|
||||
it('should return an http.Server', () => {
|
||||
const httpCreateServerSpy = spyOn(http, 'createServer').and.callThrough();
|
||||
const server = createUploadServer();
|
||||
const server = createPreviewServer();
|
||||
|
||||
expect(server).toBe(httpCreateServerSpy.calls.mostRecent().returnValue);
|
||||
});
|
||||
|
||||
|
||||
it('should create and use an appropriate BuildCreator', () => {
|
||||
const usfCreateBuildCreatorSpy = spyOn(UploadServerFactory, 'createBuildCreator').and.callThrough();
|
||||
const usfCreateBuildCreatorSpy = spyOn(PreviewServerFactory, 'createBuildCreator').and.callThrough();
|
||||
|
||||
createUploadServer();
|
||||
createPreviewServer();
|
||||
const buildRetriever = jasmine.any(BuildRetriever);
|
||||
const buildVerifier = jasmine.any(BuildVerifier);
|
||||
const prs = jasmine.any(GithubPullRequests);
|
||||
@ -124,7 +124,7 @@ describe('uploadServerFactory', () => {
|
||||
it('should create and use an appropriate middleware', () => {
|
||||
const httpCreateServerSpy = spyOn(http, 'createServer').and.callThrough();
|
||||
|
||||
createUploadServer();
|
||||
createPreviewServer();
|
||||
|
||||
const buildRetriever = jasmine.any(BuildRetriever);
|
||||
const buildVerifier = jasmine.any(BuildVerifier);
|
||||
@ -137,14 +137,14 @@ describe('uploadServerFactory', () => {
|
||||
|
||||
|
||||
it('should log the server address info on \'listening\'', () => {
|
||||
const server = createUploadServer();
|
||||
const server = createPreviewServer();
|
||||
server.address = () => ({address: 'foo', family: '', port: 1337});
|
||||
|
||||
expect(console.info).not.toHaveBeenCalled();
|
||||
|
||||
server.emit('listening');
|
||||
expect(console.info).toHaveBeenCalledWith(
|
||||
jasmine.any(String), 'UploadServer: ', 'Up and running (and listening on foo:1337)...');
|
||||
jasmine.any(String), 'PreviewServer: ', 'Up and running (and listening on foo:1337)...');
|
||||
});
|
||||
|
||||
});
|
||||
@ -158,7 +158,7 @@ describe('uploadServerFactory', () => {
|
||||
beforeEach(() => {
|
||||
const api = new GithubApi(defaultConfig.githubToken);
|
||||
const prs = new GithubPullRequests(api, defaultConfig.githubOrg, defaultConfig.githubRepo);
|
||||
buildCreator = UploadServerFactory.createBuildCreator(prs, defaultConfig.buildsDir, defaultConfig.domainName);
|
||||
buildCreator = PreviewServerFactory.createBuildCreator(prs, defaultConfig.buildsDir, defaultConfig.domainName);
|
||||
});
|
||||
|
||||
it('should pass the \'buildsDir\' to the BuildCreator', () => {
|
||||
@ -256,7 +256,7 @@ describe('uploadServerFactory', () => {
|
||||
buildVerifier = new BuildVerifier(prs, teams, defaultConfig.githubTeamSlugs, defaultConfig.trustedPrLabel);
|
||||
buildCreator = new BuildCreator(defaultConfig.buildsDir);
|
||||
|
||||
const middleware = UploadServerFactory.createMiddleware(buildRetriever, buildVerifier, buildCreator,
|
||||
const middleware = PreviewServerFactory.createMiddleware(buildRetriever, buildVerifier, buildCreator,
|
||||
defaultConfig);
|
||||
agent = supertest.agent(middleware);
|
||||
});
|
||||
@ -359,7 +359,7 @@ describe('uploadServerFactory', () => {
|
||||
await agent.post(URL).send(BASIC_PAYLOAD).expect(204);
|
||||
expect(getGithubInfoSpy).not.toHaveBeenCalled();
|
||||
expect(getSignificantFilesChangedSpy).not.toHaveBeenCalled();
|
||||
expect(console.log).toHaveBeenCalledWith(jasmine.any(String), 'UploadServer: ',
|
||||
expect(console.log).toHaveBeenCalledWith(jasmine.any(String), 'PreviewServer: ',
|
||||
'Build:12345, Job:lint -', 'Skipping preview processing because this is not the "aio_preview" job.');
|
||||
expect(downloadBuildArtifactSpy).not.toHaveBeenCalled();
|
||||
expect(getPrIsTrustedSpy).not.toHaveBeenCalled();
|
||||
@ -371,7 +371,7 @@ describe('uploadServerFactory', () => {
|
||||
await agent.post(URL).send(BASIC_PAYLOAD).expect(204);
|
||||
expect(getGithubInfoSpy).toHaveBeenCalledWith(BUILD_NUM);
|
||||
expect(getSignificantFilesChangedSpy).toHaveBeenCalledWith(PR, jasmine.any(RegExp));
|
||||
expect(console.log).toHaveBeenCalledWith(jasmine.any(String), 'UploadServer: ',
|
||||
expect(console.log).toHaveBeenCalledWith(jasmine.any(String), 'PreviewServer: ',
|
||||
'PR:777, Build:12345 - Skipping preview processing because this PR did not touch any significant files.');
|
||||
expect(downloadBuildArtifactSpy).not.toHaveBeenCalled();
|
||||
expect(getPrIsTrustedSpy).not.toHaveBeenCalled();
|
@ -1,8 +1,8 @@
|
||||
import * as express from 'express';
|
||||
import {UploadError} from '../../lib/upload-server/upload-error';
|
||||
import {respondWithError, throwRequestError} from '../../lib/upload-server/utils';
|
||||
import {PreviewServerError} from '../../lib/preview-server/preview-error';
|
||||
import {respondWithError, throwRequestError} from '../../lib/preview-server/utils';
|
||||
|
||||
describe('upload-server/utils', () => {
|
||||
describe('preview-server/utils', () => {
|
||||
describe('respondWithError', () => {
|
||||
let endSpy: jasmine.Spy;
|
||||
let statusSpy: jasmine.Spy;
|
||||
@ -15,12 +15,12 @@ describe('upload-server/utils', () => {
|
||||
});
|
||||
|
||||
it('should set the status on the response', () => {
|
||||
respondWithError(response, new UploadError(505, 'TEST MESSAGE'));
|
||||
respondWithError(response, new PreviewServerError(505, 'TEST MESSAGE'));
|
||||
expect(statusSpy).toHaveBeenCalledWith(505);
|
||||
expect(endSpy).toHaveBeenCalledWith('TEST MESSAGE', jasmine.any(Function));
|
||||
});
|
||||
|
||||
it('should convert non-UploadError errors to 500 UploadErrors', () => {
|
||||
it('should convert non-PreviewServerError errors to 500 PreviewServerErrors', () => {
|
||||
respondWithError(response, new Error('OTHER MESSAGE'));
|
||||
expect(statusSpy).toHaveBeenCalledWith(500);
|
||||
expect(endSpy).toHaveBeenCalledWith('OTHER MESSAGE', jasmine.any(Function));
|
||||
@ -39,7 +39,7 @@ describe('upload-server/utils', () => {
|
||||
throwRequestError(505, 'ERROR MESSAGE', request);
|
||||
} catch (error) {
|
||||
caught = true;
|
||||
expect(error).toEqual(jasmine.any(UploadError));
|
||||
expect(error).toEqual(jasmine.any(PreviewServerError));
|
||||
expect(error.status).toEqual(505);
|
||||
expect(error.message).toEqual(`ERROR MESSAGE in request: POST some.domain.com/path "The request body"`);
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
import {UploadError} from '../../lib/upload-server/upload-error';
|
||||
|
||||
export const expectToBeUploadError = (actual: UploadError, status?: number, message?: string) => {
|
||||
expect(actual).toEqual(jasmine.any(UploadError));
|
||||
if (status != null) {
|
||||
expect(actual.status).toBe(status);
|
||||
}
|
||||
if (message != null) {
|
||||
expect(actual.message).toBe(message);
|
||||
}
|
||||
};
|
@ -1,39 +0,0 @@
|
||||
// Imports
|
||||
import {UploadError} from '../../lib/upload-server/upload-error';
|
||||
|
||||
// Tests
|
||||
describe('UploadError', () => {
|
||||
let err: UploadError;
|
||||
|
||||
beforeEach(() => err = new UploadError(999, 'message'));
|
||||
|
||||
|
||||
it('should extend Error', () => {
|
||||
expect(err).toEqual(jasmine.any(UploadError));
|
||||
expect(err).toEqual(jasmine.any(Error));
|
||||
|
||||
expect(Object.getPrototypeOf(err)).toBe(UploadError.prototype);
|
||||
});
|
||||
|
||||
|
||||
it('should have a \'status\' property', () => {
|
||||
expect(err.status).toBe(999);
|
||||
});
|
||||
|
||||
|
||||
it('should have a \'message\' property', () => {
|
||||
expect(err.message).toBe('message');
|
||||
});
|
||||
|
||||
|
||||
it('should have a 500 \'status\' by default', () => {
|
||||
expect(new UploadError().status).toBe(500);
|
||||
});
|
||||
|
||||
|
||||
it('should have an empty \'message\' by default', () => {
|
||||
expect(new UploadError().message).toBe('');
|
||||
expect(new UploadError(999).message).toBe('');
|
||||
});
|
||||
|
||||
});
|
Reference in New Issue
Block a user