Skip to content

Commit

Permalink
Add breaking/dangerous/safe messages to action output
Browse files Browse the repository at this point in the history
  • Loading branch information
arxeiss committed May 27, 2024
1 parent 7b202c0 commit 5123440
Show file tree
Hide file tree
Showing 9 changed files with 165 additions and 46 deletions.
10 changes: 10 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ inputs:
For example, "Check Public API" and "Check Internal API".
annotations:
description: Use annotation (enabled by default)
create-action-check:
description: |
Create Github Action check with summary. When disabled, annotations are disabled too. (enabled by default)
It can be useful to disable, when running on master branch or similar. And when subsequent step is using output and annotations nor check is required.
fail-on-breaking:
description: Fail on breaking changes (enabled by default)
approve-label:
Expand Down Expand Up @@ -56,6 +60,12 @@ inputs:
outputs:
changes:
description: Total number of changes
breaking-changes:
description: List of breaking changes. Each item is message string.
dangerous-changes:
description: List of dangerous changes. Each item is message string.
safe-changes:
description: List of safe changes. Each item is message string.
runs:
using: node20
main: action/index.js
43 changes: 42 additions & 1 deletion action/index.js

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions action/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"type": "module"
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@
"@types/express": "4.17.21",
"@types/node": "20.12.12",
"@types/yargs": "17.0.32",
"@zeit/ncc": "0.22.3",
"@vercel/ncc": "0.38.1",
"bob-the-bundler": "7.0.1",
"eslint": "8.57.0",
"graphql": "16.8.1",
Expand Down
6 changes: 6 additions & 0 deletions packages/action/helpers/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ export interface ActionResult {
changes?: Change[];
}

export interface GroupedChanges {
breaking: Change[];
dangerous: Change[];
safe: Change[];
}

export interface Annotation {
path: string;
start_line: number;
Expand Down
31 changes: 19 additions & 12 deletions packages/action/helpers/utils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Change, CriticalityLevel } from '@graphql-inspector/core';
import { Endpoint } from './config.js';
import { GroupedChanges } from './types.js';

