@7n/rules-ci-github 2.4.5 → 2.4.6

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,11 @@
1
1
  # Changelog
2
2
 
3
+ ## [2.4.6] - 2026-08-29
4
+
5
+ ### Fixed
6
+
7
+ - `ga/lint_ga`: `.github/workflows/lint-ga.yml` із джобою, названою НЕ `lint-ga`, більше не дає у wasm-порті (`crates/plugin-ci-github`) одну діагностику `rego-engine-error` замість набору deny. Причина — дві розбіжності `regorus` vs OPA на UNDEFINED-значеннях: shorthand-голова `job_uses_set contains job.steps[_].uses` (і та сама форма в `job_run_blob`) на undefined корені `jobs["lint-ga"]` кидала помилку `eval` замість того щоб дати undefined — переписано в longhand; а `not helper(gha_on.push.branches, …)` з undefined-аргументом у `regorus` давало `not undefined == true` (три зайві deny, коли гілки `on:` немає) — тепер значення звʼязується окремим позитивним виразом. Канон `conftest` НЕ змінився: вихід порту звірено з живим `conftest test` на 11 фікстурах біт-у-біт, набір deny пінить `lint_ga_test.rego` (`test_deny_missing_job`, `test_missing_on_hook_denies_only_pr_paths`) (§2.81)
8
+
3
9
  ## [2.4.5] - 2026-08-29
4
10
 
5
11
  ### Changed
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@7n/rules-ci-github",
3
- "version": "2.4.5",
3
+ "version": "2.4.6",
4
4
  "description": "Плагін @7n/rules: канон GitHub Actions (.github/workflows) — обов'язкові workflow, zizmor, VS Code",
5
5
  "keywords": [
6
6
  "github-actions",
@@ -14,10 +14,20 @@ gha_on := object.get(input, "on", object.get(input, "true", {}))
14
14
 
15
15
  job := input.jobs["lint-ga"]
16
16
 
17
- job_uses_set contains job.steps[_].uses
18
-
19
- job_run_blob := concat("\n", [run |
20
- run := job.steps[_].run
17
+ # LONGHAND-форма (`some step in job.steps`), а НЕ shorthand
18
+ # `job_uses_set contains job.steps[_].uses` / `run := job.steps[_].run`:
19
+ # під regorus (wasm-порт `crates/plugin-ci-github`) shorthand кидає помилку
20
+ # eval («item cannot be indexed»), коли `job` undefined — тобто саме тоді,
21
+ # коли `jobs["lint-ga"]` відсутній, — замість того щоб дати undefined і
22
+ # пропустити керування канонічній deny «jobs.lint-ga відсутній».
23
+ # Longhand під regorus дає ТУ САМУ семантику, що й OPA/conftest.
24
+ job_uses_set contains u if {
25
+ some step in job.steps
26
+ u := step.uses
27
+ }
28
+
29
+ job_run_blob := concat("\n", [step.run |
30
+ some step in job.steps
21
31
  ])
22
32
 
23
33
  expected_name := data.template.snippet.name
@@ -46,9 +56,9 @@ expected_uses_set contains u if {
46
56
  # Opt-in для runner-образу, у якому вже є uv та conftest. Мітка runner
47
57
  # залишається `ubuntu-latest` для сумісності, але workflow явно декларує
48
58
  # джерело tooling, щоб policy не приховувала залежність від custom image.
49
- preinstalled_ci_tools if object.get(object.get(job, "env", {}), "NITRA_CI_TOOLS", false) == true
59
+ preinstalled_ci_tools if job.env.NITRA_CI_TOOLS == true
50
60
 
51
- preinstalled_ci_tools if object.get(object.get(job, "env", {}), "NITRA_CI_TOOLS", "false") == "true"
61
+ preinstalled_ci_tools if job.env.NITRA_CI_TOOLS == "true"
52
62
 
53
63
  required_uses_set contains u if {
54
64
  not preinstalled_ci_tools
@@ -70,23 +80,35 @@ expected_run_blob := concat("\n", [r |
70
80
 
71
81
  # ── deny rules ─────────────────────────────────────────────────────────────
72
82
 
83
+ # Три deny нижче спершу ЗВʼЯЗУЮТЬ `actual := gha_on.<hook>.<key>` окремим
84
+ # позитивним виразом, а вже потім негують helper. Це не косметика: у формі
85
+ # `not helper(gha_on.push.branches, …)` undefined-аргумент (гілки `on:` немає)
86
+ # в OPA робить УВЕСЬ вираз undefined (deny мовчить), а в regorus дає
87
+ # `not undefined` == true (deny спрацьовує) — розбіжність порту. Позитивне
88
+ # звʼязування падає однаково в обох двигунах, тож канон і порт збігаються.
89
+ # (`actual_pr_paths` навмисно інший: `object.get(…, [])` — там канон САМЕ
90
+ # СИГНАЛИТЬ про відсутній ключ.)
91
+
73
92
  deny contains msg if {
74
93
  input.name != expected_name
75
94
  msg := sprintf("lint-ga.yml: name має бути \"%v\" (ga.mdc)", [expected_name])
76
95
  }
77
96
 
78
97
  deny contains msg if {
79
- not branches_superset_of(gha_on.push.branches, expected_push_branches)
98
+ actual := gha_on.push.branches
99
+ not branches_superset_of(actual, expected_push_branches)
80
100
  msg := "lint-ga.yml: on.push.branches має містити dev і main (ga.mdc)"
81
101
  }
82
102
 
83
103
  deny contains msg if {
84
- not branches_superset_of(gha_on.pull_request.branches, expected_pr_branches)
104
+ actual := gha_on.pull_request.branches
105
+ not branches_superset_of(actual, expected_pr_branches)
85
106
  msg := "lint-ga.yml: on.pull_request.branches має містити dev і main (ga.mdc)"
86
107
  }
87
108
 
88
109
  deny contains msg if {
89
- not paths_superset_of(gha_on.push.paths, expected_push_paths)
110
+ actual := gha_on.push.paths
111
+ not paths_superset_of(actual, expected_push_paths)
90
112
  msg := "lint-ga.yml: on.push.paths має містити .github/actions/** і .github/workflows/** (ga.mdc)"
91
113
  }
92
114