@7n/rules-ci-github 1.9.6 → 1.9.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/package.json +1 -1
- package/rules/ga/lint_ga/lint_ga.mdc +1 -0
- package/rules/ga/lint_ga/lint_ga.rego +12 -1
- package/rules/ga/lint_ga/template/lint-ga.yml.snippet.yml +3 -0
- package/rules/js/lint_js_yml/lint_js_yml.rego +17 -0
- package/rules/js/lint_js_yml/template/lint-js.yml.snippet.yml +11 -0
- package/rules/python/lint_python_yml/lint_python_yml.rego +17 -0
- package/rules/python/lint_python_yml/template/lint-python.yml.snippet.yml +5 -0
- package/rules/rust/lint_rust_yml/lint_rust_yml.rego +17 -0
- package/rules/rust/lint_rust_yml/template/lint-rust.yml.snippet.yml +6 -0
- package/rules/text/lint_text/lint_text.mdc +1 -1
- package/rules/text/lint_text/lint_text.rego +12 -3
- package/rules/text/lint_text/template/lint-text.yml.snippet.yml +22 -0
package/CHANGELOG.md
CHANGED
package/package.json
CHANGED
|
@@ -10,6 +10,7 @@ Rego-пакет: `ga.lint_ga`
|
|
|
10
10
|
- `on.push.branches` — superset: містить `dev` і `main`
|
|
11
11
|
- `on.pull_request.branches` — superset: містить `dev` і `main`
|
|
12
12
|
- `on.push.paths` — superset: містить `.github/actions/**` і `.github/workflows/**`
|
|
13
|
+
- `on.pull_request.paths` — superset: містить `.github/actions/**` і `.github/workflows/**`
|
|
13
14
|
- `jobs.lint-ga` — job має існувати
|
|
14
15
|
- `jobs.lint-ga.runs-on` — за template (`ubuntu-latest`)
|
|
15
16
|
- `jobs.lint-ga.permissions.contents` — `read`
|
|
@@ -8,7 +8,9 @@ import rego.v1
|
|
|
8
8
|
|
|
9
9
|
# ── Аліаси ─────────────────────────────────────────────────────────────────
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
# Conftest поточних версій читає YAML 1.2 (`on`), але старі версії віддавали
|
|
12
|
+
# YAML 1.1 boolean-key (`true`). Приймаємо обидві форми, щоб policy не мовчала.
|
|
13
|
+
gha_on := object.get(input, "on", object.get(input, "true", {}))
|
|
12
14
|
|
|
13
15
|
job := input.jobs["lint-ga"]
|
|
14
16
|
|
|
@@ -26,6 +28,10 @@ expected_pr_branches := {b | some b in data.template.snippet.on.pull_request.bra
|
|
|
26
28
|
|
|
27
29
|
expected_push_paths := {p | some p in data.template.snippet.on.push.paths}
|
|
28
30
|
|
|
31
|
+
expected_pr_paths := {p | some p in data.template.snippet.on.pull_request.paths}
|
|
32
|
+
|
|
33
|
+
actual_pr_paths := object.get(object.get(gha_on, "pull_request", {}), "paths", [])
|
|
34
|
+
|
|
29
35
|
expected_runs_on := data.template.snippet.jobs["lint-ga"]["runs-on"]
|
|
30
36
|
|
|
31
37
|
expected_perms := data.template.snippet.jobs["lint-ga"].permissions
|
|
@@ -66,6 +72,11 @@ deny contains msg if {
|
|
|
66
72
|
msg := "lint-ga.yml: on.push.paths має містити .github/actions/** і .github/workflows/** (ga.mdc)"
|
|
67
73
|
}
|
|
68
74
|
|
|
75
|
+
deny contains msg if {
|
|
76
|
+
not paths_superset_of(actual_pr_paths, expected_pr_paths)
|
|
77
|
+
msg := "lint-ga.yml: on.pull_request.paths має містити .github/actions/** і .github/workflows/** (ga.mdc)"
|
|
78
|
+
}
|
|
79
|
+
|
|
69
80
|
deny contains msg if {
|
|
70
81
|
not job
|
|
71
82
|
msg := "lint-ga.yml: jobs.lint-ga відсутній (ga.mdc)"
|
|
@@ -16,6 +16,14 @@ package js.lint_js_yml
|
|
|
16
16
|
|
|
17
17
|
import rego.v1
|
|
18
18
|
|
|
19
|
+
# Conftest поточних версій читає YAML 1.2 (`on`), але старі версії віддавали
|
|
20
|
+
# YAML 1.1 boolean-key (`true`). Приймаємо обидві форми, щоб policy не мовчала.
|
|
21
|
+
gha_on := object.get(input, "on", object.get(input, "true", {}))
|
|
22
|
+
|
|
23
|
+
expected_pr_paths := {p | some p in data.template.snippet.on.pull_request.paths}
|
|
24
|
+
|
|
25
|
+
actual_pr_paths := object.get(object.get(gha_on, "pull_request", {}), "paths", [])
|
|
26
|
+
|
|
19
27
|
# Required `uses:` зі template — фільтруємо тільки кроки з uses.
|
|
20
28
|
expected_uses_set contains u if {
|
|
21
29
|
some step in data.template.snippet.jobs.eslint.steps
|
|
@@ -58,6 +66,11 @@ deny contains msg if {
|
|
|
58
66
|
msg := sprintf("lint-js.yml: відсутній крок uses: %s (js.mdc)", [required_use])
|
|
59
67
|
}
|
|
60
68
|
|
|
69
|
+
deny contains msg if {
|
|
70
|
+
not paths_superset_of(actual_pr_paths, expected_pr_paths)
|
|
71
|
+
msg := "lint-js.yml: on.pull_request.paths має містити очікувані glob-и (js.mdc)"
|
|
72
|
+
}
|
|
73
|
+
|
|
61
74
|
# ── deny: required run substrings ───────────────────────────────────────
|
|
62
75
|
|
|
63
76
|
deny contains msg if {
|
|
@@ -110,6 +123,10 @@ has_use_satisfying(required) if {
|
|
|
110
123
|
uses_satisfies(u, required)
|
|
111
124
|
}
|
|
112
125
|
|
|
126
|
+
paths_superset_of(actual, expected) if {
|
|
127
|
+
expected & {p | some p in actual} == expected
|
|
128
|
+
}
|
|
129
|
+
|
|
113
130
|
step_run_text(step) := step.run if is_string(step.run)
|
|
114
131
|
|
|
115
132
|
else := concat("\n", [s | some s in step.run]) if is_array(step.run)
|
|
@@ -14,11 +14,22 @@ on:
|
|
|
14
14
|
- '**/*.tsx'
|
|
15
15
|
- '**/*.vue'
|
|
16
16
|
- '**/eslint.config.*'
|
|
17
|
+
- '**/.oxlintrc.json'
|
|
17
18
|
|
|
18
19
|
pull_request:
|
|
19
20
|
branches:
|
|
20
21
|
- dev
|
|
21
22
|
- main
|
|
23
|
+
paths:
|
|
24
|
+
- '**/*.js'
|
|
25
|
+
- '**/*.mjs'
|
|
26
|
+
- '**/*.cjs'
|
|
27
|
+
- '**/*.jsx'
|
|
28
|
+
- '**/*.ts'
|
|
29
|
+
- '**/*.tsx'
|
|
30
|
+
- '**/*.vue'
|
|
31
|
+
- '**/eslint.config.*'
|
|
32
|
+
- '**/.oxlintrc.json'
|
|
22
33
|
|
|
23
34
|
concurrency:
|
|
24
35
|
group: ${{ github.ref }}-${{ github.workflow }}
|
|
@@ -14,6 +14,14 @@ package python.lint_python_yml
|
|
|
14
14
|
|
|
15
15
|
import rego.v1
|
|
16
16
|
|
|
17
|
+
# Conftest поточних версій читає YAML 1.2 (`on`), але старі версії віддавали
|
|
18
|
+
# YAML 1.1 boolean-key (`true`). Приймаємо обидві форми, щоб policy не мовчала.
|
|
19
|
+
gha_on := object.get(input, "on", object.get(input, "true", {}))
|
|
20
|
+
|
|
21
|
+
expected_pr_paths := {p | some p in data.template.snippet.on.pull_request.paths}
|
|
22
|
+
|
|
23
|
+
actual_pr_paths := object.get(object.get(gha_on, "pull_request", {}), "paths", [])
|
|
24
|
+
|
|
17
25
|
# Усі `uses` з канону workflow (по всіх job'ах template).
|
|
18
26
|
expected_uses contains u if {
|
|
19
27
|
some job in data.template.snippet.jobs
|
|
@@ -43,6 +51,11 @@ deny contains msg if {
|
|
|
43
51
|
msg := sprintf("lint-python.yml: відсутній step з `uses: %s` (python.mdc)", [required_use])
|
|
44
52
|
}
|
|
45
53
|
|
|
54
|
+
deny contains msg if {
|
|
55
|
+
not paths_superset_of(actual_pr_paths, expected_pr_paths)
|
|
56
|
+
msg := "lint-python.yml: on.pull_request.paths має містити очікувані glob-и (python.mdc)"
|
|
57
|
+
}
|
|
58
|
+
|
|
46
59
|
deny contains msg if {
|
|
47
60
|
msg := "lint-python.yml: actions/checkout@v6 потребує `with: persist-credentials: false` (python.mdc)"
|
|
48
61
|
some job in object.get(input, "jobs", {})
|
|
@@ -66,3 +79,7 @@ step_run_to_text(step) := step.run if is_string(step.run)
|
|
|
66
79
|
else := concat("\n", [s | some s in step.run]) if is_array(step.run)
|
|
67
80
|
|
|
68
81
|
else := ""
|
|
82
|
+
|
|
83
|
+
paths_superset_of(actual, expected) if {
|
|
84
|
+
expected & {p | some p in actual} == expected
|
|
85
|
+
}
|
|
@@ -12,6 +12,14 @@ package rust.lint_rust_yml
|
|
|
12
12
|
|
|
13
13
|
import rego.v1
|
|
14
14
|
|
|
15
|
+
# Conftest поточних версій читає YAML 1.2 (`on`), але старі версії віддавали
|
|
16
|
+
# YAML 1.1 boolean-key (`true`). Приймаємо обидві форми, щоб policy не мовчала.
|
|
17
|
+
gha_on := object.get(input, "on", object.get(input, "true", {}))
|
|
18
|
+
|
|
19
|
+
expected_pr_paths := {p | some p in data.template.snippet.on.pull_request.paths}
|
|
20
|
+
|
|
21
|
+
actual_pr_paths := object.get(object.get(gha_on, "pull_request", {}), "paths", [])
|
|
22
|
+
|
|
15
23
|
# Усі `uses` з канону workflow.
|
|
16
24
|
expected_uses contains u if {
|
|
17
25
|
some step in data.template.snippet.jobs.lint.steps
|
|
@@ -46,6 +54,11 @@ deny contains msg if {
|
|
|
46
54
|
msg := sprintf("lint-rust.yml: відсутній step з `uses: %s` (rust.mdc)", [required_use])
|
|
47
55
|
}
|
|
48
56
|
|
|
57
|
+
deny contains msg if {
|
|
58
|
+
not paths_superset_of(actual_pr_paths, expected_pr_paths)
|
|
59
|
+
msg := "lint-rust.yml: on.pull_request.paths має містити очікувані glob-и (rust.mdc)"
|
|
60
|
+
}
|
|
61
|
+
|
|
49
62
|
deny contains msg if {
|
|
50
63
|
some step in data.template.snippet.jobs.lint.steps
|
|
51
64
|
expected_run := object.get(step, "run", "")
|
|
@@ -77,3 +90,7 @@ step_run_to_text(step) := step.run if is_string(step.run)
|
|
|
77
90
|
else := concat("\n", [s | some s in step.run]) if is_array(step.run)
|
|
78
91
|
|
|
79
92
|
else := ""
|
|
93
|
+
|
|
94
|
+
paths_superset_of(actual, expected) if {
|
|
95
|
+
expected & {p | some p in actual} == expected
|
|
96
|
+
}
|
|
@@ -8,7 +8,7 @@ Rego-пакет: `text.lint_text`
|
|
|
8
8
|
|
|
9
9
|
- `name` — має бути `"Lint Text"`
|
|
10
10
|
- `on.push.branches` та `on.pull_request.branches` — мають містити `dev` і `main`
|
|
11
|
-
- `on.push.paths` —
|
|
11
|
+
- `on.push.paths` та `on.pull_request.paths` — мають бути надмножиною канонічних glob-ів (усі текстові розширення)
|
|
12
12
|
- `jobs.text` — job обов'язковий
|
|
13
13
|
- `jobs.text.runs-on` — має бути `ubuntu-latest`
|
|
14
14
|
- `jobs.text.permissions.contents` — має бути `read`
|
|
@@ -15,13 +15,17 @@ expected_pr_branches := {b | some b in data.template.snippet.on.pull_request.bra
|
|
|
15
15
|
|
|
16
16
|
expected_push_paths := {p | some p in data.template.snippet.on.push.paths}
|
|
17
17
|
|
|
18
|
+
expected_pr_paths := {p | some p in data.template.snippet.on.pull_request.paths}
|
|
19
|
+
|
|
20
|
+
actual_pr_paths := object.get(object.get(gha_on, "pull_request", {}), "paths", [])
|
|
21
|
+
|
|
18
22
|
expected_runs_on := data.template.snippet.jobs.text["runs-on"]
|
|
19
23
|
|
|
20
24
|
expected_perms := data.template.snippet.jobs.text.permissions
|
|
21
25
|
|
|
22
|
-
#
|
|
23
|
-
#
|
|
24
|
-
gha_on := input
|
|
26
|
+
# Conftest поточних версій читає YAML 1.2 (`on`), але старі версії віддавали
|
|
27
|
+
# YAML 1.1 boolean-key (`true`). Приймаємо обидві форми, щоб policy не мовчала.
|
|
28
|
+
gha_on := object.get(input, "on", object.get(input, "true", {}))
|
|
25
29
|
|
|
26
30
|
job := input.jobs.text
|
|
27
31
|
|
|
@@ -63,6 +67,11 @@ deny contains msg if {
|
|
|
63
67
|
msg := "lint-text.yml: on.push.paths має містити очікувані glob-и (text.mdc)"
|
|
64
68
|
}
|
|
65
69
|
|
|
70
|
+
deny contains msg if {
|
|
71
|
+
not paths_superset_of(actual_pr_paths, expected_pr_paths)
|
|
72
|
+
msg := "lint-text.yml: on.pull_request.paths має містити очікувані glob-и (text.mdc)"
|
|
73
|
+
}
|
|
74
|
+
|
|
66
75
|
deny contains msg if {
|
|
67
76
|
not job
|
|
68
77
|
msg := "lint-text.yml: jobs.text відсутній (text.mdc)"
|
|
@@ -32,6 +32,28 @@ on:
|
|
|
32
32
|
branches:
|
|
33
33
|
- dev
|
|
34
34
|
- main
|
|
35
|
+
paths:
|
|
36
|
+
- '**/*.js'
|
|
37
|
+
- '**/*.ts'
|
|
38
|
+
- '**/*.vue'
|
|
39
|
+
- '**/*.html'
|
|
40
|
+
- '**/*.css'
|
|
41
|
+
- '**/*.scss'
|
|
42
|
+
- '**/*.less'
|
|
43
|
+
- '**/*.json'
|
|
44
|
+
- '**/*.jsonc'
|
|
45
|
+
- '**/*.yaml'
|
|
46
|
+
- '**/*.yml'
|
|
47
|
+
- '**/*.toml'
|
|
48
|
+
- '**/*.xml'
|
|
49
|
+
- '**/*.md'
|
|
50
|
+
- '**/*.mdc'
|
|
51
|
+
- '**/*.mdс'
|
|
52
|
+
- '**/*.txt'
|
|
53
|
+
- '**/*.go'
|
|
54
|
+
- '**/*.py'
|
|
55
|
+
- '**/*.php'
|
|
56
|
+
- '**/*.sh'
|
|
35
57
|
|
|
36
58
|
concurrency:
|
|
37
59
|
group: ${{ github.ref }}-${{ github.workflow }}
|