Skip to content

Commit

Permalink
feat(release): Export quickstarts as QuickStartMetadata (WIP)
Browse files Browse the repository at this point in the history
  • Loading branch information
Andrew Anguiano committed Oct 1, 2024
1 parent b91577f commit 4405fb0
Show file tree
Hide file tree
Showing 6 changed files with 612 additions and 99 deletions.
8 changes: 4 additions & 4 deletions utils/__tests__/nr_graphql_helpers.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ describe('getCategoryTermsFromKeywords', () => {
const mockKeywords = undefined;

const categoriesFromKeywords =
await nrGraphQlHelpers.getCategoryTermsFromKeywords(mockKeywords);
await nrGraphQlHelpers.getValidCategoryTerms(mockKeywords);

expect(nrGraphQlHelpers.fetchNRGraphqlResults).toHaveBeenCalledTimes(1);
expect(categoriesFromKeywords).toEqual(undefined);
Expand All @@ -46,7 +46,7 @@ describe('getCategoryTermsFromKeywords', () => {
test('getCategoryTermsFromKeywords returns undefined if no keywords match a category', async () => {
const mockKeywords = ['python', 'apm', 'http'];
const categoriesFromKeywords =
await nrGraphQlHelpers.getCategoryTermsFromKeywords(mockKeywords);
await nrGraphQlHelpers.getValidCategoryTerms(mockKeywords);

expect(nrGraphQlHelpers.fetchNRGraphqlResults).toHaveBeenCalledTimes(1);
expect(categoriesFromKeywords).toEqual(undefined);
Expand All @@ -55,7 +55,7 @@ describe('getCategoryTermsFromKeywords', () => {
test('getCategoryTermsFromKeywords returns 1 categoryTerm given a set of keywords where a keyword belong to 1 category', async () => {
const mockKeywords = ['python', 'azure'];
const categoriesFromKeywords =
await nrGraphQlHelpers.getCategoryTermsFromKeywords(mockKeywords);
await nrGraphQlHelpers.getValidCategoryTerms(mockKeywords);

expect(nrGraphQlHelpers.fetchNRGraphqlResults).toHaveBeenCalledTimes(1);
expect(categoriesFromKeywords).toEqual(['azure']);
Expand All @@ -64,7 +64,7 @@ describe('getCategoryTermsFromKeywords', () => {
test('getCategoryTermsFromKeywords returns 2 categoryTerms given a set of keywords where keywords belong to 2 categories', async () => {
const mockKeywords = ['python', 'os', 'containers'];
const categoriesFromKeywords =
await nrGraphQlHelpers.getCategoryTermsFromKeywords(mockKeywords);
await nrGraphQlHelpers.getValidCategoryTerms(mockKeywords);

expect(nrGraphQlHelpers.fetchNRGraphqlResults).toHaveBeenCalledTimes(1);
expect(categoriesFromKeywords).toEqual(['os', 'containers']);
Expand Down
18 changes: 14 additions & 4 deletions utils/build-validate-quickstart-artifact.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import Ajv, { type ErrorObject } from 'ajv';
import { QuickstartConfig, QuickstartConfigAlert } from './types/QuickstartConfig';
import { DataSourceConfig } from './types/DataSourceConfig';
import { passedProcessArguments } from './lib/helpers';
import { QuickstartMutationVariable } from './types/QuickstartMutationVariable';
import { getAllCategoryTerms } from './lib/nr-graphql-helpers';

type ArtifactSchema = Record<string, unknown>;

Expand All @@ -28,6 +30,7 @@ type ArtifactComponents = {

type Artifact = ArtifactComponents | {
dataSourceIds: string[]
quickstarts: QuickstartMutationVariable[]
}

const getSchema = (filepath: string): ArtifactSchema => {
Expand All @@ -37,7 +40,8 @@ const getSchema = (filepath: string): ArtifactSchema => {
};

// NOTE: we could run these in parallel to speed up the script
export const getArtifactComponents = (): ArtifactComponents => {
export const getArtifactComponents = async (): Promise<ArtifactComponents> => {

const quickstarts = Quickstart.getAll().map((quickstart) => quickstart.config);
console.log(`[*] Found ${quickstarts.length} quickstarts`);

Expand Down Expand Up @@ -75,9 +79,9 @@ export const validateArtifact = (schema: ArtifactSchema, artifact: Artifact): Er
return ajv.errors ?? [];
}

const main = (shouldOutputArtifact: boolean = false) => {
const main = async (shouldOutputArtifact: boolean = false) => {
const schema = getSchema('./schema/artifact.json');
const components = getArtifactComponents();
const components = await getArtifactComponents();
const dataSourceIds = getDataSourceIds('./schema/core-datasource-ids.json', components.dataSources);
const artifact = { ...components, dataSourceIds };
const errors = validateArtifact(schema, artifact);
Expand All @@ -91,7 +95,13 @@ const main = (shouldOutputArtifact: boolean = false) => {
console.log('[*] Validation succeeded');

if (shouldOutputArtifact) {
outputArtifact(artifact);
const categoryTerms = await getAllCategoryTerms();
const transformedQuickstarts = await Promise.all(Quickstart.getAll().map(async (qs) => {
return qs.getMutationVariables(false, categoryTerms);
}
));

outputArtifact({ ...artifact, quickstarts: transformedQuickstarts });
}
}

Expand Down
16 changes: 13 additions & 3 deletions utils/lib/Quickstart.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ import {
} from '../constants';
import {
fetchNRGraphqlResults,
getCategoryTermsFromKeywords,
getAllCategoryTerms,
getValidCategoryTerms,
} from './nr-graphql-helpers';
import type {
QuickstartMutationVariable,
Expand Down Expand Up @@ -134,10 +135,15 @@ class Quickstart {

/**
* Get mutation variables from quickstart config
* @param dryRun if true, will generate a mock UUID for the quickstart
* @param validTerms if provided, will only accept these keywords and filter
* out user-supplied keywords. If not provided, will fetch them from catalog
* service.
* @returns - Promised mutation variables for quickstart
*/
async getMutationVariables(
dryRun: boolean
dryRun: boolean,
validTerms?: string[]
): Promise<QuickstartMutationVariable> {
if (!this.isValid) {
console.error(
Expand All @@ -158,9 +164,13 @@ class Quickstart {
level,
} = this.config;

if (!validTerms) {
validTerms = await getAllCategoryTerms();
}

const metadata = {
authors: authors && authors.map((author) => ({ name: author })),
categoryTerms: await getCategoryTermsFromKeywords(keywords),
categoryTerms: getValidCategoryTerms(keywords, validTerms),
description: description && description.trim(),
displayName: title && title.trim(),
slug: slug && slug.trim(),
Expand Down
14 changes: 7 additions & 7 deletions utils/lib/__tests__/Quickstart.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import * as nrGraphQlHelpers from '../nr-graphql-helpers';
import { GITHUB_RAW_BASE_URL, GITHUB_REPO_BASE_URL } from '../../constants';
import Quickstart from '../Quickstart';

nrGraphQlHelpers.getCategoryTermsFromKeywords = jest.fn();
nrGraphQlHelpers.getValidCategoryTerms = jest.fn();

const MOCK_FILES_BASEPATH = path.resolve(__dirname, '../../mock_files');

Expand All @@ -23,7 +23,7 @@ describe('Quickstart', () => {
});

test('Creates invalid quickstart', () => {
jest.spyOn(global.console, 'error').mockImplementation(() => {});
jest.spyOn(global.console, 'error').mockImplementation(() => { });

const qs = new Quickstart('', MOCK_FILES_BASEPATH);

Expand All @@ -33,7 +33,7 @@ describe('Quickstart', () => {

describe('getConfigContent', () => {
test('Handles invalid quickstart', () => {
jest.spyOn(global.console, 'error').mockImplementation(() => {});
jest.spyOn(global.console, 'error').mockImplementation(() => { });

const qs = new Quickstart('', MOCK_FILES_BASEPATH);

Expand Down Expand Up @@ -80,7 +80,7 @@ describe('Quickstart', () => {
});

test('Ensure quickstart is invalid from invalid components', () => {
jest.spyOn(global.console, 'error').mockImplementation(() => {});
jest.spyOn(global.console, 'error').mockImplementation(() => { });
const qs = new Quickstart(
'quickstarts/mock-quickstart-8/config.yml',
MOCK_FILES_BASEPATH
Expand All @@ -102,8 +102,8 @@ describe('Quickstart', () => {
});

test('Ensure quickstart is invalid from an invalid Alert', () => {
jest.spyOn(global.console, 'error').mockImplementation(() => {});
jest.spyOn(global.console, 'log').mockImplementation(() => {});
jest.spyOn(global.console, 'error').mockImplementation(() => { });
jest.spyOn(global.console, 'log').mockImplementation(() => { });
const qs = new Quickstart(
'quickstarts/mock-quickstart-6/config.yml',
MOCK_FILES_BASEPATH
Expand Down Expand Up @@ -135,7 +135,7 @@ describe('Quickstart', () => {
MOCK_FILES_BASEPATH
);

nrGraphQlHelpers.getCategoryTermsFromKeywords.mockResolvedValueOnce(
nrGraphQlHelpers.getValidCategoryTerms.mockResolvedValueOnce(
undefined
);
const variables = await qs.getMutationVariables(true);
Expand Down
34 changes: 19 additions & 15 deletions utils/lib/nr-graphql-helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ export const fetchNRGraphqlResults = async <Variables, ResponseData>(
): Promise<NerdGraphResponseWithLocalErrors<ResponseData>> => {
const NR_API_URL = process.env.NR_API_URL || '';
const NR_API_TOKEN = process.env.NR_API_TOKEN || '';
console.log(NR_API_TOKEN);

let results;
let graphqlErrors: ErrorOrNerdGraphError[] = [];
Expand Down Expand Up @@ -176,8 +177,9 @@ type CategoryTermsNRGraphqlResults = {

/**
* Method which filters out user supplied keywords to only keywords which are valid categoryTerms.
* @param {String[] | undefined} configKeywords - An array of keywords specified in a quickstart config.yml
* @returns {Promise<String[] | undefined>} An array of quickstart categoryTerms
* @param configKeywords - An array of keywords specified in a quickstart config.yml
* @param validTerms - An array of valid categoryTerms (use getAllCategoryTerms)
* @returns An array of quickstart categoryTerms
*
* @example
* // input
Expand All @@ -186,9 +188,20 @@ type CategoryTermsNRGraphqlResults = {
* // return
* ['azure', 'infrastructure']
*/
export const getCategoryTermsFromKeywords = async (
configKeywords: string[] | undefined = []
): Promise<string[] | undefined> => {
export const getValidCategoryTerms = (
configKeywords: string[] | undefined = [], validTerms: string[]
): string[] | undefined => {
const categoryKeywords = configKeywords.reduce<string[]>((acc, keyword) => {
if (validTerms && validTerms.includes(keyword)) {
acc.push(keyword);
}
return acc;
}, []);

return categoryKeywords.length > 0 ? categoryKeywords : undefined;
};

export const getAllCategoryTerms = async () => {
logger.debug(`Fetching categories...`);

// TODO: handles errors!!
Expand All @@ -203,16 +216,7 @@ export const getCategoryTermsFromKeywords = async (

const { categories } = data.actor.nr1Catalog;

const allCategoryKeywords = categories.flatMap((category) => category.terms);

const categoryKeywords = configKeywords.reduce<string[]>((acc, keyword) => {
if (allCategoryKeywords && allCategoryKeywords.includes(keyword)) {
acc.push(keyword);
}
return acc;
}, []);

return categoryKeywords.length > 0 ? categoryKeywords : undefined;
return categories?.flatMap((category) => category.terms);
};

type CoreDataSourceSearchResults = {
Expand Down
Loading

0 comments on commit 4405fb0

Please sign in to comment.