Skip to content

Commit

Permalink
Add YAML validation for configuration files.
Browse files Browse the repository at this point in the history
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
  • Loading branch information
amscanne authored and gvisor-bot committed Jan 5, 2021
1 parent 622db84 commit 2a5d3c2
Show file tree
Hide file tree
Showing 12 changed files with 345 additions and 6 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
# This workflow also generates the build badge that is referred to by
# the main README.
name: "Build"
on:
"on":
push:
branches:
- master
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# workflow simply generates and pushes the branch, as long as appropriate
# permissions are available.
name: "Go"
on:
"on":
push:
branches:
- master
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/issue_reviver.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# This workflow revives issues that are still referenced in the code, and may
# have been accidentally closed or marked stale.
name: "Issue reviver"
on:
"on":
schedule:
- cron: '0 0 * * *'

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/labeler.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Labeler labels incoming pull requests.
name: "Labeler"
on:
"on":
- pull_request

jobs:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/stale.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# The stale workflow closes stale issues and pull requests, unless specific
# tags have been applied in order to keep them open.
name: "Close stale issues"
on:
"on":
schedule:
- cron: "0 0 * * *"

Expand Down
19 changes: 19 additions & 0 deletions BUILD
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
load("//tools:defs.bzl", "build_test", "gazelle", "go_path")
load("//tools/nogo:defs.bzl", "nogo_config")
load("//tools/yamltest:defs.bzl", "yaml_test")
load("//website:defs.bzl", "doc")

package(licenses = ["notice"])
Expand Down Expand Up @@ -50,6 +51,24 @@ doc(
weight = "99",
)

yaml_test(
name = "nogo_config_test",
srcs = glob(["nogo*.yaml"]),
schema = "//tools/nogo:config-schema.json",
)

yaml_test(
name = "github_workflows_test",
srcs = glob([".github/workflows/*.yml"]),
schema = "@github_workflow_schema//file",
)

yaml_test(
name = "buildkite_pipelines_test",
srcs = glob([".buildkite/*.yaml"]),
schema = "@buildkite_pipeline_schema//file",
)

# The sandbox filegroup is used for sandbox-internal dependencies.
package_group(
name = "sandbox",
Expand Down
36 changes: 35 additions & 1 deletion WORKSPACE
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive", "http_file")
load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")

# Bazel/starlark utilities.
Expand Down Expand Up @@ -176,6 +176,19 @@ http_archive(
],
)

# Schemas for testing.
http_file(
name = "buildkite_pipeline_schema",
sha256 = "3369c58038b4d55c08928affafb653716eb1e7b3cabb4a391aef979dd921f4e1",
urls = ["https://raw.githubusercontent.com/buildkite/pipeline-schema/f7a0894074d194bcf19eec5411fec0528f7f4180/schema.json"],
)

http_file(
name = "github_workflow_schema",
sha256 = "2c375bb43dbc8b32b1bed46c290d0b70a8fa2aca7a5484dfca1b6e9c38cf9e7a",
urls = ["https://raw.githubusercontent.com/SchemaStore/schemastore/27612065234778feaac216ce14dd47846fe0a2dd/src/schemas/json/github-workflow.json"],
)

# External Go repositories.
#
# Unfortunately, gazelle will automatically parse go modules in the
Expand Down Expand Up @@ -1391,3 +1404,24 @@ go_repository(
sum = "h1:+ySTxfHnfzZb9ys375PXNlLhkJPLKgHajBU0N62BDvE=",
version = "v0.0.0-20190801114015-581e00157fb1",
)

go_repository(
name = "com_github_xeipuuv_gojsonpointer",
importpath = "github.com/xeipuuv/gojsonpointer",
sum = "h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo=",
version = "v0.0.0-20190905194746-02993c407bfb",
)

go_repository(
name = "com_github_xeipuuv_gojsonreference",
importpath = "github.com/xeipuuv/gojsonreference",
sum = "h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0=",
version = "v0.0.0-20180127040603-bd5ef7bd5415",
)

