@7n/rules-ci-github 2.0.2 → 2.2.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 +15 -0
- package/package.json +1 -1
- package/rules/style/lint_style_yml/template/lint-style.yml.snippet.yml +0 -2
- package/rules/text/lint_text/template/lint-text.yml.snippet.yml +0 -8
- package/rules/js/lint_js_yml/concern.json +0 -11
- package/rules/js/lint_js_yml/docs/fix-lint_js_yml.md +0 -35
- package/rules/js/lint_js_yml/docs/index.md +0 -9
- package/rules/js/lint_js_yml/fix-lint_js_yml.mjs +0 -15
- package/rules/js/lint_js_yml/lint_js_yml.mdc +0 -14
- package/rules/js/lint_js_yml/lint_js_yml.rego +0 -134
- package/rules/js/lint_js_yml/template/lint-js.yml.snippet.yml +0 -51
- package/rules/python/lint_python_yml/concern.json +0 -11
- package/rules/python/lint_python_yml/docs/fix-lint_python_yml.md +0 -39
- package/rules/python/lint_python_yml/docs/index.md +0 -9
- package/rules/python/lint_python_yml/fix-lint_python_yml.mjs +0 -11
- package/rules/python/lint_python_yml/lint_python_yml.mdc +0 -12
- package/rules/python/lint_python_yml/lint_python_yml.rego +0 -85
- package/rules/python/lint_python_yml/template/lint-python.yml.snippet.yml +0 -46
- package/rules/rust/lint_rust_yml/concern.json +0 -11
- package/rules/rust/lint_rust_yml/docs/fix-lint_rust_yml.md +0 -37
- package/rules/rust/lint_rust_yml/docs/index.md +0 -9
- package/rules/rust/lint_rust_yml/fix-lint_rust_yml.mjs +0 -11
- package/rules/rust/lint_rust_yml/lint_rust_yml.mdc +0 -17
- package/rules/rust/lint_rust_yml/lint_rust_yml.rego +0 -96
- package/rules/rust/lint_rust_yml/template/lint-rust.yml.snippet.yml +0 -50
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [2.2.0] - 2026-07-30
|
|
4
|
+
|
|
5
|
+
### Removed
|
|
6
|
+
|
|
7
|
+
- Прибрано `**/*.vue` з `paths` канонічного `lint-style.yml.snippet.yml` — цей глоб виїхав у `@7n/rules-lang-js` (`ci.artifact` patch-existing слот `js-lint-style-patch`), той самий патерн, що й `lint-text.yml` у хвилі 3A.
|
|
8
|
+
|
|
9
|
+
## [2.1.0] - 2026-07-29
|
|
10
|
+
|
|
11
|
+
### Removed
|
|
12
|
+
|
|
13
|
+
- text/lint_text: прибрано хардкод JS/TS/Vue/Python globs зі static template — тепер їх додають lang-js/lang-python через ci.artifact patch-existing (поведінка збережена при активних плагінах)
|
|
14
|
+
- Видалено js-специфічні CI-концерни (lint_js_yml) — власність перенесена в @7n/rules-lang-js через ci.artifact@1 contribution
|
|
15
|
+
- Rust GitHub CI-канон (lint-rust.yml) винесено в @7n/rules-lang-rust ci.artifact@1 contribution — обслуговує generic ci.artifact consumer
|
|
16
|
+
- Python-специфічні CI-артефакти (rules/python/lint_python_yml) видалено — тепер @7n/rules-lang-python own них через ci.artifact@1 contribution, обслуговується generic consumer-ом
|
|
17
|
+
|
|
3
18
|
## [2.0.2] - 2026-07-28
|
|
4
19
|
|
|
5
20
|
### Changed
|
package/package.json
CHANGED
|
@@ -6,9 +6,6 @@ on:
|
|
|
6
6
|
- dev
|
|
7
7
|
- main
|
|
8
8
|
paths:
|
|
9
|
-
- '**/*.js'
|
|
10
|
-
- '**/*.ts'
|
|
11
|
-
- '**/*.vue'
|
|
12
9
|
- '**/*.html'
|
|
13
10
|
- '**/*.css'
|
|
14
11
|
- '**/*.scss'
|
|
@@ -24,7 +21,6 @@ on:
|
|
|
24
21
|
- '**/*.mdс'
|
|
25
22
|
- '**/*.txt'
|
|
26
23
|
- '**/*.go'
|
|
27
|
-
- '**/*.py'
|
|
28
24
|
- '**/*.sh'
|
|
29
25
|
|
|
30
26
|
pull_request:
|
|
@@ -32,9 +28,6 @@ on:
|
|
|
32
28
|
- dev
|
|
33
29
|
- main
|
|
34
30
|
paths:
|
|
35
|
-
- '**/*.js'
|
|
36
|
-
- '**/*.ts'
|
|
37
|
-
- '**/*.vue'
|
|
38
31
|
- '**/*.html'
|
|
39
32
|
- '**/*.css'
|
|
40
33
|
- '**/*.scss'
|
|
@@ -50,7 +43,6 @@ on:
|
|
|
50
43
|
- '**/*.mdс'
|
|
51
44
|
- '**/*.txt'
|
|
52
45
|
- '**/*.go'
|
|
53
|
-
- '**/*.py'
|
|
54
46
|
- '**/*.sh'
|
|
55
47
|
|
|
56
48
|
concurrency:
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "https://unpkg.com/@7n/rules/schemas/concern.json",
|
|
3
|
-
"fixability": "config",
|
|
4
|
-
"policy": {
|
|
5
|
-
"files": {
|
|
6
|
-
"single": ".github/workflows/lint-js.yml",
|
|
7
|
-
"required": true
|
|
8
|
-
},
|
|
9
|
-
"missingMessage": ".github/workflows/lint-js.yml не існує — створи за каноном правила (mixin @7n/rules-ci-github)"
|
|
10
|
-
}
|
|
11
|
-
}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: JS Module
|
|
3
|
-
title: fix-lint_js_yml.mjs
|
|
4
|
-
resource: plugins/ci-github/rules/js/lint_js_yml/fix-lint_js_yml.mjs
|
|
5
|
-
docgen:
|
|
6
|
-
crc: e0152cf2
|
|
7
|
-
model: openai-codex/gpt-5.4-mini
|
|
8
|
-
tier: cloud-min
|
|
9
|
-
score: 100
|
|
10
|
-
issues: judge-refine:kept-original,judge:inaccurate:0.98
|
|
11
|
-
judgeModel: openai-codex/gpt-5.4-mini
|
|
12
|
-
---
|
|
13
|
-
|
|
14
|
-
## Огляд
|
|
15
|
-
|
|
16
|
-
`patterns` приводить шлях `.github/workflows/lint-js.yml` до канонічного шаблону концерну, щоб workflow для js-лінту відповідав стандартному корпоративному оформленню.
|
|
17
|
-
|
|
18
|
-
## Поведінка
|
|
19
|
-
|
|
20
|
-
1. `patterns` задає єдиний канонічний сценарій виправлення для CI-workflow лінту js-домену в репозиторіях-консюмерах.
|
|
21
|
-
2. Він узгоджує `.github/workflows/lint-js.yml` із шаблоном концерну: додає відсутні частини, зберігає канонічні значення як пріоритетні та не змінює сторонні коментарі й ключі поза шаблоном.
|
|
22
|
-
3. Якщо цільового файлу немає, `patterns` ініціює його створення з канонічного snippet-а.
|
|
23
|
-
4. Під час застосування механізм свідомо обходить `.github` і `.git`, щоб не зачіпати службові області поза цим сценарієм.
|
|
24
|
-
|
|
25
|
-
## Публічний API
|
|
26
|
-
|
|
27
|
-
- patterns — Один детермінований патерн: deep-merge канонічного snippet-а концерну в
|
|
28
|
-
`.github/workflows/lint-js.yml` консюмер-репо — відсутні ключі додаються,
|
|
29
|
-
канонічні значення мають пріоритет, коментарі й ключі поза шаблоном не
|
|
30
|
-
чіпаються; якщо файлу немає — створюється зі snippet-а.
|
|
31
|
-
|
|
32
|
-
## Гарантії поведінки
|
|
33
|
-
|
|
34
|
-
- Власних операцій запису (ФС/БД) у файлі немає; виклики імпортованих модулів можуть писати.
|
|
35
|
-
- Свідомо пропускає шляхи: `.github`, `.git`.
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: Directory Index
|
|
3
|
-
title: plugins/ci-github/rules/js/lint_js_yml
|
|
4
|
-
resource: plugins/ci-github/rules/js/lint_js_yml/
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
| Файл | Тип |
|
|
8
|
-
| ----------------------------------------- | --------- |
|
|
9
|
-
| [fix-lint_js_yml.mjs](fix-lint_js_yml.md) | JS Module |
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* T0-фікс концерну lint_js_yml: приводить CI-workflow лінту js-домену
|
|
3
|
-
* у консюмер-репо до канонічного шаблону концерну.
|
|
4
|
-
*/
|
|
5
|
-
import { createTemplateFixPattern } from '@7n/rules/scripts/lib/fix/template-deep-merge.mjs'
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Один детермінований патерн: deep-merge канонічного snippet-а концерну в
|
|
9
|
-
* `.github/workflows/lint-js.yml` консюмер-репо — відсутні ключі додаються,
|
|
10
|
-
* канонічні значення мають пріоритет, коментарі й ключі поза шаблоном не
|
|
11
|
-
* чіпаються; якщо файлу немає — створюється зі snippet-а.
|
|
12
|
-
*/
|
|
13
|
-
export const patterns = [
|
|
14
|
-
createTemplateFixPattern({ id: 'js-lint_js_yml-template', targetPath: '.github/workflows/lint-js.yml' })
|
|
15
|
-
]
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
## Rego-gate `.github/workflows/lint-js.yml`
|
|
2
|
-
|
|
3
|
-
Rego-пакет: `js_lint.lint_js_yml`
|
|
4
|
-
|
|
5
|
-
Цільовий файл: `.github/workflows/lint-js.yml`.
|
|
6
|
-
|
|
7
|
-
Що перевіряється:
|
|
8
|
-
|
|
9
|
-
- Наявність усіх `uses:`-кроків з канону (subset-of по `jobs.eslint.steps`); SHA-пін того самого action (`owner/action@<40-hex SHA>`, з тег-коментарем `# vX` чи без) задовольняє канонічний тег — НЕ замінюй наявний SHA-пін тегом
|
|
10
|
-
- Наявність усіх рядків `run:` з канону (substring-match по всіх кроках)
|
|
11
|
-
- `actions/checkout` (будь-який ref) має мати `with.persist-credentials: false` (inverse-check)
|
|
12
|
-
- Заборона `--fix` у CI: `bunx oxlint ... --fix` або `eslint --fix` у будь-якому `run:` → deny
|
|
13
|
-
|
|
14
|
-
Канон-snippet: [lint-js.yml.snippet.yml](./template/lint-js.yml.snippet.yml)
|
|
@@ -1,134 +0,0 @@
|
|
|
1
|
-
# Перевірка `.github/workflows/lint-js.yml` (js.mdc).
|
|
2
|
-
#
|
|
3
|
-
# Канон надходить через --data: { "template": { "snippet": ... } }
|
|
4
|
-
# Структура --data сформована з template/lint-js.yml.snippet.yml.
|
|
5
|
-
# Required uses + run substrings зчитуються з template's eslint-job steps.
|
|
6
|
-
# Універсальні workflow-перевірки — у `ga.workflow_common`.
|
|
7
|
-
#
|
|
8
|
-
# Логіка, що ЛИШАЄТЬСЯ у rego (inverse anti-patterns):
|
|
9
|
-
# - `oxlint --fix` / `eslint --fix` у CI заборонено;
|
|
10
|
-
# - actions/checkout (будь-який ref) має мати `with.persist-credentials: false`.
|
|
11
|
-
#
|
|
12
|
-
# Pin-aware: SHA-пін `owner/action@<40-hex>` (zizmor ref-pin; тег-коментар після
|
|
13
|
-
# `#` YAML-парсер відкидає) ЗАДОВОЛЬНЯЄ канонічний `owner/action@vN` з template —
|
|
14
|
-
# не вимагаємо (і не даунгрейдимо) назад до тега.
|
|
15
|
-
package js.lint_js_yml
|
|
16
|
-
|
|
17
|
-
import rego.v1
|
|
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
|
-
|
|
27
|
-
# Required `uses:` зі template — фільтруємо тільки кроки з uses.
|
|
28
|
-
expected_uses_set contains u if {
|
|
29
|
-
some step in data.template.snippet.jobs.eslint.steps
|
|
30
|
-
u := object.get(step, "uses", "")
|
|
31
|
-
u != ""
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
# Required `run:` substrings (per-line з template).
|
|
35
|
-
expected_run_substrings contains line if {
|
|
36
|
-
some step in data.template.snippet.jobs.eslint.steps
|
|
37
|
-
r := object.get(step, "run", "")
|
|
38
|
-
r != ""
|
|
39
|
-
some raw in split(r, "\n")
|
|
40
|
-
line := trim_space(raw)
|
|
41
|
-
line != ""
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
# Аліаси на input.
|
|
45
|
-
all_steps contains step if {
|
|
46
|
-
some job in object.get(input, "jobs", {})
|
|
47
|
-
some step in object.get(job, "steps", [])
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
all_uses_set contains u if {
|
|
51
|
-
some step in all_steps
|
|
52
|
-
u := object.get(step, "uses", "")
|
|
53
|
-
u != ""
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
all_run_blob := concat("\n", [r |
|
|
57
|
-
some step in all_steps
|
|
58
|
-
r := step_run_text(step)
|
|
59
|
-
])
|
|
60
|
-
|
|
61
|
-
# ── deny: required uses ─────────────────────────────────────────────────
|
|
62
|
-
|
|
63
|
-
deny contains msg if {
|
|
64
|
-
some required_use in expected_uses_set
|
|
65
|
-
not has_use_satisfying(required_use)
|
|
66
|
-
msg := sprintf("lint-js.yml: відсутній крок uses: %s (js.mdc)", [required_use])
|
|
67
|
-
}
|
|
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
|
-
|
|
74
|
-
# ── deny: required run substrings ───────────────────────────────────────
|
|
75
|
-
|
|
76
|
-
deny contains msg if {
|
|
77
|
-
some required_run in expected_run_substrings
|
|
78
|
-
not contains(all_run_blob, required_run)
|
|
79
|
-
msg := sprintf("lint-js.yml: у run немає %q (js.mdc)", [required_run])
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
# ── deny: actions/checkout has persist-credentials: false (inverse) ─────
|
|
83
|
-
|
|
84
|
-
deny contains msg if {
|
|
85
|
-
not has_checkout_persist_credentials_false
|
|
86
|
-
msg := "lint-js.yml: actions/checkout має бути з with.persist-credentials: false (js.mdc)"
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
# ── deny: --fix у CI заборонено (inverse) ───────────────────────────────
|
|
90
|
-
|
|
91
|
-
deny contains msg if {
|
|
92
|
-
regex.match(`bunx\s+oxlint[^\n]*--fix`, all_run_blob)
|
|
93
|
-
msg := "lint-js.yml: у run є oxlint з `--fix` (у CI заборонено) (js.mdc)"
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
deny contains msg if {
|
|
97
|
-
contains(all_run_blob, "eslint --fix")
|
|
98
|
-
msg := "lint-js.yml: у run є `eslint --fix` (у CI заборонено) (js.mdc)"
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
# ── helpers ─────────────────────────────────────────────────────────────
|
|
102
|
-
|
|
103
|
-
has_checkout_persist_credentials_false if {
|
|
104
|
-
some step in all_steps
|
|
105
|
-
startswith(object.get(step, "uses", ""), "actions/checkout@")
|
|
106
|
-
step.with["persist-credentials"] == false
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
# `uses:` з input задовольняє канонічний `owner/action@tag`: точний збіг…
|
|
110
|
-
uses_satisfies(actual, expected) if actual == expected
|
|
111
|
-
|
|
112
|
-
# …або той самий action-slug і ref — повний 40-hex commit SHA (zizmor ref-pin).
|
|
113
|
-
# Відповідність версії гарантує сам пін (тег-коментар `# vX` парсер відкидає).
|
|
114
|
-
uses_satisfies(actual, expected) if {
|
|
115
|
-
slug := split(expected, "@")[0]
|
|
116
|
-
startswith(actual, concat("", [slug, "@"]))
|
|
117
|
-
parts := split(actual, "@")
|
|
118
|
-
regex.match(`^[0-9a-fA-F]{40}$`, parts[count(parts) - 1])
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
has_use_satisfying(required) if {
|
|
122
|
-
some u in all_uses_set
|
|
123
|
-
uses_satisfies(u, required)
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
paths_superset_of(actual, expected) if {
|
|
127
|
-
expected & {p | some p in actual} == expected
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
step_run_text(step) := step.run if is_string(step.run)
|
|
131
|
-
|
|
132
|
-
else := concat("\n", [s | some s in step.run]) if is_array(step.run)
|
|
133
|
-
|
|
134
|
-
else := ""
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
name: Lint JS
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
push:
|
|
5
|
-
branches:
|
|
6
|
-
- dev
|
|
7
|
-
- main
|
|
8
|
-
paths:
|
|
9
|
-
- '**/*.js'
|
|
10
|
-
- '**/*.mjs'
|
|
11
|
-
- '**/*.cjs'
|
|
12
|
-
- '**/*.jsx'
|
|
13
|
-
- '**/*.ts'
|
|
14
|
-
- '**/*.tsx'
|
|
15
|
-
- '**/*.vue'
|
|
16
|
-
- '**/eslint.config.*'
|
|
17
|
-
- '**/.oxlintrc.json'
|
|
18
|
-
|
|
19
|
-
pull_request:
|
|
20
|
-
branches:
|
|
21
|
-
- dev
|
|
22
|
-
- main
|
|
23
|
-
paths:
|
|
24
|
-
- '**/*.js'
|
|
25
|
-
- '**/*.mjs'
|
|
26
|
-
- '**/*.cjs'
|
|
27
|
-
- '**/*.jsx'
|
|
28
|
-
- '**/*.ts'
|
|
29
|
-
- '**/*.tsx'
|
|
30
|
-
- '**/*.vue'
|
|
31
|
-
- '**/eslint.config.*'
|
|
32
|
-
- '**/.oxlintrc.json'
|
|
33
|
-
|
|
34
|
-
concurrency:
|
|
35
|
-
group: ${{ github.ref }}-${{ github.workflow }}
|
|
36
|
-
cancel-in-progress: true
|
|
37
|
-
|
|
38
|
-
jobs:
|
|
39
|
-
eslint:
|
|
40
|
-
runs-on: ubuntu-latest
|
|
41
|
-
permissions:
|
|
42
|
-
contents: read
|
|
43
|
-
steps:
|
|
44
|
-
- uses: actions/checkout@v6
|
|
45
|
-
with:
|
|
46
|
-
persist-credentials: false
|
|
47
|
-
|
|
48
|
-
- uses: ./.github/actions/setup-bun-deps
|
|
49
|
-
|
|
50
|
-
- name: Eslint
|
|
51
|
-
run: bunx n-rules lint js --no-fix
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "https://unpkg.com/@7n/rules/schemas/concern.json",
|
|
3
|
-
"fixability": "config",
|
|
4
|
-
"policy": {
|
|
5
|
-
"files": {
|
|
6
|
-
"single": ".github/workflows/lint-python.yml",
|
|
7
|
-
"required": true
|
|
8
|
-
},
|
|
9
|
-
"missingMessage": ".github/workflows/lint-python.yml не існує — створи за каноном правила (mixin @7n/rules-ci-github)"
|
|
10
|
-
}
|
|
11
|
-
}
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: JS Module
|
|
3
|
-
title: fix-lint_python_yml.mjs
|
|
4
|
-
resource: plugins/ci-github/rules/python/lint_python_yml/fix-lint_python_yml.mjs
|
|
5
|
-
docgen:
|
|
6
|
-
crc: 525f6959
|
|
7
|
-
model: openai-codex/gpt-5.5
|
|
8
|
-
tier: cloud-avg
|
|
9
|
-
score: 100
|
|
10
|
-
issues: judge:error
|
|
11
|
-
judgeModel: openai-codex/gpt-5.4-mini
|
|
12
|
-
---
|
|
13
|
-
|
|
14
|
-
## Огляд
|
|
15
|
-
|
|
16
|
-
Файл декларує автофікс для `python/lint_python_yml`: scaffold відсутнього `.github/workflows/lint-python.yml` з канонічного шаблону правила та `template-deep-merge` для наявного workflow. Він потрібен, щоб дописувати лише канонічні поля для Python lint у GitHub Actions і зберігати локальні налаштування проєкту.
|
|
17
|
-
|
|
18
|
-
Публічна точка входу: `patterns`. Свідомо пропущені шляхи: `.github`, `.git`. Власних операцій запису у файлі немає.
|
|
19
|
-
|
|
20
|
-
## Поведінка
|
|
21
|
-
|
|
22
|
-
1. `patterns` оголошує автофікс для правила `python/lint_python_yml`, щоб репозиторій отримував канонічний GitHub Actions workflow для Python lint.
|
|
23
|
-
|
|
24
|
-
2. Якщо `.github/workflows/lint-python.yml` відсутній, автофікс має створити його з шаблону правила.
|
|
25
|
-
|
|
26
|
-
3. Якщо workflow уже існує, автофікс має доповнити його лише канонічними полями правила, не прибираючи локальні налаштування проєкту.
|
|
27
|
-
|
|
28
|
-
4. Правило свідомо не обходить службові шляхи `.github` і `.git`, але працює з цільовим workflow-файлом як із винятком для підтримки потрібної CI-конфігурації.
|
|
29
|
-
|
|
30
|
-
5. Файл лише декларує поведінку автофікса через `patterns`; власних операцій запису не виконує.
|
|
31
|
-
|
|
32
|
-
## Публічний API
|
|
33
|
-
|
|
34
|
-
- patterns — Фікс-патерни концерну: один template-deep-merge запис для `.github/workflows/lint-python.yml`.
|
|
35
|
-
|
|
36
|
-
## Гарантії поведінки
|
|
37
|
-
|
|
38
|
-
- Власних операцій запису (ФС/БД) у файлі немає; виклики імпортованих модулів можуть писати.
|
|
39
|
-
- Свідомо пропускає шляхи: `.github`, `.git`.
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: Directory Index
|
|
3
|
-
title: plugins/ci-github/rules/python/lint_python_yml
|
|
4
|
-
resource: plugins/ci-github/rules/python/lint_python_yml/
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
| Файл | Тип |
|
|
8
|
-
| ------------------------------------------------- | --------- |
|
|
9
|
-
| [fix-lint_python_yml.mjs](fix-lint_python_yml.md) | JS Module |
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* T0-autofix концерну `python/lint_python_yml`: деклараційний template-deep-merge —
|
|
3
|
-
* scaffold відсутнього `.github/workflows/lint-python.yml` з канонічного шаблону правила або
|
|
4
|
-
* дописування в наявний файл лише канонічних полів (локальні — зберігаються).
|
|
5
|
-
*/
|
|
6
|
-
import { createTemplateFixPattern } from '@7n/rules/scripts/lib/fix/template-deep-merge.mjs'
|
|
7
|
-
|
|
8
|
-
/** Фікс-патерни концерну: один template-deep-merge запис для `.github/workflows/lint-python.yml`. */
|
|
9
|
-
export const patterns = [
|
|
10
|
-
createTemplateFixPattern({ id: 'python-lint_python_yml-template', targetPath: '.github/workflows/lint-python.yml' })
|
|
11
|
-
]
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
## Rego-gate: перевірка `.github/workflows/lint-python.yml`
|
|
2
|
-
|
|
3
|
-
Rego-пакет: `python.lint_python_yml`
|
|
4
|
-
|
|
5
|
-
Цільовий файл: `.github/workflows/lint-python.yml`
|
|
6
|
-
|
|
7
|
-
Перевіряє (drift-safe через `--data template`):
|
|
8
|
-
|
|
9
|
-
- кожен `uses` з канону (підмножина) присутній у workflow: `actions/checkout@v6`, `./.github/actions/setup-bun-deps`, `astral-sh/setup-uv@v8.0.0`;
|
|
10
|
-
- кожен `run` з канону є substring серед run-кроків: `uv sync --frozen`, `n-rules lint python --no-fix`.
|
|
11
|
-
|
|
12
|
-
Канонічний workflow: [lint-python.yml.snippet.yml](./template/lint-python.yml.snippet.yml)
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
# Перевірка `.github/workflows/lint-python.yml` для правила python (python.mdc).
|
|
2
|
-
#
|
|
3
|
-
# Канон надходить через --data: { "template": { "snippet": ... } }
|
|
4
|
-
# Структура --data сформована з template/lint-python.yml.snippet.yml.
|
|
5
|
-
# Перевіряємо (drift-safe — усе ведеться з template, без inline-літералів):
|
|
6
|
-
# - кожен `uses` з template (підмножина): actions/checkout@v6,
|
|
7
|
-
# ./.github/actions/setup-bun-deps, astral-sh/setup-uv@v8.0.0;
|
|
8
|
-
# - кожен `run` з template має бути присутнім (як substring) серед run-кроків
|
|
9
|
-
# input'а: `uv sync --frozen`, `n-rules lint python --no-fix`.
|
|
10
|
-
# Заборона Poetry-кроків (snok/install-poetry, `poetry install`) — через відсутність
|
|
11
|
-
# у каноні: правило вимагає uv-кроки, а нав'язаних poetry-кроків у template немає.
|
|
12
|
-
# Універсальні workflow-перевірки (name, concurrency, branches) — у `ga.workflow_common`.
|
|
13
|
-
package python.lint_python_yml
|
|
14
|
-
|
|
15
|
-
import rego.v1
|
|
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
|
-
|
|
25
|
-
# Усі `uses` з канону workflow (по всіх job'ах template).
|
|
26
|
-
expected_uses contains u if {
|
|
27
|
-
some job in data.template.snippet.jobs
|
|
28
|
-
some step in job.steps
|
|
29
|
-
u := object.get(step, "uses", "")
|
|
30
|
-
u != ""
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
# Усі `uses` з input workflow.
|
|
34
|
-
actual_uses contains u if {
|
|
35
|
-
some job in object.get(input, "jobs", {})
|
|
36
|
-
some step in object.get(job, "steps", [])
|
|
37
|
-
u := object.get(step, "uses", "")
|
|
38
|
-
u != ""
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
# Конкатенація всіх `run`-кроків з input workflow.
|
|
42
|
-
all_run_text := concat("\n", [run_text |
|
|
43
|
-
some job in object.get(input, "jobs", {})
|
|
44
|
-
some step in object.get(job, "steps", [])
|
|
45
|
-
run_text := step_run_to_text(step)
|
|
46
|
-
])
|
|
47
|
-
|
|
48
|
-
deny contains msg if {
|
|
49
|
-
some required_use in expected_uses
|
|
50
|
-
not required_use in actual_uses
|
|
51
|
-
msg := sprintf("lint-python.yml: відсутній step з `uses: %s` (python.mdc)", [required_use])
|
|
52
|
-
}
|
|
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
|
-
|
|
59
|
-
deny contains msg if {
|
|
60
|
-
msg := "lint-python.yml: actions/checkout@v6 потребує `with: persist-credentials: false` (python.mdc)"
|
|
61
|
-
some job in object.get(input, "jobs", {})
|
|
62
|
-
some step in object.get(job, "steps", [])
|
|
63
|
-
step.uses == "actions/checkout@v6"
|
|
64
|
-
creds := object.get(object.get(step, "with", {}), "persist-credentials", true)
|
|
65
|
-
creds != false
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
deny contains msg if {
|
|
69
|
-
some job in data.template.snippet.jobs
|
|
70
|
-
some step in job.steps
|
|
71
|
-
expected_run := object.get(step, "run", "")
|
|
72
|
-
expected_run != ""
|
|
73
|
-
not contains(all_run_text, expected_run)
|
|
74
|
-
msg := sprintf("lint-python.yml: жоден крок run не містить %q (python.mdc)", [expected_run])
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
step_run_to_text(step) := step.run if is_string(step.run)
|
|
78
|
-
|
|
79
|
-
else := concat("\n", [s | some s in step.run]) if is_array(step.run)
|
|
80
|
-
|
|
81
|
-
else := ""
|
|
82
|
-
|
|
83
|
-
paths_superset_of(actual, expected) if {
|
|
84
|
-
expected & {p | some p in actual} == expected
|
|
85
|
-
}
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
name: Lint Python
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
push:
|
|
5
|
-
branches:
|
|
6
|
-
- dev
|
|
7
|
-
- main
|
|
8
|
-
paths:
|
|
9
|
-
- '**/*.py'
|
|
10
|
-
- 'pyproject.toml'
|
|
11
|
-
- 'uv.lock'
|
|
12
|
-
- '.github/workflows/lint-python.yml'
|
|
13
|
-
|
|
14
|
-
pull_request:
|
|
15
|
-
branches:
|
|
16
|
-
- dev
|
|
17
|
-
- main
|
|
18
|
-
paths:
|
|
19
|
-
- '**/*.py'
|
|
20
|
-
- 'pyproject.toml'
|
|
21
|
-
- 'uv.lock'
|
|
22
|
-
- '.github/workflows/lint-python.yml'
|
|
23
|
-
|
|
24
|
-
concurrency:
|
|
25
|
-
group: ${{ github.ref }}-${{ github.workflow }}
|
|
26
|
-
cancel-in-progress: true
|
|
27
|
-
|
|
28
|
-
jobs:
|
|
29
|
-
python:
|
|
30
|
-
runs-on: ubuntu-latest
|
|
31
|
-
permissions:
|
|
32
|
-
contents: read
|
|
33
|
-
steps:
|
|
34
|
-
- uses: actions/checkout@v6
|
|
35
|
-
with:
|
|
36
|
-
persist-credentials: false
|
|
37
|
-
|
|
38
|
-
- uses: ./.github/actions/setup-bun-deps
|
|
39
|
-
|
|
40
|
-
- uses: astral-sh/setup-uv@v8.0.0
|
|
41
|
-
|
|
42
|
-
- name: Install dependencies (uv)
|
|
43
|
-
run: uv sync --frozen
|
|
44
|
-
|
|
45
|
-
- name: Lint Python
|
|
46
|
-
run: bunx n-rules lint python --no-fix
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "https://unpkg.com/@7n/rules/schemas/concern.json",
|
|
3
|
-
"fixability": "config",
|
|
4
|
-
"policy": {
|
|
5
|
-
"files": {
|
|
6
|
-
"single": ".github/workflows/lint-rust.yml",
|
|
7
|
-
"required": true
|
|
8
|
-
},
|
|
9
|
-
"missingMessage": ".github/workflows/lint-rust.yml не існує — створи з канонічним вмістом (rust.mdc)"
|
|
10
|
-
}
|
|
11
|
-
}
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: JS Module
|
|
3
|
-
title: fix-lint_rust_yml.mjs
|
|
4
|
-
resource: plugins/ci-github/rules/rust/lint_rust_yml/fix-lint_rust_yml.mjs
|
|
5
|
-
docgen:
|
|
6
|
-
crc: 4312b7ec
|
|
7
|
-
model: openai-codex/gpt-5.5
|
|
8
|
-
tier: cloud-avg
|
|
9
|
-
score: 100
|
|
10
|
-
issues: judge-refine:kept-original,judge:inaccurate:0.99
|
|
11
|
-
judgeModel: openai-codex/gpt-5.4-mini
|
|
12
|
-
---
|
|
13
|
-
|
|
14
|
-
## Огляд
|
|
15
|
-
|
|
16
|
-
Файл описує T0-autofix для `rust/lint_rust_yml`: scaffold відсутнього `.github/workflows/lint-rust.yml` з канонічного шаблону правила або `template-deep-merge` канонічних полів у наявний workflow зі збереженням локальних налаштувань.
|
|
17
|
-
|
|
18
|
-
Публічна функція `patterns` декларує цю поведінку для правила. Обхід свідомо пропускає шляхи `.github` і `.git`, щоб не аналізувати службові директорії як джерела проєктного Rust-коду.
|
|
19
|
-
|
|
20
|
-
## Поведінка
|
|
21
|
-
|
|
22
|
-
1. `patterns` оголошує єдиний сценарій autofix для Rust lint workflow.
|
|
23
|
-
|
|
24
|
-
2. Сценарій створює відсутній `.github/workflows/lint-rust.yml` за канонічним шаблоном правила, щоб проєкт мав стандартну GitHub Actions перевірку Rust lint.
|
|
25
|
-
|
|
26
|
-
3. Якщо workflow уже існує, сценарій доповнює його лише канонічними полями, зберігаючи локальні налаштування проєкту.
|
|
27
|
-
|
|
28
|
-
4. Autofix свідомо не обходить службові шляхи `.github` і `.git` як звичайні цілі аналізу; `.github/workflows/lint-rust.yml` використовується лише як визначений цільовий workflow-файл.
|
|
29
|
-
|
|
30
|
-
## Публічний API
|
|
31
|
-
|
|
32
|
-
- patterns — Фікс-патерни концерну: один template-deep-merge запис для `.github/workflows/lint-rust.yml`.
|
|
33
|
-
|
|
34
|
-
## Гарантії поведінки
|
|
35
|
-
|
|
36
|
-
- Власних операцій запису (ФС/БД) у файлі немає; виклики імпортованих модулів можуть писати.
|
|
37
|
-
- Свідомо пропускає шляхи: `.github`, `.git`.
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: Directory Index
|
|
3
|
-
title: plugins/ci-github/rules/rust/lint_rust_yml
|
|
4
|
-
resource: plugins/ci-github/rules/rust/lint_rust_yml/
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
| Файл | Тип |
|
|
8
|
-
| --------------------------------------------- | --------- |
|
|
9
|
-
| [fix-lint_rust_yml.mjs](fix-lint_rust_yml.md) | JS Module |
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* T0-autofix концерну `rust/lint_rust_yml`: деклараційний template-deep-merge —
|
|
3
|
-
* scaffold відсутнього `.github/workflows/lint-rust.yml` з канонічного шаблону правила або
|
|
4
|
-
* дописування в наявний файл лише канонічних полів (локальні — зберігаються).
|
|
5
|
-
*/
|
|
6
|
-
import { createTemplateFixPattern } from '@7n/rules/scripts/lib/fix/template-deep-merge.mjs'
|
|
7
|
-
|
|
8
|
-
/** Фікс-патерни концерну: один template-deep-merge запис для `.github/workflows/lint-rust.yml`. */
|
|
9
|
-
export const patterns = [
|
|
10
|
-
createTemplateFixPattern({ id: 'rust-lint_rust_yml-template', targetPath: '.github/workflows/lint-rust.yml' })
|
|
11
|
-
]
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
## Перевірка `.github/workflows/lint-rust.yml`
|
|
2
|
-
|
|
3
|
-
Rego-пакет: `rust.lint_rust_yml`
|
|
4
|
-
|
|
5
|
-
Цільовий файл: `.github/workflows/lint-rust.yml`
|
|
6
|
-
|
|
7
|
-
Перевіряє:
|
|
8
|
-
|
|
9
|
-
- кожен `uses`-крок з канону присутній у workflow (підмножина): `actions/checkout@v6`, `dtolnay/rust-toolchain@stable`, `Swatinem/rust-cache@v2`
|
|
10
|
-
- кожен `run`-крок з канону присутній як підрядок серед усіх `run`-кроків: `cargo fmt --all -- --check`, `cargo clippy --all-targets --all-features -- -D warnings`
|
|
11
|
-
- канон завантажується через `--data` з template-сніпету — drift-safe: зміна шаблону автоматично рухає перевірку
|
|
12
|
-
|
|
13
|
-
Канонічний template: [lint-rust.yml.snippet.yml](./template/lint-rust.yml.snippet.yml)
|
|
14
|
-
|
|
15
|
-
Вимога `Swatinem/rust-cache@v2` після `dtolnay/rust-toolchain@…` тут перевіряється лише для цього конкретного файлу (як частина канону). Та сама вимога для **будь-якого** іншого workflow (coverage, release/build через `tauri-apps/tauri-action`, кастомні) — concern `rust/toolchain_cache`.
|
|
16
|
-
|
|
17
|
-
Tauri-проєкти (`src-tauri/Cargo.toml`) додатково потребують у цьому файлі apt-кроку системних залежностей Linux перед Clippy — concern `tauri/linux_deps` (tauri.mdc), не частина канону тут.
|
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
# Перевірка `.github/workflows/lint-rust.yml` для правила rust (rust.mdc).
|
|
2
|
-
#
|
|
3
|
-
# Канон надходить через --data: { "template": { "snippet": ... } }
|
|
4
|
-
# Структура --data сформована з template/lint-rust.yml.snippet.yml.
|
|
5
|
-
# Перевіряємо:
|
|
6
|
-
# - кожен `uses` з template (підмножина): actions/checkout@v6,
|
|
7
|
-
# dtolnay/rust-toolchain@stable, Swatinem/rust-cache@v2;
|
|
8
|
-
# - кожен `run` з template має бути присутнім (як substring) серед
|
|
9
|
-
# run-кроків input'а — drift-safe: зміна template одразу рухає перевірку.
|
|
10
|
-
# Універсальні workflow-перевірки (name, concurrency, branches) — у `ga.workflow_common`.
|
|
11
|
-
package rust.lint_rust_yml
|
|
12
|
-
|
|
13
|
-
import rego.v1
|
|
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
|
-
|
|
23
|
-
# Усі `uses` з канону workflow.
|
|
24
|
-
expected_uses contains u if {
|
|
25
|
-
some step in data.template.snippet.jobs.lint.steps
|
|
26
|
-
u := object.get(step, "uses", "")
|
|
27
|
-
u != ""
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
# Усі `uses` з input workflow.
|
|
31
|
-
actual_uses contains u if {
|
|
32
|
-
some job in object.get(input, "jobs", {})
|
|
33
|
-
some step in object.get(job, "steps", [])
|
|
34
|
-
u := object.get(step, "uses", "")
|
|
35
|
-
u != ""
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
# Конкатенація всіх `run`-кроків з input workflow.
|
|
39
|
-
all_run_text := concat("\n", [run_text |
|
|
40
|
-
some job in object.get(input, "jobs", {})
|
|
41
|
-
some step in object.get(job, "steps", [])
|
|
42
|
-
run_text := step_run_to_text(step)
|
|
43
|
-
])
|
|
44
|
-
|
|
45
|
-
# Крок dtolnay/rust-toolchain@stable має мати with.components з rustfmt і clippy.
|
|
46
|
-
toolchain_step(step) if {
|
|
47
|
-
uses := object.get(step, "uses", "")
|
|
48
|
-
startswith(uses, "dtolnay/rust-toolchain@")
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
deny contains msg if {
|
|
52
|
-
some required_use in expected_uses
|
|
53
|
-
not required_use in actual_uses
|
|
54
|
-
msg := sprintf("lint-rust.yml: відсутній step з `uses: %s` (rust.mdc)", [required_use])
|
|
55
|
-
}
|
|
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
|
-
|
|
62
|
-
deny contains msg if {
|
|
63
|
-
some step in data.template.snippet.jobs.lint.steps
|
|
64
|
-
expected_run := object.get(step, "run", "")
|
|
65
|
-
expected_run != ""
|
|
66
|
-
not contains(all_run_text, expected_run)
|
|
67
|
-
msg := sprintf("lint-rust.yml: жоден крок run не містить %q (rust.mdc)", [expected_run])
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
deny contains msg if {
|
|
71
|
-
msg := "lint-rust.yml: dtolnay/rust-toolchain step потребує with.components: rustfmt, clippy (rust.mdc)"
|
|
72
|
-
some job in object.get(input, "jobs", {})
|
|
73
|
-
some step in object.get(job, "steps", [])
|
|
74
|
-
toolchain_step(step)
|
|
75
|
-
components := object.get(object.get(step, "with", {}), "components", "")
|
|
76
|
-
not contains(components, "rustfmt")
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
deny contains msg if {
|
|
80
|
-
msg := "lint-rust.yml: dtolnay/rust-toolchain step потребує with.components: rustfmt, clippy (rust.mdc)"
|
|
81
|
-
some job in object.get(input, "jobs", {})
|
|
82
|
-
some step in object.get(job, "steps", [])
|
|
83
|
-
toolchain_step(step)
|
|
84
|
-
components := object.get(object.get(step, "with", {}), "components", "")
|
|
85
|
-
not contains(components, "clippy")
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
step_run_to_text(step) := step.run if is_string(step.run)
|
|
89
|
-
|
|
90
|
-
else := concat("\n", [s | some s in step.run]) if is_array(step.run)
|
|
91
|
-
|
|
92
|
-
else := ""
|
|
93
|
-
|
|
94
|
-
paths_superset_of(actual, expected) if {
|
|
95
|
-
expected & {p | some p in actual} == expected
|
|
96
|
-
}
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
name: Lint Rust
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
push:
|
|
5
|
-
branches:
|
|
6
|
-
- dev
|
|
7
|
-
- main
|
|
8
|
-
paths:
|
|
9
|
-
- '**/*.rs'
|
|
10
|
-
- '**/Cargo.toml'
|
|
11
|
-
- '**/Cargo.lock'
|
|
12
|
-
- '**/rustfmt.toml'
|
|
13
|
-
- '**/clippy.toml'
|
|
14
|
-
|
|
15
|
-
pull_request:
|
|
16
|
-
branches:
|
|
17
|
-
- dev
|
|
18
|
-
- main
|
|
19
|
-
paths:
|
|
20
|
-
- '**/*.rs'
|
|
21
|
-
- '**/Cargo.toml'
|
|
22
|
-
- '**/Cargo.lock'
|
|
23
|
-
- '**/rustfmt.toml'
|
|
24
|
-
- '**/clippy.toml'
|
|
25
|
-
|
|
26
|
-
concurrency:
|
|
27
|
-
group: ${{ github.ref }}-${{ github.workflow }}
|
|
28
|
-
cancel-in-progress: true
|
|
29
|
-
|
|
30
|
-
jobs:
|
|
31
|
-
lint:
|
|
32
|
-
runs-on: ubuntu-latest
|
|
33
|
-
permissions:
|
|
34
|
-
contents: read
|
|
35
|
-
steps:
|
|
36
|
-
- uses: actions/checkout@v6
|
|
37
|
-
with:
|
|
38
|
-
persist-credentials: false
|
|
39
|
-
|
|
40
|
-
- uses: dtolnay/rust-toolchain@stable
|
|
41
|
-
with:
|
|
42
|
-
components: rustfmt, clippy
|
|
43
|
-
|
|
44
|
-
- uses: Swatinem/rust-cache@v2
|
|
45
|
-
|
|
46
|
-
- name: Rustfmt
|
|
47
|
-
run: cargo fmt --all -- --check
|
|
48
|
-
|
|
49
|
-
- name: Clippy
|
|
50
|
-
run: cargo clippy --all-targets --all-features -- -D warnings
|