more strict error type checking in most packages and backend plugins

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
Patrik Oldsberg
2021-10-08 17:41:29 +02:00
parent 9d18bc8ba4
commit 36e67d2f24
68 changed files with 248 additions and 104 deletions
@@ -16,6 +16,7 @@
import { isChildPath } from '@backstage/backend-common';
import { Entity } from '@backstage/catalog-model';
import { assertError, ForwardedError } from '@backstage/errors';
import { ScmIntegrationRegistry } from '@backstage/integration';
import { spawn } from 'child_process';
import fs from 'fs-extra';
@@ -155,8 +156,9 @@ export const getMkdocsYml = async (
mkdocsYmlPath = path.join(inputDir, 'mkdocs.yml');
mkdocsYmlFileString = await fs.readFile(mkdocsYmlPath, 'utf8');
} catch (error) {
throw new Error(
`Could not read MkDocs YAML config file mkdocs.yml or mkdocs.yaml for validation: ${error.message}`,
throw new ForwardedError(
'Could not read MkDocs YAML config file mkdocs.yml or mkdocs.yaml for validation',
error,
);
}
}
@@ -225,6 +227,7 @@ export const patchMkdocsYmlPreBuild = async (
try {
mkdocsYmlFileString = await fs.readFile(mkdocsYmlPath, 'utf8');
} catch (error) {
assertError(error);
logger.warn(
`Could not read MkDocs YAML config file ${mkdocsYmlPath} before running the generator: ${error.message}`,
);
@@ -241,6 +244,7 @@ export const patchMkdocsYmlPreBuild = async (
throw new Error('Bad YAML format.');
}
} catch (error) {
assertError(error);
logger.warn(
`Error in parsing YAML at ${mkdocsYmlPath} before running the generator. ${error.message}`,
);
@@ -279,6 +283,7 @@ export const patchMkdocsYmlPreBuild = async (
);
}
} catch (error) {
assertError(error);
logger.warn(
`Could not write to ${mkdocsYmlPath} after updating it before running the generator. ${error.message}`,
);
@@ -307,6 +312,7 @@ export const addBuildTimestampMetadata = async (
try {
json = await fs.readJson(techdocsMetadataPath);
} catch (err) {
assertError(err);
const message = `Invalid JSON at ${techdocsMetadataPath} with error ${err.message}`;
logger.error(message);
throw new Error(message);
@@ -36,6 +36,7 @@ import {
GeneratorRunInType,
GeneratorRunOptions,
} from './types';
import { ForwardedError } from '@backstage/errors';
export class TechdocsGenerator implements GeneratorBase {
/**
@@ -151,8 +152,9 @@ export class TechdocsGenerator implements GeneratorBase {
this.logger.debug(
`Failed to generate docs from ${inputDir} into ${outputDir}`,
);
throw new Error(
`Failed to generate docs from ${inputDir} into ${outputDir} with error ${error.message}`,
throw new ForwardedError(
'Failed to generate docs from ${inputDir} into ${outputDir}',
error,
);
}
@@ -14,7 +14,7 @@
* limitations under the License.
*/
import { NotModifiedError } from '@backstage/errors';
import { assertError } from '@backstage/errors';
import { UrlReader } from '@backstage/backend-common';
import { Entity } from '@backstage/catalog-model';
import { Logger } from 'winston';
@@ -40,8 +40,9 @@ export class UrlPreparer implements PreparerBase {
logger: this.logger,
});
} catch (error) {
assertError(error);
// NotModifiedError means that etag based cache is still valid.
if (error instanceof NotModifiedError) {
if (error.name === 'NotModifiedError') {
this.logger.debug(`Cache is valid for etag ${options?.etag}`);
} else {
this.logger.debug(
@@ -286,7 +286,7 @@ describe('AwsS3Publish', () => {
const fails = publisher.fetchTechDocsMetadata(invalidEntityName);
await expect(fails).rejects.toMatchObject({
message: `TechDocs metadata fetch failed, The file ${techDocsMetadaFilePath} does not exist!`,
message: `TechDocs metadata fetch failed; caused by Error: The file ${techDocsMetadaFilePath} does not exist!`,
});
});
});
@@ -15,6 +15,7 @@
*/
import { Entity, EntityName } from '@backstage/catalog-model';
import { Config } from '@backstage/config';
import { assertError, ForwardedError } from '@backstage/errors';
import aws, { Credentials } from 'aws-sdk';
import { ListObjectsV2Output } from 'aws-sdk/clients/s3';
import { CredentialsOptions } from 'aws-sdk/lib/credentials';
@@ -49,7 +50,7 @@ const streamToBuffer = (stream: Readable): Promise<Buffer> => {
stream.on('error', reject);
stream.on('end', () => resolve(Buffer.concat(chunks)));
} catch (e) {
throw new Error(`Unable to parse the response data ${e.message}`);
throw new ForwardedError('Unable to parse the response data', e);
}
});
};
@@ -204,6 +205,7 @@ export class AwsS3Publish implements PublisherBase {
prefix: remoteFolder,
});
} catch (e) {
assertError(e);
this.logger.error(
`Unable to list files for Entity ${entity.metadata.name}: ${e.message}`,
);
@@ -312,12 +314,13 @@ export class AwsS3Publish implements PublisherBase {
resolve(techdocsMetadata);
} catch (err) {
assertError(err);
this.logger.error(err.message);
reject(new Error(err.message));
}
});
} catch (e) {
throw new Error(`TechDocs metadata fetch failed, ${e.message}`);
throw new ForwardedError('TechDocs metadata fetch failed', e);
}
}
@@ -351,6 +354,7 @@ export class AwsS3Publish implements PublisherBase {
res.send(await streamToBuffer(stream));
} catch (err) {
assertError(err);
this.logger.warn(
`TechDocs S3 router failed to serve static files from bucket ${this.bucketName} at key ${filePath}: ${err.message}`,
);
@@ -396,6 +400,7 @@ export class AwsS3Publish implements PublisherBase {
try {
newPath = lowerCaseEntityTripletInStoragePath(file);
} catch (e) {
assertError(e);
this.logger.warn(e.message);
return;
}
@@ -424,6 +429,7 @@ export class AwsS3Publish implements PublisherBase {
.promise();
}
} catch (e) {
assertError(e);
this.logger.warn(`Unable to migrate ${file}: ${e.message}`);
}
}, f),
@@ -201,7 +201,7 @@ describe('AzureBlobStoragePublish', () => {
let error;
try {
await publisher.publish({ entity, directory });
} catch (e) {
} catch (e: any) {
error = e;
}
@@ -305,7 +305,7 @@ describe('AzureBlobStoragePublish', () => {
const fails = publisher.fetchTechDocsMetadata(invalidEntityName);
await expect(fails).rejects.toMatchObject({
message: `TechDocs metadata fetch failed, The file ${techDocsMetadaFilePath} does not exist!`,
message: `TechDocs metadata fetch failed; caused by Error: The file ${techDocsMetadaFilePath} does not exist!`,
});
});
});
@@ -21,6 +21,7 @@ import {
} from '@azure/storage-blob';
import { Entity, EntityName } from '@backstage/catalog-model';
import { Config } from '@backstage/config';
import { assertError, ForwardedError } from '@backstage/errors';
import express from 'express';
import JSON5 from 'json5';
import limiterFactory from 'p-limit';
@@ -132,6 +133,7 @@ export class AzureBlobStoragePublish implements PublisherBase {
);
}
} catch (e) {
assertError(e);
this.logger.error(`from Azure Blob Storage client library: ${e.message}`);
}
@@ -165,6 +167,7 @@ export class AzureBlobStoragePublish implements PublisherBase {
maxPageSize: BATCH_CONCURRENCY,
});
} catch (e) {
assertError(e);
this.logger.error(
`Unable to list files for Entity ${entity.metadata.name}: ${e.message}`,
);
@@ -307,7 +310,7 @@ export class AzureBlobStoragePublish implements PublisherBase {
);
return techdocsMetadata;
} catch (e) {
throw new Error(`TechDocs metadata fetch failed, ${e.message}`);
throw new ForwardedError('TechDocs metadata fetch failed', e);
}
}
@@ -386,6 +389,7 @@ export class AzureBlobStoragePublish implements PublisherBase {
try {
newPath = lowerCaseEntityTripletInStoragePath(originalPath);
} catch (e) {
assertError(e);
this.logger.warn(e.message);
return;
}
@@ -395,6 +399,7 @@ export class AzureBlobStoragePublish implements PublisherBase {
this.logger.verbose(`Migrating ${originalPath}`);
await this.renameBlob(originalPath, newPath, removeOriginal);
} catch (e) {
assertError(e);
this.logger.warn(`Unable to migrate ${originalPath}: ${e.message}`);
}
}
@@ -15,6 +15,7 @@
*/
import { Entity, EntityName } from '@backstage/catalog-model';
import { Config } from '@backstage/config';
import { assertError } from '@backstage/errors';
import { File, FileExistsResponse, Storage } from '@google-cloud/storage';
import express from 'express';
import JSON5 from 'json5';
@@ -112,6 +113,7 @@ export class GoogleGCSPublish implements PublisherBase {
isAvailable: true,
};
} catch (err) {
assertError(err);
this.logger.error(
`Could not retrieve metadata about the GCS bucket ${this.bucketName}. ` +
'Make sure the bucket exists. Also make sure that authentication is setup either by explicitly defining ' +
@@ -142,6 +144,7 @@ export class GoogleGCSPublish implements PublisherBase {
);
existingFiles = await this.getFilesForFolder(remoteFolder);
} catch (e) {
assertError(e);
this.logger.error(
`Unable to list files for Entity ${entity.metadata.name}: ${e.message}`,
);
@@ -37,6 +37,7 @@ import {
getHeadersForFileExtension,
lowerCaseEntityTripletInStoragePath,
} from './helpers';
import { assertError } from '@backstage/errors';
// TODO: Use a more persistent storage than node_modules or /tmp directory.
// Make it configurable with techdocs.publisher.local.publishDirectory
@@ -134,6 +135,7 @@ export class LocalPublish implements PublisherBase {
try {
return await fs.readJson(metadataPath);
} catch (err) {
assertError(err);
this.logger.error(
`Unable to read techdocs_metadata.json at ${metadataPath}. Error: ${err}`,
);
@@ -14,6 +14,7 @@
* limitations under the License.
*/
import { assertError } from '@backstage/errors';
import { File } from '@google-cloud/storage';
import { Writable } from 'stream';
import { Logger } from 'winston';
@@ -42,6 +43,7 @@ export class MigrateWriteStream extends Writable {
try {
newFile = lowerCaseEntityTripletInStoragePath(file.name);
} catch (e) {
assertError(e);
this.logger.warn(e.message);
next();
return;
@@ -31,6 +31,7 @@ import {
ReadinessResponse,
TechDocsMetadata,
} from './types';
import { assertError, ForwardedError } from '@backstage/errors';
const streamToBuffer = (stream: Stream | Readable): Promise<Buffer> => {
return new Promise((resolve, reject) => {
@@ -40,7 +41,7 @@ const streamToBuffer = (stream: Stream | Readable): Promise<Buffer> => {
stream.on('error', reject);
stream.on('end', () => resolve(Buffer.concat(chunks)));
} catch (e) {
throw new Error(`Unable to parse the response data ${e.message}`);
throw new ForwardedError('Unable to parse the response data', e);
}
});
};
@@ -118,6 +119,7 @@ export class OpenStackSwiftPublish implements PublisherBase {
isAvailable: false,
};
} catch (err) {
assertError(err);
this.logger.error(`from OpenStack client library: ${err.message}`);
return {
isAvailable: false,
@@ -203,6 +205,7 @@ export class OpenStackSwiftPublish implements PublisherBase {
resolve(techdocsMetadata);
} catch (err) {
assertError(err);
this.logger.error(err.message);
reject(new Error(err.message));
}
@@ -245,6 +248,7 @@ export class OpenStackSwiftPublish implements PublisherBase {
res.send(await streamToBuffer(stream));
} catch (err) {
assertError(err);
this.logger.warn(
`TechDocs OpenStack swift router failed to serve content from container ${this.containerName} at path ${filePath}: ${err.message}`,
);
@@ -276,6 +280,7 @@ export class OpenStackSwiftPublish implements PublisherBase {
}
return false;
} catch (err) {
assertError(err);
this.logger.warn(err.message);
return false;
}