Skip to content

Commit

Permalink
Rule: annotation-without-metadata (#882)
Browse files Browse the repository at this point in the history
Fixes #874

Signed-off-by: Anders Eknert <[email protected]>
  • Loading branch information
anderseknert authored Jul 2, 2024
1 parent 8110bc5 commit 6153d57
Show file tree
Hide file tree
Showing 7 changed files with 146 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ The following rules are currently available:

| Category | Title | Description |
|-------------|-------------------------------------------------------------------------------------------------------|-----------------------------------------------------------|
| bugs | [annotation-without-metadata](https://docs.styra.com/regal/rules/bugs/annotation-without-metadata) | Annotation without metadata |
| bugs | [argument-always-wildcard](https://docs.styra.com/regal/rules/bugs/argument-always-wildcard) | Argument is always a wildcard |
| bugs | [constant-condition](https://docs.styra.com/regal/rules/bugs/constant-condition) | Constant condition |
| bugs | [deprecated-builtin](https://docs.styra.com/regal/rules/bugs/deprecated-builtin) | Avoid using deprecated built-in functions |
Expand Down
5 changes: 5 additions & 0 deletions bundle/regal/ast/comments.rego
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ comments["metadata_attributes"] := {
"custom",
}

comments["annotation_match"](str) if regex.match(
`^(scope|title|description|related_resources|authors|organizations|schemas|entrypoint|custom)\s*:`,
str,
)

# METADATA
# description: |
# map of all ignore directive comments, like ("# regal ignore:line-length")
Expand Down
2 changes: 2 additions & 0 deletions bundle/regal/config/provided/data.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ features:
check-version: true
rules:
bugs:
annotation-without-metadata:
level: error
argument-always-wildcard:
level: error
constant-condition:
Expand Down
17 changes: 17 additions & 0 deletions bundle/regal/rules/bugs/annotation_without_metadata.rego
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# METADATA
# description: Annotation without metadata
package regal.rules.bugs["annotation-without-metadata"]

import rego.v1

import data.regal.ast
import data.regal.result

report contains violation if {
some block in ast.comments.blocks

block[0].Location.col == 1
ast.comments.annotation_match(trim_space(block[0].Text))

violation := result.fail(rego.metadata.chain(), result.location(block[0]))
}
60 changes: 60 additions & 0 deletions bundle/regal/rules/bugs/annotation_without_metadata_test.rego
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package regal.rules.bugs["annotation-without-metadata_test"]

import rego.v1

import data.regal.ast
import data.regal.config

import data.regal.rules.bugs["annotation-without-metadata"] as rule

test_fail_annotation_without_metadata if {
module := ast.with_rego_v1(`
# title: allow
allow := false
`)

r := rule.report with input as module
r == {{
"category": "bugs",
"description": "Annotation without metadata",
"level": "error",
"location": {"col": 1, "file": "policy.rego", "row": 6, "text": "# title: allow"},
"related_resources": [{
"description": "documentation",
"ref": config.docs.resolve_url("$baseUrl/$category/annotation-without-metadata", "bugs"),
}],
"title": "annotation-without-metadata",
}}
}

test_success_annotation_with_metadata if {
module := ast.with_rego_v1(`
# METADATA
# title: allow
allow := false
`)

r := rule.report with input as module
r == set()
}

test_success_annotation_but_no_metadata_location if {
module := ast.with_rego_v1(`
allow := false # title: allow
`)

r := rule.report with input as module
r == set()
}

test_success_annotation_without_metadata_but_comment_preceeding if {
module := ast.with_rego_v1(`
# something that is not an annotation here will cancel this rule
# as this is less likely to be a mistake... but weird
# title: allow
allow := false
`)

r := rule.report with input as module
r == set()
}
58 changes: 58 additions & 0 deletions docs/rules/bugs/annotation-without-metadata.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# annotation-without-metadata

**Summary**: Annotation without metadata

**Category**: Bugs

**Avoid**
```rego
package policy
import rego.v1
# description: allow allows
allow if {
# ... some conditions
}
```

**Prefer**
```rego
package policy
import rego.v1
# METADATA
# description: allow allows
allow if {
# ... some conditions
}
```

## Rationale

A comment that starts with `<annotation-attribute>:` but is not part of a metadata block is likely a mistake. Add
`# METADATA` above the line to turn it into a
[metadata](https://www.openpolicyagent.org/docs/latest/policy-language/#annotations) block.

## Configuration Options

This linter rule provides the following configuration options:

```yaml
rules:
bugs:
annotation-without-metadata:
# one of "error", "warning", "ignore"
level: error
```
## Related Resources
- OPA Docs: [Annotations](https://www.openpolicyagent.org/docs/latest/policy-language/#annotations)
## Community
If you think you've found a problem with this rule or its documentation, would like to suggest improvements, new rules,
or just talk about Regal in general, please join us in the `#regal` channel in the Styra Community
[Slack](https://communityinviter.com/apps/styracommunity/signup)!
3 changes: 3 additions & 0 deletions e2e/testdata/violations/most_violations.rego
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,9 @@ argument_always_wildcard(_) if true

argument_always_wildcard(_) if true

# title: annotation without metadata
some_rule := true

### Idiomatic ###

custom_has_key_construct(map, key) if {
Expand Down

0 comments on commit 6153d57

Please sign in to comment.