Skip to content

Commit 2a5d3c2

Browse files
amscannegvisor-bot
authored andcommitted
Add YAML validation for configuration files.
For validation, the "on" key in existing YAML files is changed to a literal string. In the YAML spec, on is a keyword which encodes a boolean value, so without relying on a specific implementation the YAML files are technically not encoding an object that complies with the specification. PiperOrigin-RevId: 350172147
1 parent 622db84 commit 2a5d3c2

File tree

12 files changed

+345
-6
lines changed

12 files changed

+345
-6
lines changed

.github/workflows/build.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
# This workflow also generates the build badge that is referred to by
77
# the main README.
88
name: "Build"
9-
on:
9+
"on":
1010
push:
1111
branches:
1212
- master

.github/workflows/go.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
# workflow simply generates and pushes the branch, as long as appropriate
44
# permissions are available.
55
name: "Go"
6-
on:
6+
"on":
77
push:
88
branches:
99
- master

.github/workflows/issue_reviver.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# This workflow revives issues that are still referenced in the code, and may
22
# have been accidentally closed or marked stale.
33
name: "Issue reviver"
4-
on:
4+
"on":
55
schedule:
66
- cron: '0 0 * * *'
77

.github/workflows/labeler.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Labeler labels incoming pull requests.
22
name: "Labeler"
3-
on:
3+
"on":
44
- pull_request
55

66
jobs:

.github/workflows/stale.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# The stale workflow closes stale issues and pull requests, unless specific
22
# tags have been applied in order to keep them open.
33
name: "Close stale issues"
4-
on:
4+
"on":
55
schedule:
66
- cron: "0 0 * * *"
77

BUILD

+19
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
load("//tools:defs.bzl", "build_test", "gazelle", "go_path")
22
load("//tools/nogo:defs.bzl", "nogo_config")
3+
load("//tools/yamltest:defs.bzl", "yaml_test")
34
load("//website:defs.bzl", "doc")
45

56
package(licenses = ["notice"])
@@ -50,6 +51,24 @@ doc(
5051
weight = "99",
5152
)
5253

54+
yaml_test(
55+
name = "nogo_config_test",
56+
srcs = glob(["nogo*.yaml"]),
57+
schema = "//tools/nogo:config-schema.json",
58+
)
59+
60+
yaml_test(
61+
name = "github_workflows_test",
62+
srcs = glob([".github/workflows/*.yml"]),
63+
schema = "@github_workflow_schema//file",
64+
)
65+
66+
yaml_test(
67+
name = "buildkite_pipelines_test",
68+
srcs = glob([".buildkite/*.yaml"]),
69+
schema = "@buildkite_pipeline_schema//file",
70+
)
71+
5372
# The sandbox filegroup is used for sandbox-internal dependencies.
5473
package_group(
5574
name = "sandbox",

WORKSPACE

+35-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
1+
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive", "http_file")
22
load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
33

44
# Bazel/starlark utilities.
@@ -176,6 +176,19 @@ http_archive(
176176
],
177177
)
178178

179+
# Schemas for testing.
180+
http_file(
181+
name = "buildkite_pipeline_schema",
182+
sha256 = "3369c58038b4d55c08928affafb653716eb1e7b3cabb4a391aef979dd921f4e1",
183+
urls = ["https://raw.githubusercontent.com/buildkite/pipeline-schema/f7a0894074d194bcf19eec5411fec0528f7f4180/schema.json"],
184+
)
185+
186+
http_file(
187+
name = "github_workflow_schema",
188+
sha256 = "2c375bb43dbc8b32b1bed46c290d0b70a8fa2aca7a5484dfca1b6e9c38cf9e7a",
189+
urls = ["https://raw.githubusercontent.com/SchemaStore/schemastore/27612065234778feaac216ce14dd47846fe0a2dd/src/schemas/json/github-workflow.json"],
190+
)
191+
179192
# External Go repositories.
180193
#
181194
# Unfortunately, gazelle will automatically parse go modules in the
@@ -1391,3 +1404,24 @@ go_repository(
13911404
sum = "h1:+ySTxfHnfzZb9ys375PXNlLhkJPLKgHajBU0N62BDvE=",
13921405
version = "v0.0.0-20190801114015-581e00157fb1",
13931406
)
1407+
1408+
go_repository(
1409+
name = "com_github_xeipuuv_gojsonpointer",
1410+
importpath = "github.com/xeipuuv/gojsonpointer",
1411+
sum = "h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo=",
1412+
version = "v0.0.0-20190905194746-02993c407bfb",
1413+
)
1414+
1415+
go_repository(
1416+
name = "com_github_xeipuuv_gojsonreference",
1417+
importpath = "github.com/xeipuuv/gojsonreference",
1418+
sum = "h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0=",
1419+
version = "v0.0.0-20180127040603-bd5ef7bd5415",
1420+
)
1421+
1422+
go_repository(
1423+
name = "com_github_xeipuuv_gojsonschema",
1424+
importpath = "github.com/xeipuuv/gojsonschema",
1425+
sum = "h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74=",
1426+
version = "v1.2.0",
1427+
)

