Merge branch 'master' into generic-grid--page

This commit is contained in:
Philipp Hugenroth
2021-07-12 09:32:36 +02:00
13 changed files with 89 additions and 30 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-catalog-react': patch
---
Fix `EntityTypeFilter` so it produces unique case-insensitive set of available types
+12
View File
@@ -0,0 +1,12 @@
---
'@backstage/plugin-scaffolder-backend': patch
---
Scaffolder: Added an 'eq' handlebars helper for use in software template YAML files. This can be used to execute a step depending on the value of an input, e.g.:
```yaml
steps:
id: 'conditional-step'
action: 'custom-action'
if: '{{ eq parameters.myvalue "custom" }}',
```
+6
View File
@@ -0,0 +1,6 @@
---
'@backstage/plugin-search-backend-node': minor
---
Change return value of `SearchEngine.index` to `Promise<void>` to support
implementation of external search engines.
@@ -132,4 +132,4 @@ Integrating infrastructure of this size and complexity can seem overwhelming. It
## More questions about adopting Backstage?
[Contact the Backstage team at Spotify.](https://calendly.com/spotify-backstage) Well share more about what weve learned from our experience here at Spotify — and from other companies who are already using Backstage to transform their developer experience.
[Contact the Backstage team at Spotify.](https://backstage.spotify.com/) Well share more about what weve learned from our experience here at Spotify — and from other companies who are already using Backstage to transform their developer experience.
@@ -86,10 +86,11 @@ export function useEntityTypeFilter(): EntityTypeReturn {
const countByType = entities.reduce((acc, entity) => {
if (typeof entity.spec?.type !== 'string') return acc;
if (!acc[entity.spec.type]) {
acc[entity.spec.type] = 0;
const entityType = entity.spec.type.toLocaleLowerCase('en-US');
if (!acc[entityType]) {
acc[entityType] = 0;
}
acc[entity.spec.type] += 1;
acc[entityType] += 1;
return acc;
}, {} as Record<string, number>);
@@ -203,6 +203,39 @@ describe('TaskWorker', () => {
expect((event?.body?.output as JsonObject).result).toBe('winning');
});
it('should execute steps conditionally with eq helper', async () => {
const broker = new StorageTaskBroker(storage, logger);
const taskWorker = new TaskWorker({
logger,
workingDirectory: os.tmpdir(),
actionRegistry,
taskBroker: broker,
});
const { taskId } = await broker.dispatch({
steps: [
{ id: 'test', name: 'test', action: 'test-action' },
{
id: 'conditional',
name: 'conditional',
action: 'test-action',
if: '{{ eq steps.test.output.testOutput "winning" }}',
},
],
output: {
result: '{{ steps.conditional.output.testOutput }}',
},
values: {},
});
const task = await broker.claim();
await taskWorker.runOneTask(task);
const { events } = await storage.listEvents({ taskId });
const event = events.find(e => e.type === 'completion');
expect((event?.body?.output as JsonObject).result).toBe('winning');
});
it('should skip steps conditionally', async () => {
const broker = new StorageTaskBroker(storage, logger);
const taskWorker = new TaskWorker({
@@ -56,6 +56,8 @@ export class TaskWorker {
this.handlebars.registerHelper('json', obj => JSON.stringify(obj));
this.handlebars.registerHelper('not', value => !isTruthy(value));
this.handlebars.registerHelper('eq', (a, b) => a === b);
}
start() {
+2 -2
View File
@@ -32,7 +32,7 @@ export class LunrSearchEngine implements SearchEngine {
// (undocumented)
protected docStore: Record<string, IndexableDocument>;
// (undocumented)
index(type: string, documents: IndexableDocument[]): void;
index(type: string, documents: IndexableDocument[]): Promise<void>;
// (undocumented)
protected logger: Logger_2;
// (undocumented)
@@ -57,7 +57,7 @@ export class Scheduler {
// @public
export interface SearchEngine {
index(type: string, documents: IndexableDocument[]): void;
index(type: string, documents: IndexableDocument[]): Promise<void>;
query(query: SearchQuery): Promise<SearchResultSet>;
setTranslator(translator: QueryTranslator): void;
}
@@ -140,7 +140,7 @@ export class IndexBuilder {
}
// pushing documents to index to a configured search engine.
this.searchEngine.index(type, documents);
await this.searchEngine.index(type, documents);
}, this.collators[type].refreshInterval * 1000);
});
@@ -15,9 +15,9 @@
*/
import { getVoidLogger } from '@backstage/backend-common';
import { ConcreteLunrQuery, LunrSearchEngine } from './LunrSearchEngine';
import { SearchEngine } from '../types';
import lunr from 'lunr';
import { SearchEngine } from '../types';
import { ConcreteLunrQuery, LunrSearchEngine } from './LunrSearchEngine';
/**
* Just used to test the default translator shipped with LunrSearchEngine.
@@ -45,7 +45,7 @@ describe('LunrSearchEngine', () => {
testLunrSearchEngine.setTranslator(translatorSpy);
// When: querying the search engine
testLunrSearchEngine.query({
await testLunrSearchEngine.query({
term: 'testTerm',
filters: {},
pageCursor: '',
@@ -259,7 +259,7 @@ describe('LunrSearchEngine', () => {
];
// Mock indexing of 1 document
testLunrSearchEngine.index('test-index', mockDocuments);
await testLunrSearchEngine.index('test-index', mockDocuments);
// Perform search query
const mockedSearchResult = await testLunrSearchEngine.query({
@@ -282,7 +282,7 @@ describe('LunrSearchEngine', () => {
];
// Mock indexing of 1 document
testLunrSearchEngine.index('test-index', mockDocuments);
await testLunrSearchEngine.index('test-index', mockDocuments);
// Perform search query
const mockedSearchResult = await testLunrSearchEngine.query({
@@ -315,7 +315,7 @@ describe('LunrSearchEngine', () => {
];
// Mock indexing of 1 document
testLunrSearchEngine.index('test-index', mockDocuments);
await testLunrSearchEngine.index('test-index', mockDocuments);
// Perform search query
const mockedSearchResult = await testLunrSearchEngine.query({
@@ -347,7 +347,7 @@ describe('LunrSearchEngine', () => {
];
// Mock indexing of 1 document
testLunrSearchEngine.index('test-index', mockDocuments);
await testLunrSearchEngine.index('test-index', mockDocuments);
// Perform search query
const mockedSearchResult = await testLunrSearchEngine.query({
@@ -379,7 +379,7 @@ describe('LunrSearchEngine', () => {
];
// Mock indexing of 1 document
testLunrSearchEngine.index('test-index', mockDocuments);
await testLunrSearchEngine.index('test-index', mockDocuments);
// Perform search query
const mockedSearchResult = await testLunrSearchEngine.query({
@@ -412,7 +412,7 @@ describe('LunrSearchEngine', () => {
];
// Mock indexing of 1 document
testLunrSearchEngine.index('test-index', mockDocuments);
await testLunrSearchEngine.index('test-index', mockDocuments);
// Perform search query
const mockedSearchResult = await testLunrSearchEngine.query({
@@ -445,7 +445,7 @@ describe('LunrSearchEngine', () => {
];
// Mock indexing of 1 document
testLunrSearchEngine.index('test-index', mockDocuments);
await testLunrSearchEngine.index('test-index', mockDocuments);
// Perform search query
const mockedSearchResult = await testLunrSearchEngine.query({
@@ -483,7 +483,7 @@ describe('LunrSearchEngine', () => {
];
// Mock indexing of 2 documents
testLunrSearchEngine.index('test-index', mockDocuments);
await testLunrSearchEngine.index('test-index', mockDocuments);
// Perform search query
const mockedSearchResult = await testLunrSearchEngine.query({
@@ -527,8 +527,8 @@ describe('LunrSearchEngine', () => {
];
// Mock 2 indices with 1 document each
testLunrSearchEngine.index('test-index', mockDocuments);
testLunrSearchEngine.index('test-index-2', mockDocuments2);
await testLunrSearchEngine.index('test-index', mockDocuments);
await testLunrSearchEngine.index('test-index-2', mockDocuments2);
// Perform search query scoped to "test-index-2" with a filter on the field "extraField"
const mockedSearchResult = await testLunrSearchEngine.query({
term: 'testTitle',
@@ -565,7 +565,7 @@ describe('LunrSearchEngine', () => {
];
// Mock indexing of 2 documents
testLunrSearchEngine.index('test-index', mockDocuments);
await testLunrSearchEngine.index('test-index', mockDocuments);
// Perform search query
const mockedSearchResult = await testLunrSearchEngine.query({
@@ -618,8 +618,8 @@ describe('LunrSearchEngine', () => {
];
// Mock 2 indices with 2 documents each
testLunrSearchEngine.index('test-index', mockDocuments);
testLunrSearchEngine.index('test-index-2', mockDocuments2);
await testLunrSearchEngine.index('test-index', mockDocuments);
await testLunrSearchEngine.index('test-index-2', mockDocuments2);
// Perform search query scoped to "test-index-2"
const mockedSearchResult = await testLunrSearchEngine.query({
@@ -661,7 +661,7 @@ describe('LunrSearchEngine', () => {
];
// call index func and ensure the index func was invoked.
testLunrSearchEngine.index('test-index', mockDocuments);
await testLunrSearchEngine.index('test-index', mockDocuments);
expect(indexSpy).toHaveBeenCalled();
expect(indexSpy).toHaveBeenCalledWith('test-index', [
{ title: 'testTerm', text: 'testText', location: 'test/location' },
@@ -15,13 +15,13 @@
*/
import {
SearchQuery,
IndexableDocument,
SearchQuery,
SearchResultSet,
} from '@backstage/search-common';
import lunr from 'lunr';
import { Logger } from 'winston';
import { SearchEngine, QueryTranslator } from '../types';
import { QueryTranslator, SearchEngine } from '../types';
export type ConcreteLunrQuery = {
lunrQueryBuilder: lunr.Index.QueryBuilder;
@@ -113,7 +113,7 @@ export class LunrSearchEngine implements SearchEngine {
this.translator = translator;
}
index(type: string, documents: IndexableDocument[]): void {
async index(type: string, documents: IndexableDocument[]): Promise<void> {
const lunrBuilder = new lunr.Builder();
lunrBuilder.pipeline.add(lunr.trimmer, lunr.stopWordFilter, lunr.stemmer);
@@ -139,7 +139,7 @@ export class LunrSearchEngine implements SearchEngine {
this.lunrIndices[type] = lunrBuilder.build();
}
query(query: SearchQuery): Promise<SearchResultSet> {
async query(query: SearchQuery): Promise<SearchResultSet> {
const { lunrQueryBuilder, documentTypes } = this.translator(
query,
) as ConcreteLunrQuery;
@@ -183,6 +183,6 @@ export class LunrSearchEngine implements SearchEngine {
}),
};
return Promise.resolve(realResultSet);
return realResultSet;
}
}
+1 -1
View File
@@ -67,7 +67,7 @@ export interface SearchEngine {
/**
* Add the given documents to the SearchEngine index of the given type.
*/
index(type: string, documents: IndexableDocument[]): void;
index(type: string, documents: IndexableDocument[]): Promise<void>;
/**
* Perform a search query against the SearchEngine.
View File