export function bolderize(msg: string): string {
return quotesTransformer(msg, '**');
Expand Down Expand Up @@ -28,17 +29,23 @@ export function filterChangesByLevel(level: CriticalityLevel) {
return (change: Change) => change.criticality.level === level;
}

export function splitChangesIntoGroups(changes: Change[]): GroupedChanges {
return {
breaking: changes.filter(filterChangesByLevel(CriticalityLevel.Breaking)),
dangerous: changes.filter(filterChangesByLevel(CriticalityLevel.Dangerous)),
safe: changes.filter(filterChangesByLevel(CriticalityLevel.NonBreaking)),
};
}

export function createSummary(changes: Change[], summaryLimit: number, isLegacyConfig = false) {
const breakingChanges = changes.filter(filterChangesByLevel(CriticalityLevel.Breaking));
const dangerousChanges = changes.filter(filterChangesByLevel(CriticalityLevel.Dangerous));
const safeChanges = changes.filter(filterChangesByLevel(CriticalityLevel.NonBreaking));
const groupedChanges = splitChangesIntoGroups(changes);

const summary: string[] = [
`# Found ${changes.length} change${changes.length > 1 ? 's' : ''}`,
'',
`Breaking: ${breakingChanges.length}`,
`Dangerous: ${dangerousChanges.length}`,
`Safe: ${safeChanges.length}`,
`Breaking: ${groupedChanges.breaking.length}`,
`Dangerous: ${groupedChanges.dangerous.length}`,
`Safe: ${groupedChanges.safe.length}`,
];

if (isLegacyConfig) {
Expand Down Expand Up @@ -74,16 +81,16 @@ export function createSummary(changes: Change[], summaryLimit: number, isLegacyC
summaryLimit -= changes.length;
}

if (breakingChanges.length) {
addChangesToSummary('Breaking', breakingChanges);
if (groupedChanges.breaking.length) {
addChangesToSummary('Breaking', groupedChanges.breaking);
}

if (dangerousChanges.length) {
addChangesToSummary('Dangerous', dangerousChanges);
if (groupedChanges.dangerous.length) {
addChangesToSummary('Dangerous', groupedChanges.dangerous);
}

if (safeChanges.length) {
addChangesToSummary('Safe', safeChanges);
if (groupedChanges.safe.length) {
addChangesToSummary('Safe', groupedChanges.safe);
}

summary.push(
Expand Down
70 changes: 48 additions & 22 deletions packages/action/src/run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { diff } from '../helpers/diff.js';
import { printSchemaFromEndpoint } from '../helpers/loaders.js';
import { produceSchema } from '../helpers/schema.js';
import { CheckConclusion } from '../helpers/types.js';
import { createSummary } from '../helpers/utils.js';
import { createSummary, splitChangesIntoGroups } from '../helpers/utils.js';
import { updateCheckRun } from './checks.js';
import { fileLoader } from './files.js';
import { getAssociatedPullRequest, getCurrentCommitSha } from './git.js';
Expand Down Expand Up @@ -41,6 +41,7 @@ export async function run() {
const approveLabel: string = core.getInput('approve-label') || 'approved-breaking-change';
const rulesList = getInputAsArray('rules') || [];
const onUsage = core.getInput('onUsage');
const createActionCheck = castToBoolean(core.getInput('create-action-check'), true);

const octokit = github.getOctokit(token);

Expand All @@ -50,19 +51,26 @@ export async function run() {
// pull request
const pullRequest = await getAssociatedPullRequest(octokit, commitSha);

core.info(`Creating a check named "${checkName}"`);

const check = await octokit.checks.create({
owner,
repo,
name: checkName,
head_sha: commitSha,
status: 'in_progress',
});
let checkId = null;
let seeCheckURL = '';
if (createActionCheck) {
core.info(`Creating a check named "${checkName}"`);

const check = await octokit.checks.create({
owner,
repo,
name: checkName,
head_sha: commitSha,
status: 'in_progress',
});

const checkId = check.data.id;
checkId = check.data.id;
seeCheckURL = ' For more info see: ' + check.data.html_url;

core.info(`Check ID: ${checkId}`);
core.info(`Check ID: ${checkId}`);
} else {
core.info('Skipping check creation - disabled by input option');
}

const schemaPointer = core.getInput('schema', { required: true });

Expand Down Expand Up @@ -188,8 +196,20 @@ export async function run() {
let annotations = action.annotations || [];
const changes = action.changes || [];

const groupedChanges = splitChangesIntoGroups(changes);
core.setOutput('changes', String(changes.length || 0));
core.info(`Changes: ${changes.length || 0}`);
core.setOutput(
'breaking-changes',
groupedChanges.breaking.map(c => c.message),
);
core.setOutput(
'dangerous-changes',
groupedChanges.dangerous.map(c => c.message),
);
core.setOutput(
'safe-changes',
groupedChanges.safe.map(c => c.message),
);

const hasApprovedBreakingChangeLabel = pullRequest?.labels?.some(
(label: any) => label.name === approveLabel,
Expand All @@ -204,20 +224,26 @@ export async function run() {
conclusion = CheckConclusion.Success;
}

if (useAnnotations === false || isNewSchemaUrl) {
core.info(`Anotations are disabled. Skipping annotations...`);
annotations = [];
}

const summary = createSummary(changes, 100, false);

const title =
conclusion === CheckConclusion.Failure
? 'Something is wrong with your schema'
? 'Something is wrong with your schema.' + seeCheckURL // add Check URL to navigate users to Check from action.
: 'Everything looks good';

core.info(`Conclusion: ${conclusion}`);

// Action Check is disabled
if (checkId === null) {
core.info('Github Action Check is disabled, use outputs to determine errors');
if (conclusion === CheckConclusion.Failure) {
core.setFailed(conclusion);
}
return;
}

if (useAnnotations === false || isNewSchemaUrl) {
core.info(`Anotations are disabled. Skipping annotations...`);
annotations = [];
}
const summary = createSummary(changes, 100, false);
try {
return await updateCheckRun(octokit, checkId, {
conclusion,
Expand Down
19 changes: 9 additions & 10 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

27 changes: 27 additions & 0 deletions website/src/pages/docs/products/action.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,19 @@ Use annotation (`true` by default).
annotations: false
```

### `create-action-check`

Create Github Action check with summary. When disabled, annotations are disabled too. (`true` by default)

It can be useful to disable, when running on master branch or similar. And when subsequent step is using output and annotations nor check is required.

```yaml
- uses: kamilkisiela/graphql-inspector@master
with:
schema: 'master:schema.graphql'
create-action-check: false
```

### `fail-on-breaking`

Fail on breaking changes (`true` by default).
Expand Down Expand Up @@ -161,6 +174,20 @@ to see how to use outputs.

Total number of changes

### `breaking-changes`

List of breaking changes. Each item is message string.

Example: ```["Type `Abc` was removed", "Field `Xyz` was removed from object type `Abc`"]```

### `dangerous-changes`

List of dangerous changes. Each item is message string, see `breaking-changes` for example.

### `safe-changes`

List of safe changes. Each item is message string, see `breaking-changes` for example.

![Summary](/assets/img/github/summary.jpg)

![Annotations](/assets/img/cli/github.jpg)

0 comments on commit 5123440

Please sign in to comment.