Skip to content

Commit

Permalink
Add schema for Antsibull changelogs (#2814)
Browse files Browse the repository at this point in the history
* Add schema for Antsibull changelogs

* chore: auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
  • Loading branch information
ssbarnea and pre-commit-ci[bot] authored Dec 14, 2022
1 parent 6fd2268 commit c98d662
Show file tree
Hide file tree
Showing 16 changed files with 296 additions and 1 deletion.
2 changes: 1 addition & 1 deletion .github/workflows/tox.yml
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ jobs:
WSLENV: FORCE_COLOR:PYTEST_REQPASS:TOXENV:GITHUB_STEP_SUMMARY
# Number of expected test passes, safety measure for accidental skip of
# tests. Update value if you add/remove tests.
PYTEST_REQPASS: 741
PYTEST_REQPASS: 742

steps:
- name: Activate WSL1
Expand Down
Empty file added examples/changelog.yml
Empty file.
1 change: 1 addition & 0 deletions src/ansiblelint/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@
{"requirements": "**/requirements.{yaml,yml}"}, # v2 and v1
{"playbook": "**/molecule/*/*.{yaml,yml}"}, # molecule playbooks
{"yaml": "**/{.ansible-lint,.yamllint}"},
{"changelog": "**/changelog.yml"},
{"yaml": "**/*.{yaml,yml}"},
{"yaml": "**/.*.{yaml,yml}"},
]
Expand Down
3 changes: 3 additions & 0 deletions src/ansiblelint/schemas/__store__.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
"etag": "bd98c32fe4b9672bdadb85efd0dbfded7ef08b6cfda5c0ff91fb1cf45e274e0e",
"url": "https://raw.githubusercontent.com/ansible/ansible-lint/main/src/ansiblelint/schemas/arg_specs.json"
},
"changelog": {
"url": "https://raw.githubusercontent.com/ansible/ansible-lint/main/src/ansiblelint/schemas/changelog.json"
},
"execution-environment": {
"etag": "17ebd7426f2f31e362f7e0eae6683fbb17b83983bc0fdfc2cdf5c83e1ed38808",
"url": "https://raw.githubusercontent.com/ansible/ansible-lint/main/src/ansiblelint/schemas/execution-environment.json"
Expand Down
98 changes: 98 additions & 0 deletions src/ansiblelint/schemas/changelog.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
{
"$defs": {
"release": {
"additionalProperties": false,
"properties": {
"changes": {
"additionalProperties": false,
"properties": {
"bugfixes": {
"items": {
"type": "string"
},
"type": "array"
},
"deprecated_features": {
"items": {
"type": "string"
},
"type": "array"
},
"minor_changes": {
"items": {
"type": "string"
},
"type": "array"
},
"release_summary": {
"type": "string"
}
},
"type": "object"
},
"codename": {
"type": "string"
},
"modules": {
"items": {
"properties": {
"description": {
"markdownDescription": "Value of `short_description from plugin `DOCUMENTATION`.",
"title": "Description",
"type": "string"
},
"name": {
"markdownDescription": " It must not be the FQCN, but the name inside the collection.",
"pattern": "[a-zA-Z0-9_]+",
"title": "Short module name",
"type": "string"
},
"namespace": {
"markdownDescription": "Must be `null` for plugin and objects. For modules it must be either empty string. The namespace is used to group new modules by their namespace inside the collection.",
"title": "Namespace",
"type": ["string", "null"]
}
},
"type": "object"
},
"type": "array"
},
"release_date": {
"format": "date",
"markdownDescription": "Use ISO-8601 date format, like 2020-12-31",
"pattern": "\\d\\d\\d\\d-\\d\\d-\\d\\d",
"title": "Date of the release.",
"type": "string"
}
},
"type": "object"
},
"semver": {
"pattern": "\\d+.\\d+.\\d+.*",
"title": "Version string following SemVer specification.",
"type": "string"
}
},
"$id": "https://raw.githubusercontent.com/ansible-lint/main/src/ansiblelint/schemas/changelog.json",
"$schema": "http://json-schema.org/draft-07/schema",
"additionalProperties": false,
"description": "Antsibull Changelog Schema",
"examples": ["changelog.yml"],
"markdownDescription": "See [Changelog YAML Format](https://github.com/ansible-community/antsibull-changelog/blob/main/docs/changelog.yaml-format.md)",
"properties": {
"ancestor": {
"$ref": "#/$defs/semver"
},
"releases": {
"patternProperties": {
"\\d+.\\d+.\\d+.*": {
"$ref": "#/$defs/release",
"type": "object"
}
},
"type": "object"
}
},
"title": "Antsibull Changelog Schema",
"type": "object"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
releases:
1.0.0:
release_date: 01-01-2020 # invalid date format, must be ISO-8601 !
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# ajv errors

```json
[
{
"instancePath": "/releases/1.0.0/release_date",
"keyword": "pattern",
"message": "must match pattern \"\\d\\d\\d\\d-\\d\\d-\\d\\d\"",
"params": {
"pattern": "\\d\\d\\d\\d-\\d\\d-\\d\\d"
},
"schemaPath": "#/$defs/release/properties/release_date/pattern"
}
]
```

# check-jsonschema

stdout:

```json
{
"status": "fail",
"errors": [
{
"filename": "negative_test/changelogs/invalid-date/changelog.yml",
"path": "$.releases.1.0.0.release_date",
"message": "'01-01-2020' is not a 'date'",
"has_sub_errors": false
},
{
"filename": "negative_test/changelogs/invalid-date/changelog.yml",
"path": "$.releases.1.0.0.release_date",
"message": "'01-01-2020' does not match '\\\\d\\\\d\\\\d\\\\d-\\\\d\\\\d-\\\\d\\\\d'",
"has_sub_errors": false
}
],
"parse_errors": []
}
```
4 changes: 4 additions & 0 deletions test/schemas/negative_test/changelogs/list/changelog.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
- this is invalid
- as changelog must be object (mapping)
- not an array (sequence)
34 changes: 34 additions & 0 deletions test/schemas/negative_test/changelogs/list/changelog.yml.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# ajv errors

```json
[
{
"instancePath": "",
"keyword": "type",
"message": "must be object",
"params": {
"type": "object"
},
"schemaPath": "#/type"
}
]
```

# check-jsonschema

stdout:

```json
{
"status": "fail",
"errors": [
{
"filename": "negative_test/changelogs/list/changelog.yml",
"path": "$",
"message": "['this is invalid', 'as changelog must be object (mapping)', 'not an array (sequence)'] is not of type 'object'",
"has_sub_errors": false
}
],
"parse_errors": []
}
```
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
releases: foo # <-- not a semver
34 changes: 34 additions & 0 deletions test/schemas/negative_test/changelogs/no-semver/changelog.yml.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# ajv errors

```json
[
{
"instancePath": "/releases",
"keyword": "type",
"message": "must be object",
"params": {
"type": "object"
},
"schemaPath": "#/properties/releases/type"
}
]
```

# check-jsonschema

stdout:

```json
{
"status": "fail",
"errors": [
{
"filename": "negative_test/changelogs/no-semver/changelog.yml",
"path": "$.releases",
"message": "'foo' is not of type 'object'",
"has_sub_errors": false
}
],
"parse_errors": []
}
```
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
release: {} # <- unknown key, correct would be releases
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# ajv errors

```json
[
{
"instancePath": "",
"keyword": "additionalProperties",
"message": "must NOT have additional properties",
"params": {
"additionalProperty": "release"
},
"schemaPath": "#/additionalProperties"
}
]
```

# check-jsonschema

stdout:

```json
{
"status": "fail",
"errors": [
{
"filename": "negative_test/changelogs/unknown-keys/changelog.yml",
"path": "$",
"message": "Additional properties are not allowed ('release' was unexpected)",
"has_sub_errors": false
}
],
"parse_errors": []
}
```
17 changes: 17 additions & 0 deletions test/schemas/test/changelog.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
ancestor: 0.5.4
releases:
1.0.0-alpha:
release_date: "2020-01-01"
codename: "The first public one"
changes:
release_summary: A bit o markdown text
bugfixes:
- Fixed bug `#1 <https://example.com>`
deprecated_features:
- Free form text mentioning a deprecation
minor_changes:
- Free form text mentioning a minor change
modules:
- description: foo
name: short_module_name
namespace: foo
3 changes: 3 additions & 0 deletions test/schemas/test/changelogs/minimal/changelog.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
---
# Example of minimal changelog.yml that is considered valid
releases: {}
22 changes: 22 additions & 0 deletions test/test_schemas.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
"""Test schemas modules."""
from time import sleep

import pytest

from ansiblelint.rules import RulesCollection
from ansiblelint.runner import Runner
from ansiblelint.schemas import refresh_schemas


Expand All @@ -16,3 +20,21 @@ def test_refresh_schemas() -> None:
sleep(1)
# should be cached now
assert refresh_schemas(min_age_seconds=10) == 0


@pytest.mark.parametrize(
("file", "expected_tags"),
(pytest.param("examples/changelog.yml", ["schema[changelog]"], id="changelog"),),
)
def test_schema(
default_rules_collection: RulesCollection,
file: str,
expected_tags: list[str],
) -> None:
"""Test that runner can go through any corner cases."""
runner = Runner(file, rules=default_rules_collection)
matches = runner.run()

assert len(matches) == len(expected_tags)
for i, match in enumerate(matches):
assert match.tag == expected_tags[i]

0 comments on commit c98d662

Please sign in to comment.