Commit de472d6d authored by Lukas Eipert's avatar Lukas Eipert Committed by Vitaly Slobodin

Check that possibleTypes for apollo are correct

When our GraphQL Union types or Interfaces change, we need to regenerate
app/assets/javascripts/graphql_shared/possibleTypes.json. Not doing this
has caused a regression before, so we create a little script to
regenerate the types _and_ check whether the checked in types are
correct in CI.
parent 1f55fa41
...@@ -11,3 +11,5 @@ graphql-verify: ...@@ -11,3 +11,5 @@ graphql-verify:
script: script:
- bundle exec rake gitlab:graphql:validate - bundle exec rake gitlab:graphql:validate
- bundle exec rake gitlab:graphql:check_docs - bundle exec rake gitlab:graphql:check_docs
- bundle exec rake gitlab:graphql:schema:dump
- node scripts/frontend/graphql_possible_types_extraction.js --check
{"AlertManagementIntegration":["AlertManagementHttpIntegration","AlertManagementPrometheusIntegration"],"CurrentUserTodos":["BoardEpic","Design","Epic","EpicIssue","Issue","MergeRequest"],"DependencyLinkMetadata":["NugetDependencyLinkMetadata"],"DesignFields":["Design","DesignAtVersion"],"Entry":["Blob","Submodule","TreeEntry"],"Eventable":["BoardEpic","Epic"],"Issuable":["Epic","Issue","MergeRequest","WorkItem"],"JobNeedUnion":["CiBuildNeed","CiJob"],"MemberInterface":["GroupMember","ProjectMember"],"NoteableInterface":["AlertManagementAlert","BoardEpic","Design","Epic","EpicIssue","Issue","MergeRequest","Snippet","Vulnerability"],"NoteableType":["Design","Issue","MergeRequest"],"OrchestrationPolicy":["ScanExecutionPolicy","ScanResultPolicy"],"PackageFileMetadata":["ConanFileMetadata","HelmFileMetadata"],"PackageMetadata":["ComposerMetadata","ConanMetadata","MavenMetadata","NugetMetadata","PypiMetadata"],"ResolvableInterface":["Discussion","Note"],"Service":["BaseService","JiraService"],"TimeboxReportInterface":["Iteration","Milestone"],"Todoable":["AlertManagementAlert","BoardEpic","Commit","Design","Epic","EpicIssue","Issue","MergeRequest"],"User":["MergeRequestAssignee","MergeRequestAuthor","MergeRequestParticipant","MergeRequestReviewer","UserCore"],"VulnerabilityDetail":["VulnerabilityDetailBase","VulnerabilityDetailBoolean","VulnerabilityDetailCode","VulnerabilityDetailCommit","VulnerabilityDetailDiff","VulnerabilityDetailFileLocation","VulnerabilityDetailInt","VulnerabilityDetailList","VulnerabilityDetailMarkdown","VulnerabilityDetailModuleLocation","VulnerabilityDetailTable","VulnerabilityDetailText","VulnerabilityDetailUrl"],"VulnerabilityLocation":["VulnerabilityLocationClusterImageScanning","VulnerabilityLocationContainerScanning","VulnerabilityLocationCoverageFuzzing","VulnerabilityLocationDast","VulnerabilityLocationDependencyScanning","VulnerabilityLocationGeneric","VulnerabilityLocationSast","VulnerabilityLocationSecretDetection"]}
\ No newline at end of file
{
"AlertManagementIntegration": [
"AlertManagementHttpIntegration",
"AlertManagementPrometheusIntegration"
],
"CurrentUserTodos": [
"BoardEpic",
"Design",
"Epic",
"EpicIssue",
"Issue",
"MergeRequest"
],
"DependencyLinkMetadata": [
"NugetDependencyLinkMetadata"
],
"DesignFields": [
"Design",
"DesignAtVersion"
],
"Entry": [
"Blob",
"Submodule",
"TreeEntry"
],
"Eventable": [
"BoardEpic",
"Epic"
],
"Issuable": [
"Epic",
"Issue",
"MergeRequest",
"WorkItem"
],
"JobNeedUnion": [
"CiBuildNeed",
"CiJob"
],
"MemberInterface": [
"GroupMember",
"ProjectMember"
],
"NoteableInterface": [
"AlertManagementAlert",
"BoardEpic",
"Design",
"Epic",
"EpicIssue",
"Issue",
"MergeRequest",
"Snippet",
"Vulnerability"
],
"NoteableType": [
"Design",
"Issue",
"MergeRequest"
],
"OrchestrationPolicy": [
"ScanExecutionPolicy",
"ScanResultPolicy"
],
"PackageFileMetadata": [
"ConanFileMetadata",
"HelmFileMetadata"
],
"PackageMetadata": [
"ComposerMetadata",
"ConanMetadata",
"MavenMetadata",
"NugetMetadata",
"PypiMetadata"
],
"ResolvableInterface": [
"Discussion",
"Note"
],
"Service": [
"BaseService",
"JiraService"
],
"TimeboxReportInterface": [
"Iteration",
"Milestone"
],
"Todoable": [
"AlertManagementAlert",
"BoardEpic",
"Commit",
"Design",
"Epic",
"EpicIssue",
"Issue",
"MergeRequest"
],
"User": [
"MergeRequestAssignee",
"MergeRequestAuthor",
"MergeRequestParticipant",
"MergeRequestReviewer",
"UserCore"
],
"VulnerabilityDetail": [
"VulnerabilityDetailBase",
"VulnerabilityDetailBoolean",
"VulnerabilityDetailCode",
"VulnerabilityDetailCommit",
"VulnerabilityDetailDiff",
"VulnerabilityDetailFileLocation",
"VulnerabilityDetailInt",
"VulnerabilityDetailList",
"VulnerabilityDetailMarkdown",
"VulnerabilityDetailModuleLocation",
"VulnerabilityDetailTable",
"VulnerabilityDetailText",
"VulnerabilityDetailUrl"
],
"VulnerabilityLocation": [
"VulnerabilityLocationClusterImageScanning",
"VulnerabilityLocationContainerScanning",
"VulnerabilityLocationCoverageFuzzing",
"VulnerabilityLocationDast",
"VulnerabilityLocationDependencyScanning",
"VulnerabilityLocationGeneric",
"VulnerabilityLocationSast",
"VulnerabilityLocationSecretDetection"
]
}
...@@ -3,7 +3,7 @@ import { BatchHttpLink } from '@apollo/client/link/batch-http'; ...@@ -3,7 +3,7 @@ import { BatchHttpLink } from '@apollo/client/link/batch-http';
import { createUploadLink } from 'apollo-upload-client'; import { createUploadLink } from 'apollo-upload-client';
import ActionCableLink from '~/actioncable_link'; import ActionCableLink from '~/actioncable_link';
import { apolloCaptchaLink } from '~/captcha/apollo_captcha_link'; import { apolloCaptchaLink } from '~/captcha/apollo_captcha_link';
import possibleTypes from '~/graphql_shared/possibleTypes.json'; import possibleTypes from '~/graphql_shared/possible_types.json';
import { StartupJSLink } from '~/lib/utils/apollo_startup_js_link'; import { StartupJSLink } from '~/lib/utils/apollo_startup_js_link';
import csrf from '~/lib/utils/csrf'; import csrf from '~/lib/utils/csrf';
import { objectToQuery, queryToObject } from '~/lib/utils/url_utility'; import { objectToQuery, queryToObject } from '~/lib/utils/url_utility';
......
#!/usr/bin/env node
const fs = require('fs/promises');
const path = require('path');
const assert = require('assert');
const ROOT_DIR = path.join(__dirname, '../../');
const GRAPHQL_SCHEMA = path.join(ROOT_DIR, 'tmp/tests/graphql/gitlab_schema.json');
const POSSIBLE_TYPES_REL = 'app/assets/javascripts/graphql_shared/possible_types.json';
const POSSIBLE_TYPES = path.join(ROOT_DIR, POSSIBLE_TYPES_REL);
function extractTypes(schema) {
return Object.fromEntries(
// eslint-disable-next-line no-underscore-dangle
schema.data.__schema.types
.filter((type) => type.possibleTypes)
.map(({ name, possibleTypes }) => [name, possibleTypes.map((subtype) => subtype.name)]),
);
}
async function main() {
let schema;
try {
schema = JSON.parse(await fs.readFile(GRAPHQL_SCHEMA, 'utf-8'));
} catch (e) {
console.error(
'Could not read the GraphQL Schema, make sure to run: bundle exec rake gitlab:graphql:schema:dump',
);
throw e;
}
const possibleTypes = extractTypes(schema);
if (process.argv.includes('--check')) {
const previousTypes = JSON.parse(await fs.readFile(POSSIBLE_TYPES, 'utf-8'));
assert.deepStrictEqual(
previousTypes,
possibleTypes,
`
${POSSIBLE_TYPES_REL} needs to be regenerated, please run:
node scripts/frontend/graphql_possible_types_extraction.js --write
and commit the changes!
`,
);
return;
}
if (process.argv.includes('--write')) {
const stringifiedPossibleTypes = JSON.stringify(possibleTypes, null, 2);
await fs.writeFile(POSSIBLE_TYPES, `${stringifiedPossibleTypes}\n`);
console.log(`Successfully updated ${POSSIBLE_TYPES_REL}`);
return;
}
throw new Error(`
ERROR: Please use the script correctly:
Usage: graphql_possible_types_extraction [options]
Options:
--check Check whether there are new Interface or Union types
--write Generate new possible types
`);
}
main().catch((error) => {
console.warn(error.message);
process.exitCode = 1;
});
import { InMemoryCache } from '@apollo/client/core'; import { InMemoryCache } from '@apollo/client/core';
import { createMockClient as createMockApolloClient } from 'mock-apollo-client'; import { createMockClient as createMockApolloClient } from 'mock-apollo-client';
import VueApollo from 'vue-apollo'; import VueApollo from 'vue-apollo';
import possibleTypes from '~/graphql_shared/possibleTypes.json'; import possibleTypes from '~/graphql_shared/possible_types.json';
import { typePolicies } from '~/lib/graphql'; import { typePolicies } from '~/lib/graphql';
export function createMockClient(handlers = [], resolvers = {}, cacheOptions = {}) { export function createMockClient(handlers = [], resolvers = {}, cacheOptions = {}) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment