@7n/rules-ci-github 1.2.2 → 1.3.0
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
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@7n/rules-ci-github",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "\u041f\u043b\u0430\u0433\u0456\u043d @7n/rules: \u043a\u0430\u043d\u043e\u043d GitHub Actions (.github/workflows) \u2014 \u043e\u0431\u043e\u0432'\u044f\u0437\u043a\u043e\u0432\u0456 workflow, zizmor, VS Code",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"github-actions",
|
|
@@ -6,7 +6,10 @@ Rego-пакет: `ga.workflow_common`
|
|
|
6
6
|
|
|
7
7
|
### Що перевіряється
|
|
8
8
|
|
|
9
|
-
- **concurrency** — обов'язкова наявність блоку;
|
|
9
|
+
- **concurrency** — обов'язкова наявність блоку; два допустимі режими:
|
|
10
|
+
- канонічний CI: `group` = `${{ github.ref }}-${{ github.workflow }}` + `cancel-in-progress: true`
|
|
11
|
+
- release-серіалізація: статичний `group` (без `${{ }}`-виразів, глобальний lock) + `cancel-in-progress: false` — для workflow, що піднімають версію/тег/CHANGELOG і не можуть бути скасовані на півдорозі; відсутній `cancel-in-progress` = `false` (семантика GitHub)
|
|
12
|
+
- змішані комбінації (статичний `group` + `true`, per-ref `group` + `false`) — заборонені
|
|
10
13
|
- **Заборонені кроки** — `oven-sh/setup-bun`, `actions/cache`, `bun install` у будь-якому `uses:`/`run:` (мають бути інкапсульовані у composite `setup-bun-deps`)
|
|
11
14
|
- **Порядок кроків** — якщо є `setup-bun-deps`, перед ним обов'язковий `actions/checkout@`
|
|
12
15
|
- **Shell-продовження** — `\` перед переносом рядка у `run:` заборонено; треба `run: >-`
|
|
@@ -18,6 +18,10 @@ import rego.v1
|
|
|
18
18
|
|
|
19
19
|
expected_concurrency_group := concat("", ["$", "{{ github.ref }}-$", "{{ github.workflow }}"])
|
|
20
20
|
|
|
21
|
+
# Маркер GitHub-виразу `${{` — через concat (та сама причина, що й у
|
|
22
|
+
# expected_concurrency_group): без сирого літерала в rego-джерелі.
|
|
23
|
+
gh_expr_marker := concat("", ["$", "{{"])
|
|
24
|
+
|
|
21
25
|
# Локальні composite setup-bun-deps (ga.mdc) — два варіанти шляху:
|
|
22
26
|
# `.github/actions/...` (cursor-репо) і `npm/github-actions/...` (npm-пакет dev-локально).
|
|
23
27
|
local_setup_bun_markers := {
|
|
@@ -45,6 +49,16 @@ concurrency_missing_template := concat(" ", [
|
|
|
45
49
|
"додай concurrency.group: %s і cancel-in-progress: true (ga.mdc)",
|
|
46
50
|
])
|
|
47
51
|
|
|
52
|
+
concurrency_group_template := concat(" ", [
|
|
53
|
+
"concurrency.group має бути %s,",
|
|
54
|
+
"або статичний рядок-lock для release-серіалізації (ga.mdc)",
|
|
55
|
+
])
|
|
56
|
+
|
|
57
|
+
concurrency_release_cancel_template := concat(" ", [
|
|
58
|
+
"статичний concurrency.group — release-серіалізація: скасування на півдорозі",
|
|
59
|
+
"лишає репо в неконсистентному стані, тому cancel-in-progress: false (ga.mdc)",
|
|
60
|
+
])
|
|
61
|
+
|
|
48
62
|
shell_continuation_template := concat(" ", [
|
|
49
63
|
"jobs.%s.steps[%d]: у run заборонено продовження рядків через зворотний сліш;",
|
|
50
64
|
"оформи як folded block (run: >-) (ga.mdc)",
|
|
@@ -147,6 +161,14 @@ deny contains msg if {
|
|
|
147
161
|
# Дублює окремі per-workflow перевірки для clean-ga-workflows / clean-merged-branch /
|
|
148
162
|
# lint-ga / git-ai, але вкриває й решту workflow-файлів (apply-k8s, lint-js, …),
|
|
149
163
|
# для яких поки немає виділеної polysi.
|
|
164
|
+
#
|
|
165
|
+
# Допустимі рівно два когерентні режими:
|
|
166
|
+
# 1. канонічний CI: per-ref group + cancel-in-progress: true;
|
|
167
|
+
# 2. release-серіалізація: статичний group (глобальний lock, без `${{ }}`-виразів)
|
|
168
|
+
# + cancel-in-progress: false — для workflow, що піднімають версію/тег і не
|
|
169
|
+
# можуть бути скасовані на півдорозі (per-ref lock не захищає від двох
|
|
170
|
+
# одночасних push-подій, які обидві піднімають версію).
|
|
171
|
+
# Змішані комбінації (статичний group + true, per-ref + false) — заборонені.
|
|
150
172
|
|
|
151
173
|
deny contains msg if {
|
|
152
174
|
# `object.get(…, default)` повертає `false` коли ключа немає — інакше `not is_object(…)`
|
|
@@ -157,16 +179,25 @@ deny contains msg if {
|
|
|
157
179
|
|
|
158
180
|
deny contains msg if {
|
|
159
181
|
is_object(object.get(input, "concurrency", false))
|
|
160
|
-
input.concurrency
|
|
161
|
-
|
|
182
|
+
group := object.get(input.concurrency, "group", "")
|
|
183
|
+
group != expected_concurrency_group
|
|
184
|
+
not is_release_lock_group(group)
|
|
185
|
+
msg := sprintf(concurrency_group_template, [expected_concurrency_group])
|
|
162
186
|
}
|
|
163
187
|
|
|
164
188
|
deny contains msg if {
|
|
165
189
|
is_object(object.get(input, "concurrency", false))
|
|
166
|
-
input.concurrency
|
|
190
|
+
input.concurrency.group == expected_concurrency_group
|
|
191
|
+
object.get(input.concurrency, "cancel-in-progress", false) != true
|
|
167
192
|
msg := "concurrency.cancel-in-progress має бути true (ga.mdc)"
|
|
168
193
|
}
|
|
169
194
|
|
|
195
|
+
deny contains concurrency_release_cancel_template if {
|
|
196
|
+
is_object(object.get(input, "concurrency", false))
|
|
197
|
+
is_release_lock_group(object.get(input.concurrency, "group", ""))
|
|
198
|
+
object.get(input.concurrency, "cancel-in-progress", false) != false
|
|
199
|
+
}
|
|
200
|
+
|
|
170
201
|
# ── deny: мінімальні версії marketplace actions у `uses:` ─────────────────
|
|
171
202
|
#
|
|
172
203
|
# Канон — `template/uses-min-versions.snippet.json` (через --data).
|
|
@@ -191,6 +222,14 @@ deny contains msg if {
|
|
|
191
222
|
|
|
192
223
|
# ── helpers ────────────────────────────────────────────────────────────────
|
|
193
224
|
|
|
225
|
+
# Статичний непорожній group без `${{ }}`-виразів — глобальний lock
|
|
226
|
+
# (режим release-серіалізації concurrency).
|
|
227
|
+
is_release_lock_group(group) if {
|
|
228
|
+
is_string(group)
|
|
229
|
+
group != ""
|
|
230
|
+
not contains(group, gh_expr_marker)
|
|
231
|
+
}
|
|
232
|
+
|
|
194
233
|
# Об'єднаний рядок `uses` + `run` для одного кроку — для substring-пошуку
|
|
195
234
|
# заборонених патернів. `run` може бути рядком або масивом рядків (YAML).
|
|
196
235
|
step_uses_or_run_blob(step) := blob if {
|