Skip to content

Commit a75ed20

Browse files
authored
Fix github-workflow schema to avoid ambiguous $ref (SchemaStore#5027)
For the `pull_request`, `pull_request_target`, and `push` event types, the schema was declared to both define properties and use a `$ref` which defined properties (`#/definitions/ref`). This usage is ambiguous at best, since it's unclear if the properties are meant to be merged -- which is the intent and AJV's behavior -- or overridden. These definitions are updated here to avoid using a $ref at all, and greatly enhance the clarity of their semantics by nesting `oneOf` and `allOf` in a way which better reflects the criteria being declared. The newly added negative test passes with AJV using the schema in `master` but fails when run through `python-jsonschema`'s toolchain. Specifically, a failure is easy to produce with pipx run check-jsonschema \ --schemafile schemas/json/github-workflow.json \ src/negative_test/github-workflow/bad_pull_request_event_declaration.yaml With the schema updated to remove the unclear `$ref` loading, both tools agree that the negative test input is incorrect.
1 parent 71c836f commit a75ed20

File tree

2 files changed

+202
-126
lines changed

2 files changed

+202
-126
lines changed
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# yaml-language-server: $schema=../../schemas/json/github-workflow.json
2+
on:
3+
pull_request:
4+
# this is a typo! it should be `paths-ignore`
5+
ignore-paths: ['foo.yaml']
6+
7+
jobs:
8+
with:
9+
runs-on: ubuntu-latest
10+
steps:
11+
- uses: actions/checkout@v1

src/schemas/json/github-workflow.json

Lines changed: 191 additions & 126 deletions
Original file line numberDiff line numberDiff line change
@@ -337,53 +337,6 @@
337337
"$ref": "#/definitions/globs",
338338
"description": "When using the push and pull_request events, you can configure a workflow to run when at least one file does not match paths-ignore or at least one modified file matches the configured paths. Path filters are not evaluated for pushes to tags.\nThe paths-ignore and paths keywords accept glob patterns that use the * and ** wildcard characters to match more than one path name. For more information, see https://help.github.com/en/github/automating-your-workflow-with-github-actions/workflow-syntax-for-github-actions#filter-pattern-cheat-sheet.\nYou can exclude paths using two types of filters. You cannot use both of these filters for the same event in a workflow.\n- paths-ignore - Use the paths-ignore filter when you only need to exclude path names.\n- paths - Use the paths filter when you need to filter paths for positive matches and exclude paths."
339339
},
340-
"ref": {
341-
"properties": {
342-
"branches": {
343-
"$ref": "#/definitions/branch"
344-
},
345-
"branches-ignore": {
346-
"$ref": "#/definitions/branch"
347-
},
348-
"tags": {
349-
"$ref": "#/definitions/branch"
350-
},
351-
"tags-ignore": {
352-
"$ref": "#/definitions/branch"
353-
},
354-
"paths": {
355-
"$ref": "#/definitions/path"
356-
},
357-
"paths-ignore": {
358-
"$ref": "#/definitions/path"
359-
}
360-
},
361-
"oneOf": [
362-
{
363-
"type": "object",
364-
"allOf": [
365-
{
366-
"not": {
367-
"required": ["branches", "branches-ignore"]
368-
}
369-
},
370-
{
371-
"not": {
372-
"required": ["tags", "tags-ignore"]
373-
}
374-
},
375-
{
376-
"not": {
377-
"required": ["paths", "paths-ignore"]
378-
}
379-
}
380-
]
381-
},
382-
{
383-
"type": "null"
384-
}
385-
]
386-
},
387340
"shell": {
388341
"$comment": "https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsshell",
389342
"description": "You can override the default shell settings in the runner's operating system using the shell keyword. You can use built-in shell keywords, or you can define a custom set of shell options.",
@@ -1347,46 +1300,83 @@
13471300
},
13481301
"pull_request": {
13491302
"$comment": "https://help.github.com/en/github/automating-your-workflow-with-github-actions/events-that-trigger-workflows#pull-request-event-pull_request",
1350-
"$ref": "#/definitions/ref",
13511303
"description": "Runs your workflow anytime the pull_request event occurs. More than one activity type triggers this event. For information about the REST API, see https://developer.github.com/v3/pulls.\nNote: Workflows do not run on private base repositories when you open a pull request from a forked repository.\nWhen you create a pull request from a forked repository to the base repository, GitHub sends the pull_request event to the base repository and no pull request events occur on the forked repository.\nWorkflows don't run on forked repositories by default. You must enable GitHub Actions in the Actions tab of the forked repository.\nThe permissions for the GITHUB_TOKEN in forked repositories is read-only. For more information about the GITHUB_TOKEN, see https://help.github.com/en/articles/virtual-environments-for-github-actions.",
1352-
"properties": {
1353-
"types": {
1354-
"$ref": "#/definitions/types",
1355-
"items": {
1356-
"type": "string",
1357-
"enum": [
1358-
"assigned",
1359-
"unassigned",
1360-
"labeled",
1361-
"unlabeled",
1362-
"opened",
1363-
"edited",
1364-
"closed",
1365-
"reopened",
1366-
"synchronize",
1367-
"converted_to_draft",
1368-
"ready_for_review",
1369-
"locked",
1370-
"unlocked",
1371-
"milestoned",
1372-
"demilestoned",
1373-
"review_requested",
1374-
"review_request_removed",
1375-
"auto_merge_enabled",
1376-
"auto_merge_disabled",
1377-
"enqueued",
1378-
"dequeued"
1379-
]
1380-
},
1381-
"default": ["opened", "synchronize", "reopened"]
1382-
}
1383-
},
1384-
"patternProperties": {
1385-
"^(branche|tag|path)s(-ignore)?$": {
1386-
"type": "array"
1304+
"oneOf": [
1305+
{ "type": "null" },
1306+
{
1307+
"allOf": [
1308+
{
1309+
"type": "object",
1310+
"properties": {
1311+
"types": {
1312+
"$ref": "#/definitions/types",
1313+
"items": {
1314+
"type": "string",
1315+
"enum": [
1316+
"assigned",
1317+
"unassigned",
1318+
"labeled",
1319+
"unlabeled",
1320+
"opened",
1321+
"edited",
1322+
"closed",
1323+
"reopened",
1324+
"synchronize",
1325+
"converted_to_draft",
1326+
"ready_for_review",
1327+
"locked",
1328+
"unlocked",
1329+
"milestoned",
1330+
"demilestoned",
1331+
"review_requested",
1332+
"review_request_removed",
1333+
"auto_merge_enabled",
1334+
"auto_merge_disabled",
1335+
"enqueued",
1336+
"dequeued"
1337+
]
1338+
},
1339+
"default": ["opened", "synchronize", "reopened"]
1340+
},
1341+
"branches": {
1342+
"$ref": "#/definitions/branch"
1343+
},
1344+
"branches-ignore": {
1345+
"$ref": "#/definitions/branch"
1346+
},
1347+
"tags": {
1348+
"$ref": "#/definitions/branch"
1349+
},
1350+
"tags-ignore": {
1351+
"$ref": "#/definitions/branch"
1352+
},
1353+
"paths": {
1354+
"$ref": "#/definitions/path"
1355+
},
1356+
"paths-ignore": {
1357+
"$ref": "#/definitions/path"
1358+
}
1359+
},
1360+
"additionalProperties": false
1361+
},
1362+
{
1363+
"not": {
1364+
"required": ["branches", "branches-ignore"]
1365+
}
1366+
},
1367+
{
1368+
"not": {
1369+
"required": ["tags", "tags-ignore"]
1370+
}
1371+
},
1372+
{
1373+
"not": {
1374+
"required": ["paths", "paths-ignore"]
1375+
}
1376+
}
1377+
]
13871378
}
1388-
},
1389-
"additionalProperties": false
1379+
]
13901380
},
13911381
"pull_request_review": {
13921382
"$comment": "https://help.github.com/en/github/automating-your-workflow-with-github-actions/events-that-trigger-workflows#pull-request-review-event-pull_request_review",
@@ -1420,54 +1410,129 @@
14201410
},
14211411
"pull_request_target": {
14221412
"$comment": "https://docs.github.com/en/actions/reference/events-that-trigger-workflows#pull_request_target",
1423-
"$ref": "#/definitions/ref",
14241413
"description": "This event is similar to pull_request, except that it runs in the context of the base repository of the pull request, rather than in the merge commit. This means that you can more safely make your secrets available to the workflows triggered by the pull request, because only workflows defined in the commit on the base repository are run. For example, this event allows you to create workflows that label and comment on pull requests, based on the contents of the event payload.",
1425-
"properties": {
1426-
"types": {
1427-
"$ref": "#/definitions/types",
1428-
"items": {
1429-
"type": "string",
1430-
"enum": [
1431-
"assigned",
1432-
"unassigned",
1433-
"labeled",
1434-
"unlabeled",
1435-
"opened",
1436-
"edited",
1437-
"closed",
1438-
"reopened",
1439-
"synchronize",
1440-
"converted_to_draft",
1441-
"ready_for_review",
1442-
"locked",
1443-
"unlocked",
1444-
"review_requested",
1445-
"review_request_removed",
1446-
"auto_merge_enabled",
1447-
"auto_merge_disabled"
1448-
]
1449-
},
1450-
"default": ["opened", "synchronize", "reopened"]
1414+
"oneOf": [
1415+
{ "type": "null" },
1416+
{
1417+
"allOf": [
1418+
{
1419+
"type": "object",
1420+
"properties": {
1421+
"types": {
1422+
"$ref": "#/definitions/types",
1423+
"items": {
1424+
"type": "string",
1425+
"enum": [
1426+
"assigned",
1427+
"unassigned",
1428+
"labeled",
1429+
"unlabeled",
1430+
"opened",
1431+
"edited",
1432+
"closed",
1433+
"reopened",
1434+
"synchronize",
1435+
"converted_to_draft",
1436+
"ready_for_review",
1437+
"locked",
1438+
"unlocked",
1439+
"review_requested",
1440+
"review_request_removed",
1441+
"auto_merge_enabled",
1442+
"auto_merge_disabled"
1443+
]
1444+
},
1445+
"default": ["opened", "synchronize", "reopened"]
1446+
},
1447+
"branches": {
1448+
"$ref": "#/definitions/branch"
1449+
},
1450+
"branches-ignore": {
1451+
"$ref": "#/definitions/branch"
1452+
},
1453+
"tags": {
1454+
"$ref": "#/definitions/branch"
1455+
},
1456+
"tags-ignore": {
1457+
"$ref": "#/definitions/branch"
1458+
},
1459+
"paths": {
1460+
"$ref": "#/definitions/path"
1461+
},
1462+
"paths-ignore": {
1463+
"$ref": "#/definitions/path"
1464+
}
1465+
},
1466+
"additionalProperties": false
1467+
},
1468+
{
1469+
"not": {
1470+
"required": ["branches", "branches-ignore"]
1471+
}
1472+
},
1473+
{
1474+
"not": {
1475+
"required": ["tags", "tags-ignore"]
1476+
}
1477+
},
1478+
{
1479+
"not": {
1480+
"required": ["paths", "paths-ignore"]
1481+
}
1482+
}
1483+
]
14511484
}
1452-
},
1453-
"patternProperties": {
1454-
"^(branche|tag|path)s(-ignore)?$": {}
1455-
},
1456-
"additionalProperties": false
1485+
]
14571486
},
14581487
"push": {
14591488
"$comment": "https://help.github.com/en/github/automating-your-workflow-with-github-actions/events-that-trigger-workflows#push-event-push",
1460-
"$ref": "#/definitions/ref",
14611489
"description": "Runs your workflow when someone pushes to a repository branch, which triggers the push event.\nNote: The webhook payload available to GitHub Actions does not include the added, removed, and modified attributes in the commit object. You can retrieve the full commit object using the REST API. For more information, see https://developer.github.com/v3/repos/commits/#get-a-single-commit.",
1462-
"patternProperties": {
1463-
"^(branche|tag|path)s(-ignore)?$": {
1464-
"items": {
1465-
"type": "string"
1466-
},
1467-
"type": "array"
1490+
"oneOf": [
1491+
{ "type": "null" },
1492+
{
1493+
"allOf": [
1494+
{
1495+
"type": "object",
1496+
"properties": {
1497+
"branches": {
1498+
"$ref": "#/definitions/branch"
1499+
},
1500+
"branches-ignore": {
1501+
"$ref": "#/definitions/branch"
1502+
},
1503+
"tags": {
1504+
"$ref": "#/definitions/branch"
1505+
},
1506+
"tags-ignore": {
1507+
"$ref": "#/definitions/branch"
1508+
},
1509+
"paths": {
1510+
"$ref": "#/definitions/path"
1511+
},
1512+
"paths-ignore": {
1513+
"$ref": "#/definitions/path"
1514+
}
1515+
},
1516+
"additionalProperties": false
1517+
},
1518+
{
1519+
"not": {
1520+
"required": ["branches", "branches-ignore"]
1521+
}
1522+
},
1523+
{
1524+
"not": {
1525+
"required": ["tags", "tags-ignore"]
1526+
}
1527+
},
1528+
{
1529+
"not": {
1530+
"required": ["paths", "paths-ignore"]
1531+
}
1532+
}
1533+
]
14681534
}
1469-
},
1470-
"additionalProperties": false
1535+
]
14711536
},
14721537
"registry_package": {
14731538
"$comment": "https://help.github.com/en/actions/reference/events-that-trigger-workflows#registry-package-event-registry_package",

0 commit comments

Comments
 (0)