go_repository(
name = "com_github_xeipuuv_gojsonschema",
importpath = "github.com/xeipuuv/gojsonschema",
sum = "h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74=",
version = "v1.2.0",
)
2 changes: 2 additions & 0 deletions tools/nogo/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ load("//tools/nogo:defs.bzl", "nogo_objdump_tool", "nogo_stdlib", "nogo_target")

package(licenses = ["notice"])

exports_files(["config-schema.json"])

nogo_target(
name = "target",
goarch = select_goarch(),
Expand Down
97 changes: 97 additions & 0 deletions tools/nogo/config-schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
{
"$schema": "http://json-schema.org/draft-07/schema",
"definitions": {
"group": {
"type": "object",
"properties": {
"name": {
"description": "The name of the group.",
"type": "string"
},
"regex": {
"description": "A regular expression for matching paths.",
"type": "string"
},
"default": {
"description": "Whether the group is enabled by default.",
"type": "boolean"
}
},
"required": [
"name",
"regex",
"default"
],
"additionalProperties": false
},
"regexlist": {
"description": "A list of regular expressions.",
"oneOf": [
{
"type": "array",
"items": {
"type": "string"
}
},
{
"type": "null"
}
]
},
"rule": {
"type": "object",
"properties": {
"exclude": {
"description": "A regular expression for paths to exclude.",
"$ref": "#/definitions/regexlist"
},
"suppress": {
"description": "A regular expression for messages to suppress.",
"$ref": "#/definitions/regexlist"
}
},
"additionalProperties": false
},
"ruleList": {
"type": "object",
"additionalProperties": {
"oneOf": [
{
"$ref": "#/definitions/rule"
},
{
"type": "null"
}
]
}
}
},
"properties": {
"groups": {
"description": "A definition of all groups.",
"type": "array",
"items": {
"$ref": "#/definitions/group"
},
"minItems": 1
},
"global": {
"description": "A global set of rules.",
"type": "object",
"additionalProperties": {
"$ref": "#/definitions/rule"
}
},
"analyzers": {
"description": "A definition of all groups.",
"type": "object",
"additionalProperties": {
"$ref": "#/definitions/ruleList"
}
}
},
"required": [
"groups"
],
"additionalProperties": false
}
13 changes: 13 additions & 0 deletions tools/yamltest/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
load("//tools:defs.bzl", "go_binary")

package(licenses = ["notice"])

go_binary(
name = "yamltest",
srcs = ["main.go"],
visibility = ["//visibility:public"],
deps = [
"@com_github_xeipuuv_gojsonschema//:go_default_library",
"@in_gopkg_yaml_v2//:go_default_library",
],
)
41 changes: 41 additions & 0 deletions tools/yamltest/defs.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
"""Tools for testing yaml files against schemas."""

def _yaml_test_impl(ctx):
"""Implementation for yaml_test."""
runner = ctx.actions.declare_file(ctx.label.name)
ctx.actions.write(runner, "\n".join([
"#!/bin/bash",
"set -euo pipefail",
"%s -schema=%s -- %s" % (
ctx.files._tool[0].short_path,
ctx.files.schema[0].short_path,
" ".join([f.short_path for f in ctx.files.srcs]),
),
]), is_executable = True)
return [DefaultInfo(
runfiles = ctx.runfiles(files = ctx.files._tool + ctx.files.schema + ctx.files.srcs),
executable = runner,
)]

yaml_test = rule(
implementation = _yaml_test_impl,
doc = "Tests a yaml file against a schema.",
attrs = {
"srcs": attr.label_list(
doc = "The input yaml files.",
mandatory = True,
allow_files = True,
),
"schema": attr.label(
doc = "The schema file in JSON schema format.",
allow_single_file = True,
mandatory = True,
),
"_tool": attr.label(
executable = True,
cfg = "host",
default = Label("//tools/yamltest:yamltest"),
),
},
test = True,
)
Loading

0 comments on commit 2a5d3c2

Please sign in to comment.