UNPKG

@graphql-inspector/action

Version:

GraphQL Inspector functionality for GitHub Actions

187 lines (186 loc) • 7.29 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.run = run; const tslib_1 = require("tslib"); const path_1 = require("path"); const graphql_1 = require("graphql"); const core = tslib_1.__importStar(require("@actions/core")); const github = tslib_1.__importStar(require("@actions/github")); const diff_js_1 = require("../helpers/diff.js"); const loaders_js_1 = require("../helpers/loaders.js"); const schema_js_1 = require("../helpers/schema.js"); const types_js_1 = require("../helpers/types.js"); const utils_js_1 = require("../helpers/utils.js"); const checks_js_1 = require("./checks.js"); const files_js_1 = require("./files.js"); const git_js_1 = require("./git.js"); const utils_js_2 = require("./utils.js"); const CHECK_NAME = 'GraphQL Inspector'; async function run() { core.info(`GraphQL Inspector started`); // env let ref = process.env.GITHUB_SHA; const commitSha = (0, git_js_1.getCurrentCommitSha)(); core.info(`Ref: ${ref}`); core.info(`Commit SHA: ${commitSha}`); const token = core.getInput('github-token', { required: true }); const checkName = core.getInput('name') || CHECK_NAME; let workspace = process.env.GITHUB_WORKSPACE; if (!workspace) { return core.setFailed('Failed to resolve workspace directory. GITHUB_WORKSPACE is missing'); } const useMerge = (0, utils_js_2.castToBoolean)(core.getInput('experimental_merge'), true); const useAnnotations = (0, utils_js_2.castToBoolean)(core.getInput('annotations')); const failOnBreaking = (0, utils_js_2.castToBoolean)(core.getInput('fail-on-breaking')); const endpoint = core.getInput('endpoint'); const approveLabel = core.getInput('approve-label') || 'approved-breaking-change'; const rulesList = (0, utils_js_2.getInputAsArray)('rules') || []; const onUsage = core.getInput('onUsage'); const octokit = github.getOctokit(token); // repo const { owner, repo } = github.context.repo; // pull request const pullRequest = await (0, git_js_1.getAssociatedPullRequest)(octokit, commitSha); core.info(`Creating a check named "${checkName}"`); const check = await octokit.rest.checks.create({ owner, repo, name: checkName, head_sha: commitSha, status: 'in_progress', }); const checkId = check.data.id; core.info(`Check ID: ${checkId}`); const schemaPointer = core.getInput('schema', { required: true }); const loadFile = (0, files_js_1.fileLoader)({ octokit, owner, repo, }); if (!schemaPointer) { core.error('No `schema` variable'); return core.setFailed('Failed to find `schema` variable'); } const rules = rulesList .map(r => { const rule = (0, utils_js_2.resolveRule)(r); if (!rule) { core.error(`Rule ${r} is invalid. Did you specify the correct path?`); } return rule; }) .filter(Boolean); // Different lengths mean some rules were resolved to undefined if (rules.length !== rulesList.length) { return core.setFailed("Some rules weren't recognised"); } let config; if (onUsage) { const checkUsage = require(onUsage); if (checkUsage) { config = { checkUsage, }; } } let [schemaRef, schemaPath] = schemaPointer.split(':'); if (useMerge && pullRequest?.state === 'open') { ref = `refs/pull/${pullRequest.number}/merge`; workspace = undefined; core.info(`EXPERIMENTAL - Using Pull Request ${ref}`); const baseRef = pullRequest.base?.ref; if (baseRef) { schemaRef = baseRef; core.info(`EXPERIMENTAL - Using ${baseRef} as base schema ref`); } } if (endpoint) { schemaPath = schemaPointer; } const isNewSchemaUrl = endpoint && schemaPath.startsWith('http'); const [oldFile, newFile] = await Promise.all([ endpoint ? (0, loaders_js_1.printSchemaFromEndpoint)(endpoint) : loadFile({ ref: schemaRef, path: schemaPath, }), isNewSchemaUrl ? (0, loaders_js_1.printSchemaFromEndpoint)(schemaPath) : loadFile({ path: schemaPath, ref, workspace, }), ]); core.info('Got both sources'); let oldSchema; let newSchema; let sources; if ((0, path_1.extname)(schemaPath.toLowerCase()) === '.json') { oldSchema = endpoint ? (0, graphql_1.buildSchema)(oldFile) : (0, graphql_1.buildClientSchema)(JSON.parse(oldFile)); newSchema = (0, graphql_1.buildClientSchema)(JSON.parse(newFile)); sources = { old: new graphql_1.Source((0, graphql_1.printSchema)(oldSchema), endpoint || `${schemaRef}:${schemaPath}`), new: new graphql_1.Source((0, graphql_1.printSchema)(newSchema), schemaPath), }; } else { sources = { old: new graphql_1.Source(oldFile, endpoint || `${schemaRef}:${schemaPath}`), new: new graphql_1.Source(newFile, schemaPath), }; oldSchema = (0, schema_js_1.produceSchema)(sources.old); newSchema = (0, schema_js_1.produceSchema)(sources.new); } const schemas = { old: oldSchema, new: newSchema, }; core.info(`Built both schemas`); core.info(`Start comparing schemas`); const action = await (0, diff_js_1.diff)({ path: schemaPath, schemas, sources, rules, config, }); let conclusion = action.conclusion; let annotations = action.annotations || []; const changes = action.changes || []; core.setOutput('changes', String(changes.length || 0)); core.info(`Changes: ${changes.length || 0}`); const hasApprovedBreakingChangeLabel = pullRequest?.labels?.some((label) => label.name === approveLabel); // Force Success when failOnBreaking is disabled if ((failOnBreaking === false || hasApprovedBreakingChangeLabel) && conclusion === types_js_1.CheckConclusion.Failure) { core.info('FailOnBreaking disabled. Forcing SUCCESS'); conclusion = types_js_1.CheckConclusion.Success; } if (useAnnotations === false || isNewSchemaUrl) { core.info(`Anotations are disabled. Skipping annotations...`); annotations = []; } const summary = (0, utils_js_1.createSummary)(changes, 100, false); const title = conclusion === types_js_1.CheckConclusion.Failure ? 'Something is wrong with your schema' : 'Everything looks good'; core.info(`Conclusion: ${conclusion}`); try { return await (0, checks_js_1.updateCheckRun)(octokit, checkId, { conclusion, output: { title, summary, annotations }, }); } catch (e) { // Error core.error(e.message || e); const title = 'Invalid config. Failed to add annotation'; await (0, checks_js_1.updateCheckRun)(octokit, checkId, { conclusion: types_js_1.CheckConclusion.Failure, output: { title, summary: title, annotations: [] }, }); return core.setFailed(title); } }