@@ -235,7 +235,7 @@ The code above calls the "[AUTOTITLE](/rest/checks#update-a-check-run)" API endp
|
||||
|
||||
Here's what this code is doing. First, it updates the check run's status to `in_progress` and implicitly sets the `started_at` time to the current time. In [Part 2](#part-2-creating-the-octo-rubocop-ci-test) of this quickstart, you'll add code that kicks off a real CI test under `***** RUN A CI TEST *****`. For now, you'll leave that section as a placeholder, so the code that follows it will just simulate that the CI process succeeds and all tests pass. Finally, the code updates the status of the check run again to `completed`.
|
||||
|
||||
You'll notice in the "[AUTOTITLE](/rest/checks#update-a-check-run)" docs that when you provide a status of `completed`, the `conclusion` and `completed_at` parameters are required. The `conclusion` summarizes the outcome of a check run and can be `success`, `failure`, `neutral`, `cancelled`, `timed_out`, or `action_required`. You'll set the conclusion to `success`, the `completed_at` time to the current time, and the status to `completed`.
|
||||
You'll notice in the "[AUTOTITLE](/rest/checks#update-a-check-run)" docs that when you provide a status of `completed`, the `conclusion` and `completed_at` parameters are required. The `conclusion` summarizes the outcome of a check run and can be `success`, `failure`, `neutral`, `cancelled`, `timed_out`, `skipped`, or `action_required`. You'll set the conclusion to `success`, the `completed_at` time to the current time, and the status to `completed`.
|
||||
|
||||
You could also provide more details about what your check is doing, but you'll get to that in the next section. Let's test this code again by re-running `template_server.rb`:
|
||||
|
||||
|
||||
@@ -23,14 +23,17 @@ For an example of how to use the REST API with a {% data variables.product.prodn
|
||||
|
||||
When someone pushes code to a repository, GitHub creates a check suite for the last commit. A check suite is a collection of the [check runs](/rest/checks#check-runs) created by a single GitHub App for a specific commit. Check suites summarize the status and conclusion of the check runs that a suite includes.
|
||||
|
||||
The `status` can be `queued`, `in_progress`, or `complete`.
|
||||
The `status` can be `queued`, `in_progress`, or `completed`.
|
||||
|
||||
If the status is `complete`, the conclusion can be any of the following:
|
||||
If the status is `completed`, the conclusion can be any of the following:
|
||||
- `action_required`
|
||||
- `cancelled`
|
||||
- `timed_out`
|
||||
- `failure`
|
||||
- `neutral`
|
||||
- `skipped`
|
||||
- `stale`
|
||||
- `startup_failure`
|
||||
- `success`
|
||||
|
||||
The check suite reports the highest priority check run `conclusion` in the check suite's `conclusion`. For example, if three check runs have conclusions of `timed_out`, `success`, and `neutral` the check suite conclusion will be `timed_out`.
|
||||
@@ -49,7 +52,7 @@ To use the endpoints to manage check suites, the {% data variables.product.prodn
|
||||
|
||||
A check run is an individual test that is part of a check suite. Each run includes a status and conclusion.
|
||||
|
||||
The status can be `queued`, `in_progress`, or `complete`.
|
||||
The status can be `queued`, `in_progress`, or `completed`.
|
||||
|
||||
If the status is `completed`, the conclusion can be any of the following:
|
||||
- `action_required`
|
||||
@@ -57,6 +60,7 @@ If the status is `completed`, the conclusion can be any of the following:
|
||||
- `timed_out`
|
||||
- `failure`
|
||||
- `neutral`
|
||||
- `skipped`
|
||||
- `success`
|
||||
|
||||
If a check run is in an incomplete state for more than 14 days, then the check run's `conclusion` becomes `stale` and appears on {% data variables.product.prodname_dotcom %} as stale with {% octicon "issue-reopened" aria-label="The issue-reopened icon" %}. Only {% data variables.product.prodname_dotcom %} can mark check runs as `stale`. For more information about possible conclusions of a check run, see the [`conclusion` parameter](/rest/checks#create-a-check-run--parameters).
|
||||
|
||||
11
package-lock.json
generated
11
package-lock.json
generated
@@ -80,7 +80,6 @@
|
||||
"remark-parse": "^10.0.1",
|
||||
"remark-parse-no-trim": "^8.0.4",
|
||||
"remark-rehype": "^10.1.0",
|
||||
"revalidator": "^0.3.1",
|
||||
"rss-parser": "^3.12.0",
|
||||
"scroll-anchoring": "^0.1.0",
|
||||
"semver": "^7.3.7",
|
||||
@@ -17863,13 +17862,6 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/revalidator": {
|
||||
"version": "0.3.1",
|
||||
"license": "Apache 2.0",
|
||||
"engines": {
|
||||
"node": ">= 0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/rfdc": {
|
||||
"version": "1.3.0",
|
||||
"dev": true,
|
||||
@@ -32425,9 +32417,6 @@
|
||||
"version": "1.0.4",
|
||||
"dev": true
|
||||
},
|
||||
"revalidator": {
|
||||
"version": "0.3.1"
|
||||
},
|
||||
"rfdc": {
|
||||
"version": "1.3.0",
|
||||
"dev": true
|
||||
|
||||
@@ -82,7 +82,6 @@
|
||||
"remark-parse": "^10.0.1",
|
||||
"remark-parse-no-trim": "^8.0.4",
|
||||
"remark-rehype": "^10.1.0",
|
||||
"revalidator": "^0.3.1",
|
||||
"rss-parser": "^3.12.0",
|
||||
"scroll-anchoring": "^0.1.0",
|
||||
"semver": "^7.3.7",
|
||||
|
||||
@@ -3,67 +3,66 @@
|
||||
|
||||
// PREVIEWS
|
||||
export const previewsValidator = {
|
||||
type: 'object',
|
||||
required: [
|
||||
'title',
|
||||
'description',
|
||||
'toggled_by',
|
||||
'toggled_on',
|
||||
'owning_teams',
|
||||
'accept_header',
|
||||
'href',
|
||||
],
|
||||
properties: {
|
||||
title: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
},
|
||||
description: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
},
|
||||
toggled_by: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
},
|
||||
toggled_on: {
|
||||
type: 'array',
|
||||
required: true,
|
||||
},
|
||||
owning_teams: {
|
||||
type: 'array',
|
||||
required: true,
|
||||
},
|
||||
accept_header: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
},
|
||||
href: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// UPCOMING CHANGES
|
||||
export const upcomingChangesValidator = {
|
||||
type: 'object',
|
||||
required: ['location', 'description', 'reason', 'date', 'criticality', 'owner'],
|
||||
properties: {
|
||||
location: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
},
|
||||
description: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
},
|
||||
reason: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
},
|
||||
date: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
pattern: /^\d{4}-\d{2}-\d{2}$/,
|
||||
pattern: '^\\d{4}-\\d{2}-\\d{2}$',
|
||||
},
|
||||
criticality: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
pattern: '(breaking|dangerous)',
|
||||
},
|
||||
owner: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
pattern: /^[\S]*$/,
|
||||
pattern: '^[\\S]*$',
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -74,35 +73,27 @@ const coreProps = {
|
||||
properties: {
|
||||
name: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
},
|
||||
type: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
},
|
||||
kind: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
},
|
||||
id: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
},
|
||||
href: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
},
|
||||
description: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
},
|
||||
isDeprecated: {
|
||||
type: 'boolean',
|
||||
required: false,
|
||||
},
|
||||
preview: {
|
||||
type: 'object',
|
||||
required: false,
|
||||
properties: previewsValidator.properties,
|
||||
},
|
||||
},
|
||||
@@ -113,14 +104,15 @@ const corePropsPlusArgs = dup(coreProps)
|
||||
|
||||
corePropsPlusArgs.properties.args = {
|
||||
type: 'array',
|
||||
required: false,
|
||||
properties: coreProps.properties,
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: coreProps.properties,
|
||||
},
|
||||
}
|
||||
|
||||
// the args object can have defaultValue prop
|
||||
corePropsPlusArgs.properties.args.properties.defaultValue = {
|
||||
corePropsPlusArgs.properties.args.items.properties.defaultValue = {
|
||||
type: 'boolean',
|
||||
required: false,
|
||||
}
|
||||
|
||||
const corePropsNoType = dup(coreProps)
|
||||
@@ -132,45 +124,60 @@ delete corePropsNoDescription.properties.description
|
||||
// QUERIES
|
||||
const queries = dup(corePropsPlusArgs)
|
||||
|
||||
queries.type = 'object'
|
||||
queries.required = ['name', 'type', 'kind', 'id', 'href', 'description']
|
||||
|
||||
// MUTATIONS
|
||||
const mutations = dup(corePropsNoType)
|
||||
|
||||
mutations.type = 'object'
|
||||
mutations.required = ['name', 'kind', 'id', 'href', 'description', 'inputFields', 'returnFields']
|
||||
|
||||
mutations.properties.inputFields = {
|
||||
type: 'array',
|
||||
required: true,
|
||||
properties: corePropsNoDescription.properties,
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: corePropsNoDescription.properties,
|
||||
},
|
||||
}
|
||||
|
||||
mutations.properties.returnFields = {
|
||||
type: 'array',
|
||||
required: true,
|
||||
properties: coreProps.properties,
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: coreProps.properties,
|
||||
},
|
||||
}
|
||||
|
||||
// OBJECTS
|
||||
const objects = dup(corePropsNoType)
|
||||
|
||||
objects.type = 'object'
|
||||
objects.required = ['name', 'kind', 'id', 'href', 'description', 'fields']
|
||||
|
||||
objects.properties.fields = {
|
||||
type: 'array',
|
||||
required: true,
|
||||
properties: corePropsPlusArgs.properties,
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: corePropsPlusArgs.properties,
|
||||
},
|
||||
}
|
||||
|
||||
objects.properties.implements = {
|
||||
type: 'array',
|
||||
required: false,
|
||||
properties: {
|
||||
name: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
},
|
||||
id: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
},
|
||||
href: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
items: {
|
||||
type: 'object',
|
||||
required: ['name', 'id', 'href'],
|
||||
properties: {
|
||||
name: {
|
||||
type: 'string',
|
||||
},
|
||||
id: {
|
||||
type: 'string',
|
||||
},
|
||||
href: {
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -178,26 +185,35 @@ objects.properties.implements = {
|
||||
// INTERFACES
|
||||
const interfaces = dup(corePropsNoType)
|
||||
|
||||
interfaces.type = 'object'
|
||||
interfaces.required = ['name', 'kind', 'id', 'href', 'description', 'fields']
|
||||
|
||||
interfaces.properties.fields = {
|
||||
type: 'array',
|
||||
required: true,
|
||||
properties: corePropsPlusArgs.properties,
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: corePropsPlusArgs.properties,
|
||||
},
|
||||
}
|
||||
|
||||
// ENUMS
|
||||
const enums = dup(corePropsNoType)
|
||||
|
||||
enums.type = 'object'
|
||||
enums.required = ['name', 'kind', 'id', 'href', 'description', 'values']
|
||||
|
||||
enums.properties.values = {
|
||||
type: 'array',
|
||||
required: true,
|
||||
properties: {
|
||||
name: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
},
|
||||
description: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
items: {
|
||||
type: 'object',
|
||||
required: ['name', 'description'],
|
||||
properties: {
|
||||
name: {
|
||||
type: 'string',
|
||||
},
|
||||
description: {
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -205,21 +221,24 @@ enums.properties.values = {
|
||||
// UNIONS
|
||||
const unions = dup(corePropsNoType)
|
||||
|
||||
unions.type = 'object'
|
||||
unions.required = ['name', 'kind', 'id', 'href', 'description', 'possibleTypes']
|
||||
|
||||
unions.properties.possibleTypes = {
|
||||
type: 'array',
|
||||
required: true,
|
||||
properties: {
|
||||
name: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
},
|
||||
id: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
},
|
||||
href: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
items: {
|
||||
type: 'object',
|
||||
required: ['name', 'id', 'href'],
|
||||
properties: {
|
||||
name: {
|
||||
type: 'string',
|
||||
},
|
||||
id: {
|
||||
type: 'string',
|
||||
},
|
||||
href: {
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -227,15 +246,22 @@ unions.properties.possibleTypes = {
|
||||
// INPUT OBJECTS
|
||||
const inputObjects = dup(corePropsNoType)
|
||||
|
||||
inputObjects.type = 'object'
|
||||
inputObjects.required = ['name', 'kind', 'id', 'href', 'description', 'inputFields']
|
||||
|
||||
inputObjects.properties.inputFields = {
|
||||
type: 'array',
|
||||
required: true,
|
||||
properties: coreProps.properties,
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: coreProps.properties,
|
||||
},
|
||||
}
|
||||
|
||||
// SCALARS
|
||||
const scalars = dup(corePropsNoType)
|
||||
scalars.properties.kind.required = false
|
||||
|
||||
scalars.type = 'object'
|
||||
scalars.required = ['name', 'id', 'href', 'description']
|
||||
|
||||
function dup(obj) {
|
||||
return JSON.parse(JSON.stringify(obj))
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { jest } from '@jest/globals'
|
||||
import Ajv from 'ajv'
|
||||
|
||||
import readJsonFile from '../../lib/read-json-file.js'
|
||||
import {
|
||||
@@ -6,7 +7,7 @@ import {
|
||||
previewsValidator,
|
||||
upcomingChangesValidator,
|
||||
} from '../../src/graphql/lib/validator.js'
|
||||
import revalidator from 'revalidator'
|
||||
import { formatAjvErrors } from '../helpers/schemas.js'
|
||||
import { allVersions } from '../../lib/all-versions.js'
|
||||
import { GRAPHQL_DATA_DIR } from '../../src/graphql/lib/index.js'
|
||||
|
||||
@@ -14,6 +15,16 @@ const allVersionValues = Object.values(allVersions)
|
||||
const graphqlVersions = allVersionValues.map((v) => v.miscVersionName)
|
||||
const graphqlTypes = readJsonFile('./src/graphql/lib/types.json').map((t) => t.kind)
|
||||
|
||||
const ajv = new Ajv({ allErrors: true, allowUnionTypes: true })
|
||||
const previewsValidate = ajv.compile(previewsValidator)
|
||||
const upcomingChangesValidate = ajv.compile(upcomingChangesValidator)
|
||||
// setup ajv validator functions for each graphql type (e.g. queries, mutations,
|
||||
// etc.)
|
||||
const schemaValidatorFunctions = {}
|
||||
graphqlTypes.forEach((type) => {
|
||||
schemaValidatorFunctions[type] = ajv.compile(schemaValidator[type])
|
||||
})
|
||||
|
||||
describe('graphql json files', () => {
|
||||
jest.setTimeout(3 * 60 * 1000)
|
||||
|
||||
@@ -31,9 +42,16 @@ describe('graphql json files', () => {
|
||||
if (typeObjsTested.has(key)) return
|
||||
typeObjsTested.add(key)
|
||||
|
||||
const { valid, errors } = revalidator.validate(typeObj, schemaValidator[type])
|
||||
const errorMessage = JSON.stringify(errors, null, 2)
|
||||
expect(valid, errorMessage).toBe(true)
|
||||
const valid = schemaValidatorFunctions[type](typeObj)
|
||||
let errors
|
||||
|
||||
if (!valid) {
|
||||
errors = `kind: ${typeObj.kind}, name: ${typeObj.name}: ${formatAjvErrors(
|
||||
schemaValidatorFunctions[type].errors
|
||||
)}`
|
||||
}
|
||||
|
||||
expect(valid, errors).toBe(true)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -43,9 +61,14 @@ describe('graphql json files', () => {
|
||||
graphqlVersions.forEach((version) => {
|
||||
const previews = readJsonFile(`${GRAPHQL_DATA_DIR}/${version}/previews.json`)
|
||||
previews.forEach((preview) => {
|
||||
const { valid, errors } = revalidator.validate(preview, previewsValidator)
|
||||
const errorMessage = JSON.stringify(errors, null, 2)
|
||||
expect(valid, errorMessage).toBe(true)
|
||||
const valid = previewsValidate(preview)
|
||||
let errors
|
||||
|
||||
if (!valid) {
|
||||
errors = formatAjvErrors(previewsValidate.errors)
|
||||
}
|
||||
|
||||
expect(valid, errors).toBe(true)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -56,9 +79,14 @@ describe('graphql json files', () => {
|
||||
for (const changes of Object.values(upcomingChanges)) {
|
||||
// each object value is an array of changes
|
||||
changes.forEach((changeObj) => {
|
||||
const { valid, errors } = revalidator.validate(changeObj, upcomingChangesValidator)
|
||||
const errorMessage = JSON.stringify(errors, null, 2)
|
||||
expect(valid, errorMessage).toBe(true)
|
||||
const valid = upcomingChangesValidate(changeObj)
|
||||
let errors
|
||||
|
||||
if (!valid) {
|
||||
errors = formatAjvErrors(upcomingChangesValidate.errors)
|
||||
}
|
||||
|
||||
expect(valid, errors).toBe(true)
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user