tools/nogo/BUILD

+2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ load("//tools/nogo:defs.bzl", "nogo_objdump_tool", "nogo_stdlib", "nogo_target")
33

44
package(licenses = ["notice"])
55

6+
exports_files(["config-schema.json"])
7+
68
nogo_target(
79
name = "target",
810
goarch = select_goarch(),

tools/nogo/config-schema.json

+97
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
{
2+
"$schema": "http://json-schema.org/draft-07/schema",
3+
"definitions": {
4+
"group": {
5+
"type": "object",
6+
"properties": {
7+
"name": {
8+
"description": "The name of the group.",
9+
"type": "string"
10+
},
11+
"regex": {
12+
"description": "A regular expression for matching paths.",
13+
"type": "string"
14+
},
15+
"default": {
16+
"description": "Whether the group is enabled by default.",
17+
"type": "boolean"
18+
}
19+
},
20+
"required": [
21+
"name",
22+
"regex",
23+
"default"
24+
],
25+
"additionalProperties": false
26+
},
27+
"regexlist": {
28+
"description": "A list of regular expressions.",
29+
"oneOf": [
30+
{
31+
"type": "array",
32+
"items": {
33+
"type": "string"
34+
}
35+
},
36+
{
37+
"type": "null"
38+
}
39+
]
40+
},
41+
"rule": {
42+
"type": "object",
43+
"properties": {
44+
"exclude": {
45+
"description": "A regular expression for paths to exclude.",
46+
"$ref": "#/definitions/regexlist"
47+
},
48+
"suppress": {
49+
"description": "A regular expression for messages to suppress.",
50+
"$ref": "#/definitions/regexlist"
51+
}
52+
},
53+
"additionalProperties": false
54+
},
55+
"ruleList": {
56+
"type": "object",
57+
"additionalProperties": {
58+
"oneOf": [
59+
{
60+
"$ref": "#/definitions/rule"
61+
},
62+
{
63+
"type": "null"
64+
}
65+
]
66+
}
67+
}
68+
},
69+
"properties": {
70+
"groups": {
71+
"description": "A definition of all groups.",
72+
"type": "array",
73+
"items": {
74+
"$ref": "#/definitions/group"
75+
},
76+
"minItems": 1
77+
},
78+
"global": {
79+
"description": "A global set of rules.",
80+
"type": "object",
81+
"additionalProperties": {
82+
"$ref": "#/definitions/rule"
83+
}
84+
},
85+
"analyzers": {
86+
"description": "A definition of all groups.",
87+
"type": "object",
88+
"additionalProperties": {
89+
"$ref": "#/definitions/ruleList"
90+
}
91+
}
92+
},
93+
"required": [
94+
"groups"
95+
],
96+
"additionalProperties": false
97+
}

tools/yamltest/BUILD

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
load("//tools:defs.bzl", "go_binary")
2+
3+
package(licenses = ["notice"])
4+
5+
go_binary(
6+
name = "yamltest",
7+
srcs = ["main.go"],
8+
visibility = ["//visibility:public"],
9+
deps = [
10+
"@com_github_xeipuuv_gojsonschema//:go_default_library",
11+
"@in_gopkg_yaml_v2//:go_default_library",
12+
],
13+
)

tools/yamltest/defs.bzl

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
"""Tools for testing yaml files against schemas."""
2+
3+
def _yaml_test_impl(ctx):
4+
"""Implementation for yaml_test."""
5+
runner = ctx.actions.declare_file(ctx.label.name)
6+
ctx.actions.write(runner, "\n".join([
7+
"#!/bin/bash",
8+
"set -euo pipefail",
9+
"%s -schema=%s -- %s" % (
10+
ctx.files._tool[0].short_path,
11+
ctx.files.schema[0].short_path,
12+
" ".join([f.short_path for f in ctx.files.srcs]),
13+
),
14+
]), is_executable = True)
15+
return [DefaultInfo(
16+
runfiles = ctx.runfiles(files = ctx.files._tool + ctx.files.schema + ctx.files.srcs),
17+
executable = runner,
18+
)]
19+
20+
yaml_test = rule(
21+
implementation = _yaml_test_impl,
22+
doc = "Tests a yaml file against a schema.",
23+
attrs = {
24+
"srcs": attr.label_list(
25+
doc = "The input yaml files.",
26+
mandatory = True,
27+
allow_files = True,
28+
),
29+
"schema": attr.label(
30+
doc = "The schema file in JSON schema format.",
31+
allow_single_file = True,
32+
mandatory = True,
33+
),
34+
"_tool": attr.label(
35+
executable = True,
36+
cfg = "host",
37+
default = Label("//tools/yamltest:yamltest"),
38+
),
39+
},
40+
test = True,
41+
)

0 commit comments

Comments
 (0)