Implement Tech Insights backend

* Add common types and interfaces for Tech Insights. Exposing components needed to use and modify tech-insights-backend module and to implement individual Fact Retrievers, Fact Checkers and their persistence options.

* Implement a framework to run fact retrievers and store fact data into the database. Add migration scripts to create a new database for `tech_insights`.

* Create a default implementation of a FactChecker enabling users to construct checks and run them and generate scorecards based on checks.

* To be able to use tech insights in your application you need to implement `FactRetriever`s to retrieve and return data for facts and register them to the tech-insights-backend. If you want to use fact checking functionality, you need to create `check`s and register them to an implementation of a `FactChecker`.

For more information see documentation on the README.md files of the respective packages.

Signed-off-by: Jussi Hallila <jussi@hallila.com>
This commit is contained in:
Jussi Hallila
2021-09-14 12:54:52 +02:00
parent bb1539a89f
commit 75fc6ac85b
47 changed files with 4065 additions and 3 deletions
@@ -0,0 +1,57 @@
/*
* Copyright 2021 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// @ts-check
/**
* @param {import('knex').Knex} knex
*/
exports.up = async function up(knex) {
await knex.schema.createTable('fact_schemas', table => {
table.comment(
'The table for tech insight fact schemas. Containing a versioned data model definition for a collection of facts.',
);
table.increments('id').primary();
table
.text('ref')
.notNullable()
.comment('Identifier of the fact retriever plugin/package');
table
.string('version')
.notNullable()
.comment('SemVer string defining the version of schema.');
table
.text('schema')
.notNullable()
.comment(
'Fact schema defining the values/types what this version of the fact would contain.',
);
table.index('ref', 'fact_schema_ref_idx');
table.index(['ref', 'version'], 'fact_schema_ref_version_idx');
});
};
/**
* @param {import('knex').Knex} knex
*/
exports.down = async function down(knex) {
await knex.schema.alterTable('fact_schemas', table => {
table.dropIndex([], 'fact_schema_ref_idx');
table.dropIndex([], 'fact_schema_ref_version_idx');
});
await knex.schema.dropTable('fact_schemas');
};
@@ -0,0 +1,73 @@
/*
* Copyright 2021 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// @ts-check
/**
* @param {import('knex').Knex} knex
*/
exports.up = async function up(knex) {
await knex.schema.createTable('facts', table => {
table.comment(
'The table for tech insight fact collections. Contains facts for individual fact retriever namespace/ref.',
);
table
.bigIncrements('index')
.notNullable()
.comment('An insert counter to ensure ordering');
table
.text('ref')
.notNullable()
.comment('Unique identifier of the fact retriever plugin/package');
table
.string('version')
.notNullable()
.comment(
'SemVer string defining the version of schema this fact is based on.',
);
table
.dateTime('timestamp')
.defaultTo(knex.fn.now())
.notNullable()
.comment('The timestamp when this entry was created');
table
.text('entity')
.notNullable()
.comment('Identifier of the entity these facts relate to');
table
.text('facts')
.notNullable()
.comment(
'Values of the fact collection stored as key-value pairs in JSON format.',
);
table.index('index', 'fact_index_idx');
table.index('ref', 'fact_ref_idx');
table.index(['ref', 'entity'], 'fact_ref_entity_idx');
});
};
/**
* @param {import('knex').Knex} knex
*/
exports.down = async function down(knex) {
await knex.schema.alterTable('facts', table => {
table.dropIndex([], 'facts_index_idx');
table.dropIndex([], 'fact_ref_idx');
table.dropIndex([], 'fact_ref_entity_idx');
});
await knex.schema.dropTable('facts');
};