@7n/rules-ci-github 2.3.0 → 2.3.2

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 CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## [2.3.2] - 2026-08-25
4
+
5
+ ### Fixed
6
+
7
+ - ga-політики стали незалежними від версії YAML-парсера: читання події workflow-а тепер object.get(input, "on", object.get(input, "true", {})) у всіх пʼятьох пакетах (було лише в lint_ga). Під conftest вивід не змінився; без цього будь-який YAML-1.2-парсер зробив би три пакети тихо непрацездатними. sprintf %q замінено на \"%v\" — байт-у-байт той самий текст
8
+
9
+ ## [2.3.1] - 2026-08-19
10
+
11
+ ### Changed
12
+
13
+ - дозволено preinstalled ci-tools у lint-ga policy
14
+
3
15
  ## [2.3.0] - 2026-08-01
4
16
 
5
17
  ### Added
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@7n/rules-ci-github",
3
- "version": "2.3.0",
3
+ "version": "2.3.2",
4
4
  "description": "Плагін @7n/rules: канон GitHub Actions (.github/workflows) — обов'язкові workflow, zizmor, VS Code",
5
5
  "keywords": [
6
6
  "github-actions",
@@ -9,10 +9,12 @@ package ga.clean_ga_workflows
9
9
  import rego.v1
10
10
 
11
11
  # ── Аліаси на input ────────────────────────────────────────────────────────
12
- # GHA YAML quirk: ключ `on:` YAML 1.1 boolean `true`, у conftest серіалізується
13
- # як рядковий ключ "true". Template (через --data JSON) має ключ "on".
14
-
15
- gha_on := input["true"]
12
+ # Читання події workflow-а НЕ залежить від версії YAML-парсера. `on:` у YAML 1.1
13
+ # булеве `true` (conftest серіалізує його рядковим ключем "true"), у YAML 1.2 —
14
+ # звичайний рядок "on". Обидві форми читаються тут; без цього зміна парсера
15
+ # зробила б УСІ правила цього пакета тихо непрацездатними — не падінням, а
16
+ # порожнім результатом назавжди. Template (через --data JSON) має ключ "on".
17
+ gha_on := object.get(input, "on", object.get(input, "true", {}))
16
18
 
17
19
  step0 := input.jobs.cleanup_old_workflows.steps[0]
18
20
 
@@ -31,7 +33,7 @@ expected_runs_on := data.template.snippet.jobs.cleanup_old_workflows["runs-on"]
31
33
 
32
34
  deny contains msg if {
33
35
  input.name != expected_name
34
- msg := sprintf("clean-ga-workflows.yml: name має бути %q (ga.mdc)", [expected_name])
36
+ msg := sprintf("clean-ga-workflows.yml: name має бути \"%v\" (ga.mdc)", [expected_name])
35
37
  }
36
38
 
37
39
  deny contains msg if {
@@ -7,8 +7,12 @@ package ga.clean_merged_branch
7
7
  import rego.v1
8
8
 
9
9
  # ── Аліаси ─────────────────────────────────────────────────────────────────
10
-
11
- gha_on := input["true"]
10
+ # Читання події workflow-а НЕ залежить від версії YAML-парсера. `on:` у YAML 1.1
11
+ # булеве `true` (conftest серіалізує його рядковим ключем "true"), у YAML 1.2 —
12
+ # звичайний рядок "on". Обидві форми читаються тут; без цього зміна парсера
13
+ # зробила б УСІ правила цього пакета тихо непрацездатними — не падінням, а
14
+ # порожнім результатом назавжди. Template (через --data JSON) має ключ "on".
15
+ gha_on := object.get(input, "on", object.get(input, "true", {}))
12
16
 
13
17
  steps := input.jobs.cleanup_old_branches.steps
14
18
 
@@ -30,7 +34,7 @@ expected_perms := data.template.snippet.jobs.cleanup_old_branches.permissions
30
34
 
31
35
  deny contains msg if {
32
36
  input.name != expected_name
33
- msg := sprintf("clean-merged-branch.yml: name має бути %q (ga.mdc)", [expected_name])
37
+ msg := sprintf("clean-merged-branch.yml: name має бути \"%v\" (ga.mdc)", [expected_name])
34
38
  }
35
39
 
36
40
  deny contains msg if {
@@ -9,8 +9,12 @@ package ga.git_ai
9
9
  import rego.v1
10
10
 
11
11
  # ── Аліаси ─────────────────────────────────────────────────────────────────
12
-
13
- gha_on := input["true"]
12
+ # Читання події workflow-а НЕ залежить від версії YAML-парсера. `on:` у YAML 1.1
13
+ # булеве `true` (conftest серіалізує його рядковим ключем "true"), у YAML 1.2 —
14
+ # звичайний рядок "on". Обидві форми читаються тут; без цього зміна парсера
15
+ # зробила б УСІ правила цього пакета тихо непрацездатними — не падінням, а
16
+ # порожнім результатом назавжди. Template (через --data JSON) має ключ "on".
17
+ gha_on := object.get(input, "on", object.get(input, "true", {}))
14
18
 
15
19
  job := input.jobs["git-ai"]
16
20
 
@@ -36,7 +40,7 @@ run_substring := "git-ai ci github run"
36
40
 
37
41
  deny contains msg if {
38
42
  input.name != expected_name
39
- msg := sprintf("git-ai.yml: name має бути %q (ga.mdc)", [expected_name])
43
+ msg := sprintf("git-ai.yml: name має бути \"%v\" (ga.mdc)", [expected_name])
40
44
  }
41
45
 
42
46
  deny contains msg if {
@@ -19,4 +19,12 @@ Rego-пакет: `ga.lint_ga`
19
19
  - `steps[*].run` (сукупно) — містить `open-policy-agent/conftest` (Install conftest)
20
20
  - `steps[*].run` (сукупно) — містить `n-rules lint ga --no-fix`
21
21
 
22
+ ### Preinstalled `ci-tools`
23
+
24
+ Forgejo runner може мапити сумісну мітку `ubuntu-latest` на власний образ, де вже
25
+ встановлені `uv` і `conftest`. Для цього workflow декларативно встановлює
26
+ `jobs.lint-ga.env.NITRA_CI_TOOLS: 'true'`. За цієї явної opt-in policy не вимагає
27
+ `astral-sh/setup-uv` і крок завантаження Conftest; `checkout`, локальний
28
+ `setup-bun-deps` і `n-rules lint ga --no-fix` лишаються обов'язковими.
29
+
22
30
  Канон: [lint-ga.yml.snippet.yml](./template/lint-ga.yml.snippet.yml)
@@ -43,6 +43,24 @@ expected_uses_set contains u if {
43
43
  u != ""
44
44
  }
45
45
 
46
+ # Opt-in для runner-образу, у якому вже є uv та conftest. Мітка runner
47
+ # залишається `ubuntu-latest` для сумісності, але workflow явно декларує
48
+ # джерело tooling, щоб policy не приховувала залежність від custom image.
49
+ preinstalled_ci_tools if object.get(object.get(job, "env", {}), "NITRA_CI_TOOLS", false) == true
50
+
51
+ preinstalled_ci_tools if object.get(object.get(job, "env", {}), "NITRA_CI_TOOLS", "false") == "true"
52
+
53
+ required_uses_set contains u if {
54
+ not preinstalled_ci_tools
55
+ some u in expected_uses_set
56
+ }
57
+
58
+ required_uses_set contains u if {
59
+ preinstalled_ci_tools
60
+ some u in expected_uses_set
61
+ not startswith(u, "astral-sh/setup-uv@")
62
+ }
63
+
46
64
  # Required `run:` substrings — collected from steps with `run`.
47
65
  expected_run_blob := concat("\n", [r |
48
66
  some step in data.template.snippet.jobs["lint-ga"].steps
@@ -54,7 +72,7 @@ expected_run_blob := concat("\n", [r |
54
72
 
55
73
  deny contains msg if {
56
74
  input.name != expected_name
57
- msg := sprintf("lint-ga.yml: name має бути %q (ga.mdc)", [expected_name])
75
+ msg := sprintf("lint-ga.yml: name має бути \"%v\" (ga.mdc)", [expected_name])
58
76
  }
59
77
 
60
78
  deny contains msg if {
@@ -98,12 +116,13 @@ deny contains msg if {
98
116
  }
99
117
 
100
118
  deny contains msg if {
101
- some required_use in expected_uses_set
119
+ some required_use in required_uses_set
102
120
  not job_has_use_satisfying(required_use)
103
121
  msg := sprintf("lint-ga.yml: має бути uses: %s (ga.mdc)", [required_use])
104
122
  }
105
123
 
106
124
  deny contains msg if {
125
+ not preinstalled_ci_tools
107
126
  expected_run_blob != ""
108
127
  not contains(job_run_blob, "open-policy-agent/conftest")
109
128
  msg := "lint-ga.yml: має бути крок Install conftest (ga.mdc)"
@@ -70,7 +70,7 @@ setup_bun_no_checkout_template := concat(" ", [
70
70
  ])
71
71
 
72
72
  min_uses_version_template := concat(" ", [
73
- "jobs.%s.steps[%d]: %s має бути >= v%s (зараз %q) —",
73
+ "jobs.%s.steps[%d]: %s має бути >= v%s (зараз \"%v\") —",
74
74
  "онови ref у uses: (ga.mdc)",
75
75
  ])
76
76