@7n/rules 1.5.1 → 1.6.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 +6 -0
- package/bin/n-rules.js +83 -21
- package/package.json +1 -1
- package/rules/abie/main.mdc +0 -6
- package/rules/js/check/docs/main.md +1 -1
- package/rules/js/check/main.mjs +6 -10
- package/rules/js/main.mdc +0 -1
- package/rules/js/vscode_extensions/template/extensions.json.snippet.json +4 -1
- package/rules/npm-module/main.mdc +0 -2
- package/rules/php/tooling/docs/main.md +1 -1
- package/rules/php/tooling/main.mjs +2 -7
- package/rules/python/tooling/docs/main.md +1 -1
- package/rules/python/tooling/main.mjs +2 -7
- package/rules/rego/lib/docs/run-external-tool.md +1 -2
- package/rules/rego/lib/run-external-tool.mjs +4 -1
- package/rules/security/main.mdc +0 -1
- package/rules/style/main.mdc +0 -1
- package/rules/style/tooling/docs/main.md +1 -1
- package/rules/style/tooling/main.mjs +2 -7
- package/rules/tauri/release/release.mdc +1 -1
- package/rules/text/formatting/docs/main.md +1 -1
- package/rules/text/formatting/main.mjs +11 -11
- package/rules/text/main.mdc +0 -1
- package/scripts/docs/skills-cli.md +3 -3
- package/scripts/lib/acp-runner.mjs +8 -10
- package/scripts/lib/docs/acp-runner.md +5 -5
- package/scripts/lib/docs/mirror-parity.md +1 -1
- package/scripts/lib/mirror-parity.mjs +49 -16
- package/scripts/skills-cli.mjs +1 -1
- package/rules/abie/clean_merged_ignore_branches/clean_merged_ignore_branches.mdc +0 -19
- package/rules/abie/clean_merged_ignore_branches/clean_merged_ignore_branches.rego +0 -81
- package/rules/abie/clean_merged_ignore_branches/concern.json +0 -11
- package/rules/abie/clean_merged_ignore_branches/docs/fix-clean_merged_ignore_branches.md +0 -31
- package/rules/abie/clean_merged_ignore_branches/docs/index.md +0 -9
- package/rules/abie/clean_merged_ignore_branches/fix-clean_merged_ignore_branches.mjs +0 -8
- package/rules/abie/clean_merged_ignore_branches/template/clean-merged-branch.yml.snippet.yml +0 -9
- package/rules/docker/lint_docker_yml/concern.json +0 -12
- package/rules/docker/lint_docker_yml/docs/fix-lint_docker_yml.md +0 -31
- package/rules/docker/lint_docker_yml/docs/index.md +0 -9
- package/rules/docker/lint_docker_yml/fix-lint_docker_yml.mjs +0 -5
- package/rules/docker/lint_docker_yml/lint_docker_yml.mdc +0 -14
- package/rules/docker/lint_docker_yml/lint_docker_yml.rego +0 -79
- package/rules/docker/lint_docker_yml/template/lint-docker.yml.snippet.yml +0 -41
- package/rules/js/lint_js_yml/concern.json +0 -12
- package/rules/js/lint_js_yml/docs/fix-lint_js_yml.md +0 -28
- package/rules/js/lint_js_yml/docs/index.md +0 -9
- package/rules/js/lint_js_yml/fix-lint_js_yml.mjs +0 -5
- package/rules/js/lint_js_yml/lint_js_yml.mdc +0 -14
- package/rules/js/lint_js_yml/lint_js_yml.rego +0 -117
- package/rules/js/lint_js_yml/template/lint-js.yml.snippet.yml +0 -40
- package/rules/k8s/lint_k8s_yml/concern.json +0 -12
- package/rules/k8s/lint_k8s_yml/docs/fix-lint_k8s_yml.md +0 -30
- package/rules/k8s/lint_k8s_yml/docs/index.md +0 -9
- package/rules/k8s/lint_k8s_yml/fix-lint_k8s_yml.mjs +0 -5
- package/rules/k8s/lint_k8s_yml/lint_k8s_yml.rego +0 -57
- package/rules/k8s/lint_k8s_yml/template/lint-k8s.yml.snippet.yml +0 -43
- package/rules/npm-module/npm_publish_yml/concern.json +0 -13
- package/rules/npm-module/npm_publish_yml/docs/fix-npm_publish_yml.md +0 -28
- package/rules/npm-module/npm_publish_yml/docs/index.md +0 -9
- package/rules/npm-module/npm_publish_yml/fix-npm_publish_yml.mjs +0 -8
- package/rules/npm-module/npm_publish_yml/template/npm-publish.yml.snippet.yml +0 -49
- package/rules/php/lint_php_yml/concern.json +0 -12
- package/rules/php/lint_php_yml/docs/fix-lint_php_yml.md +0 -28
- package/rules/php/lint_php_yml/docs/index.md +0 -9
- package/rules/php/lint_php_yml/fix-lint_php_yml.mjs +0 -5
- package/rules/php/lint_php_yml/lint_php_yml.mdc +0 -23
- package/rules/php/lint_php_yml/lint_php_yml.rego +0 -34
- package/rules/php/lint_php_yml/template/lint-php.yml.snippet.yml +0 -47
- package/rules/python/lint_python_yml/concern.json +0 -12
- package/rules/python/lint_python_yml/docs/fix-lint_python_yml.md +0 -27
- package/rules/python/lint_python_yml/docs/index.md +0 -9
- package/rules/python/lint_python_yml/fix-lint_python_yml.mjs +0 -5
- package/rules/python/lint_python_yml/lint_python_yml.mdc +0 -12
- package/rules/python/lint_python_yml/lint_python_yml.rego +0 -68
- package/rules/python/lint_python_yml/template/lint-python.yml.snippet.yml +0 -41
- package/rules/rust/lint_rust_yml/concern.json +0 -14
- package/rules/rust/lint_rust_yml/docs/fix-lint_rust_yml.md +0 -28
- package/rules/rust/lint_rust_yml/docs/index.md +0 -9
- package/rules/rust/lint_rust_yml/fix-lint_rust_yml.mjs +0 -5
- package/rules/rust/lint_rust_yml/lint_rust_yml.mdc +0 -17
- package/rules/rust/lint_rust_yml/lint_rust_yml.rego +0 -79
- package/rules/rust/lint_rust_yml/template/lint-rust.yml.snippet.yml +0 -44
- package/rules/rust/toolchain_cache/concern.json +0 -14
- package/rules/rust/toolchain_cache/docs/fix-toolchain_cache.md +0 -35
- package/rules/rust/toolchain_cache/docs/index.md +0 -12
- package/rules/rust/toolchain_cache/docs/main.md +0 -57
- package/rules/rust/toolchain_cache/fix-toolchain_cache.mjs +0 -117
- package/rules/rust/toolchain_cache/main.mjs +0 -177
- package/rules/rust/toolchain_cache/toolchain_cache.mdc +0 -23
- package/rules/security/lint_security_yml/concern.json +0 -14
- package/rules/security/lint_security_yml/docs/fix-lint_security_yml.md +0 -31
- package/rules/security/lint_security_yml/docs/index.md +0 -9
- package/rules/security/lint_security_yml/fix-lint_security_yml.mjs +0 -8
- package/rules/security/lint_security_yml/lint_security_yml.mdc +0 -7
- package/rules/security/lint_security_yml/lint_security_yml.rego +0 -33
- package/rules/security/lint_security_yml/template/lint-security.yml.snippet.yml +0 -31
- package/rules/style/lint_style_yml/concern.json +0 -12
- package/rules/style/lint_style_yml/docs/fix-lint_style_yml.md +0 -31
- package/rules/style/lint_style_yml/docs/index.md +0 -9
- package/rules/style/lint_style_yml/fix-lint_style_yml.mjs +0 -5
- package/rules/style/lint_style_yml/lint_style_yml.mdc +0 -13
- package/rules/style/lint_style_yml/lint_style_yml.rego +0 -38
- package/rules/style/lint_style_yml/template/lint-style.yml.snippet.yml +0 -39
- package/rules/text/lint_text/concern.json +0 -11
- package/rules/text/lint_text/docs/fix-lint_text.md +0 -28
- package/rules/text/lint_text/docs/index.md +0 -9
- package/rules/text/lint_text/fix-lint_text.mjs +0 -5
- package/rules/text/lint_text/lint_text.mdc +0 -19
- package/rules/text/lint_text/lint_text.rego +0 -104
- package/rules/text/lint_text/template/lint-text.yml.snippet.yml +0 -61
|
@@ -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,68 +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
|
-
# Усі `uses` з канону workflow (по всіх job'ах template).
|
|
18
|
-
expected_uses contains u if {
|
|
19
|
-
some job in data.template.snippet.jobs
|
|
20
|
-
some step in job.steps
|
|
21
|
-
u := object.get(step, "uses", "")
|
|
22
|
-
u != ""
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
# Усі `uses` з input workflow.
|
|
26
|
-
actual_uses contains u if {
|
|
27
|
-
some job in object.get(input, "jobs", {})
|
|
28
|
-
some step in object.get(job, "steps", [])
|
|
29
|
-
u := object.get(step, "uses", "")
|
|
30
|
-
u != ""
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
# Конкатенація всіх `run`-кроків з input workflow.
|
|
34
|
-
all_run_text := concat("\n", [run_text |
|
|
35
|
-
some job in object.get(input, "jobs", {})
|
|
36
|
-
some step in object.get(job, "steps", [])
|
|
37
|
-
run_text := step_run_to_text(step)
|
|
38
|
-
])
|
|
39
|
-
|
|
40
|
-
deny contains msg if {
|
|
41
|
-
some required_use in expected_uses
|
|
42
|
-
not required_use in actual_uses
|
|
43
|
-
msg := sprintf("lint-python.yml: відсутній step з `uses: %s` (python.mdc)", [required_use])
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
deny contains msg if {
|
|
47
|
-
msg := "lint-python.yml: actions/checkout@v6 потребує `with: persist-credentials: false` (python.mdc)"
|
|
48
|
-
some job in object.get(input, "jobs", {})
|
|
49
|
-
some step in object.get(job, "steps", [])
|
|
50
|
-
step.uses == "actions/checkout@v6"
|
|
51
|
-
creds := object.get(object.get(step, "with", {}), "persist-credentials", true)
|
|
52
|
-
creds != false
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
deny contains msg if {
|
|
56
|
-
some job in data.template.snippet.jobs
|
|
57
|
-
some step in job.steps
|
|
58
|
-
expected_run := object.get(step, "run", "")
|
|
59
|
-
expected_run != ""
|
|
60
|
-
not contains(all_run_text, expected_run)
|
|
61
|
-
msg := sprintf("lint-python.yml: жоден крок run не містить %q (python.mdc)", [expected_run])
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
step_run_to_text(step) := step.run if is_string(step.run)
|
|
65
|
-
|
|
66
|
-
else := concat("\n", [s | some s in step.run]) if is_array(step.run)
|
|
67
|
-
|
|
68
|
-
else := ""
|
|
@@ -1,41 +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
|
-
|
|
19
|
-
concurrency:
|
|
20
|
-
group: ${{ github.ref }}-${{ github.workflow }}
|
|
21
|
-
cancel-in-progress: true
|
|
22
|
-
|
|
23
|
-
jobs:
|
|
24
|
-
python:
|
|
25
|
-
runs-on: ubuntu-latest
|
|
26
|
-
permissions:
|
|
27
|
-
contents: read
|
|
28
|
-
steps:
|
|
29
|
-
- uses: actions/checkout@v6
|
|
30
|
-
with:
|
|
31
|
-
persist-credentials: false
|
|
32
|
-
|
|
33
|
-
- uses: ./.github/actions/setup-bun-deps
|
|
34
|
-
|
|
35
|
-
- uses: astral-sh/setup-uv@v8.0.0
|
|
36
|
-
|
|
37
|
-
- name: Install dependencies (uv)
|
|
38
|
-
run: uv sync --frozen
|
|
39
|
-
|
|
40
|
-
- name: Lint Python
|
|
41
|
-
run: bunx n-rules lint python --no-fix
|
|
@@ -1,14 +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
|
-
"requires": {
|
|
12
|
-
"capability": "ci:github"
|
|
13
|
-
}
|
|
14
|
-
}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: JS Module
|
|
3
|
-
title: fix-lint_rust_yml.mjs
|
|
4
|
-
resource: npm/rules/rust/lint_rust_yml/fix-lint_rust_yml.mjs
|
|
5
|
-
docgen:
|
|
6
|
-
crc: f9900918
|
|
7
|
-
model: openai-codex/gpt-5.4-mini
|
|
8
|
-
tier: cloud-min
|
|
9
|
-
score: 100
|
|
10
|
-
issues: judge:inaccurate:0.99
|
|
11
|
-
judgeModel: openai-codex/gpt-5.4-mini
|
|
12
|
-
---
|
|
13
|
-
|
|
14
|
-
## Огляд
|
|
15
|
-
|
|
16
|
-
Функція `patterns` описує правила для вибірки шляхів і логів, пов’язаних із Rust lint-конфігурацією, зокрема для `lint-rust.yml` та `workflow path filter`. Вона свідомо не охоплює `.github` і `.git`, щоб не зачіпати службові та внутрішні шляхи. Поведінка read-only: лише читає дані й формує результат без запису у ФС чи БД.
|
|
17
|
-
|
|
18
|
-
## Поведінка
|
|
19
|
-
|
|
20
|
-
1. `patterns` формує набір правил для автоматичного виправлення lint-конфігурації Rust.
|
|
21
|
-
2. `patterns` цільово охоплює workflow-файл `.github/workflows/lint-rust.yml`, щоб підтримувати його в узгодженому стані.
|
|
22
|
-
3. `patterns` працює read-only щодо сховища: не змінює ФС чи БД, а лише описує, що саме треба виправити.
|
|
23
|
-
4. `patterns` свідомо не зачіпає `.github` і `.git` як окремі шляхи поза визначеним цільовим файлом.
|
|
24
|
-
|
|
25
|
-
## Гарантії поведінки
|
|
26
|
-
|
|
27
|
-
- Read-only: не виконує операцій запису (ФС/БД).
|
|
28
|
-
- Свідомо пропускає шляхи: `.github`, `.git`.
|
|
@@ -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,79 +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
|
-
# Усі `uses` з канону workflow.
|
|
16
|
-
expected_uses contains u if {
|
|
17
|
-
some step in data.template.snippet.jobs.lint.steps
|
|
18
|
-
u := object.get(step, "uses", "")
|
|
19
|
-
u != ""
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
# Усі `uses` з input workflow.
|
|
23
|
-
actual_uses contains u if {
|
|
24
|
-
some job in object.get(input, "jobs", {})
|
|
25
|
-
some step in object.get(job, "steps", [])
|
|
26
|
-
u := object.get(step, "uses", "")
|
|
27
|
-
u != ""
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
# Конкатенація всіх `run`-кроків з input workflow.
|
|
31
|
-
all_run_text := concat("\n", [run_text |
|
|
32
|
-
some job in object.get(input, "jobs", {})
|
|
33
|
-
some step in object.get(job, "steps", [])
|
|
34
|
-
run_text := step_run_to_text(step)
|
|
35
|
-
])
|
|
36
|
-
|
|
37
|
-
# Крок dtolnay/rust-toolchain@stable має мати with.components з rustfmt і clippy.
|
|
38
|
-
toolchain_step(step) if {
|
|
39
|
-
uses := object.get(step, "uses", "")
|
|
40
|
-
startswith(uses, "dtolnay/rust-toolchain@")
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
deny contains msg if {
|
|
44
|
-
some required_use in expected_uses
|
|
45
|
-
not required_use in actual_uses
|
|
46
|
-
msg := sprintf("lint-rust.yml: відсутній step з `uses: %s` (rust.mdc)", [required_use])
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
deny contains msg if {
|
|
50
|
-
some step in data.template.snippet.jobs.lint.steps
|
|
51
|
-
expected_run := object.get(step, "run", "")
|
|
52
|
-
expected_run != ""
|
|
53
|
-
not contains(all_run_text, expected_run)
|
|
54
|
-
msg := sprintf("lint-rust.yml: жоден крок run не містить %q (rust.mdc)", [expected_run])
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
deny contains msg if {
|
|
58
|
-
msg := "lint-rust.yml: dtolnay/rust-toolchain step потребує with.components: rustfmt, clippy (rust.mdc)"
|
|
59
|
-
some job in object.get(input, "jobs", {})
|
|
60
|
-
some step in object.get(job, "steps", [])
|
|
61
|
-
toolchain_step(step)
|
|
62
|
-
components := object.get(object.get(step, "with", {}), "components", "")
|
|
63
|
-
not contains(components, "rustfmt")
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
deny contains msg if {
|
|
67
|
-
msg := "lint-rust.yml: dtolnay/rust-toolchain step потребує with.components: rustfmt, clippy (rust.mdc)"
|
|
68
|
-
some job in object.get(input, "jobs", {})
|
|
69
|
-
some step in object.get(job, "steps", [])
|
|
70
|
-
toolchain_step(step)
|
|
71
|
-
components := object.get(object.get(step, "with", {}), "components", "")
|
|
72
|
-
not contains(components, "clippy")
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
step_run_to_text(step) := step.run if is_string(step.run)
|
|
76
|
-
|
|
77
|
-
else := concat("\n", [s | some s in step.run]) if is_array(step.run)
|
|
78
|
-
|
|
79
|
-
else := ""
|
|
@@ -1,44 +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
|
-
|
|
20
|
-
concurrency:
|
|
21
|
-
group: ${{ github.ref }}-${{ github.workflow }}
|
|
22
|
-
cancel-in-progress: true
|
|
23
|
-
|
|
24
|
-
jobs:
|
|
25
|
-
lint:
|
|
26
|
-
runs-on: ubuntu-latest
|
|
27
|
-
permissions:
|
|
28
|
-
contents: read
|
|
29
|
-
steps:
|
|
30
|
-
- uses: actions/checkout@v6
|
|
31
|
-
with:
|
|
32
|
-
persist-credentials: false
|
|
33
|
-
|
|
34
|
-
- uses: dtolnay/rust-toolchain@stable
|
|
35
|
-
with:
|
|
36
|
-
components: rustfmt, clippy
|
|
37
|
-
|
|
38
|
-
- uses: Swatinem/rust-cache@v2
|
|
39
|
-
|
|
40
|
-
- name: Rustfmt
|
|
41
|
-
run: cargo fmt --all -- --check
|
|
42
|
-
|
|
43
|
-
- name: Clippy
|
|
44
|
-
run: cargo clippy --all-targets --all-features -- -D warnings
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "https://unpkg.com/@7n/rules/schemas/concern.json",
|
|
3
|
-
"fixability": "config",
|
|
4
|
-
"lint": {
|
|
5
|
-
"scope": "full",
|
|
6
|
-
"glob": [
|
|
7
|
-
".github/workflows/*.yml",
|
|
8
|
-
".github/workflows/*.yaml"
|
|
9
|
-
]
|
|
10
|
-
},
|
|
11
|
-
"requires": {
|
|
12
|
-
"capability": "ci:github"
|
|
13
|
-
}
|
|
14
|
-
}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: JS Module
|
|
3
|
-
title: fix-toolchain_cache.mjs
|
|
4
|
-
resource: npm/rules/rust/toolchain_cache/fix-toolchain_cache.mjs
|
|
5
|
-
docgen:
|
|
6
|
-
crc: ad42b3a8
|
|
7
|
-
model: omlx/gemma-4-e4b-it-OptiQ-4bit
|
|
8
|
-
score: 100
|
|
9
|
-
issues: judge:inaccurate:0.97
|
|
10
|
-
judgeModel: openai-codex/gpt-5.4-mini
|
|
11
|
-
---
|
|
12
|
-
|
|
13
|
-
## Огляд
|
|
14
|
-
|
|
15
|
-
Управляє логікою кешування `Swatinem/rust-cache@v2` у системі. Додає необхідні кроки кешування до робочих процесів через `insertRustCache` та `addCacheWorkspaces`. Визначає шаблони для застосування трансформерів до файлів з конфігураційними порушеннями, використовуючи `patterns`. Забезпечує механізм fail-safe, перехоплюючи помилки без викиду винятків.
|
|
16
|
-
|
|
17
|
-
## Поведінка
|
|
18
|
-
|
|
19
|
-
Поведінка:
|
|
20
|
-
insertRustCache вставляє відсутній крок кешування `Swatinem/rust-cache@v2` після кроків, що використовують `dtolnay/rust-toolchain`, у робочих процесах, якщо це можливо.
|
|
21
|
-
addCacheWorkspaces дописує конфігурацію `with: workspaces: <dir>` до існуючих кроків кешування `Swatinem/rust-cache@v2` у робочих процесах Tauri, якщо вони не містять цієї інформації.
|
|
22
|
-
patterns надає визначення для автоматичного застосування трансформерів до файлів, що містять порушення конфігурації кешування, використовуючи логіку, визначену у файлі.
|
|
23
|
-
|
|
24
|
-
## Публічний API
|
|
25
|
-
|
|
26
|
-
insertRustCache — вставляє інструмент для кешування Rust-засобів одразу після кроку з інструментарієм Rust, якщо в цьому ж завдання немає кроку кешування.
|
|
27
|
-
|
|
28
|
-
addCacheWorkspaces — додає вказування робочих просторів до кожного кроку кешування Tauri-завдання, де ця інформація відсутня.
|
|
29
|
-
|
|
30
|
-
patterns — визначає шаблони, за якими застосовується логіка.
|
|
31
|
-
|
|
32
|
-
## Гарантії поведінки
|
|
33
|
-
|
|
34
|
-
- Перехоплює помилки і не пропускає винятків назовні (fail-safe).
|
|
35
|
-
- Кешує результати в межах одного прогону.
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: Directory Index
|
|
3
|
-
title: npm/rules/rust/toolchain_cache
|
|
4
|
-
resource: npm/rules/rust/toolchain_cache/
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# npm/rules/rust/toolchain_cache
|
|
8
|
-
|
|
9
|
-
| Файл | Тип |
|
|
10
|
-
| ------------------------------------------------- | --------- |
|
|
11
|
-
| [fix-toolchain_cache.mjs](fix-toolchain_cache.md) | JS Module |
|
|
12
|
-
| [main.mjs](main.md) | JS Module |
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: JS Module
|
|
3
|
-
title: main.mjs
|
|
4
|
-
resource: npm/rules/rust/toolchain_cache/main.mjs
|
|
5
|
-
docgen:
|
|
6
|
-
crc: bcb01136
|
|
7
|
-
model: omlx/gemma-4-e4b-it-OptiQ-4bit
|
|
8
|
-
score: 100
|
|
9
|
-
issues: judge:inaccurate:0.99
|
|
10
|
-
judgeModel: openai-codex/gpt-5.4-mini
|
|
11
|
-
---
|
|
12
|
-
|
|
13
|
-
## Огляд
|
|
14
|
-
|
|
15
|
-
Огляд
|
|
16
|
-
Конструкція забезпечує перевірку у `.github/workflows/*.yml` того, що кожен job, що використовує `dtolnay/rust-toolchain@stable` для встановлення Rust toolchain, має подальший крок із кешуванням Rust за допомогою `Swatinem/rust-cache@v2`. Якщо job також виконує `tauri-apps/tauri-action` і `Cargo.toml` лежить у `src-tauri/`, кеш-крок повинен мати `with.workspaces` на цей каталог. Ця логіка контролюється згідно з принципами, описаними у (rust.mdc), використовуючи константи `MISSING_RUST_CACHE` та `MISSING_RUST_CACHE_WORKSPACES` для маркування відхилень.
|
|
17
|
-
|
|
18
|
-
Поведінка
|
|
19
|
-
MISSING_RUST_CACHE — константа-рядок, яка позначає відсутність необхідного кешування Rust toolchain.
|
|
20
|
-
MISSING_RUST_CACHE_WORKSPACES — константа-рядок, що інформує про неправильну конфігурацію кешування для робочих просторів Rust.
|
|
21
|
-
TOOLCHAIN_RE — визначення для ідентифікації кроків встановлення Rust toolchain.
|
|
22
|
-
CACHE_RE — визначення для ідентифікації кроків, що використовують кешування Rust.
|
|
23
|
-
scanToolchainSteps — аналізує вміст YAML-файлу workflow, виявляючи кроки встановлення toolchain та інформацію про кешування в межах одного job-а.
|
|
24
|
-
tauriWorkspaceDir — визначає шлях до робочого простору Tauri, коли `Cargo.toml` не знаходиться в корені репозиторію.
|
|
25
|
-
lint — сканує всі `.yml` та `.yaml` файли у каталозі `.github/workflows`, перевіряючи відповідність вимогам кешування.
|
|
26
|
-
Інструмент працює лише з читанням конфігурацій (Read-only) та здійснює кешування інформації в межах поточного прогону.
|
|
27
|
-
|
|
28
|
-
## Поведінка
|
|
29
|
-
|
|
30
|
-
**Поведінка**
|
|
31
|
-
MISSING_RUST_CACHE — константа, що позначає відсутність необхідного кешування Rust toolchain.
|
|
32
|
-
MISSING_RUST_CACHE_WORKSPACES — константа, що позначає неправильну конфігурацію кешування для робочих просторів Rust.
|
|
33
|
-
TOOLCHAIN_RE — регулярний вираз для ідентифікації кроків, що встановлюють Rust toolchain.
|
|
34
|
-
CACHE_RE — регулярний вираз для ідентифікації кроків, що використовують кешування Rust.
|
|
35
|
-
scanToolchainSteps — аналізує вміст YAML-файлу workflow, виявляючи кроки встановлення toolchain та інформацію про кешування в межах одного job-а.
|
|
36
|
-
tauriWorkspaceDir — визначає шлях до робочого простору Tauri, якщо файл `Cargo.toml` не розташований у корені проєкту.
|
|
37
|
-
lint — сканує всі `.yml` та `.yaml` файли в каталозі `.github/workflows`, перевіряючи, чи присутні необхідні кешування для кроків Rust toolchain, і повідомляє про відхилення. При цьому ігнорує каталоги .github та .git.
|
|
38
|
-
|
|
39
|
-
## Публічний API
|
|
40
|
-
|
|
41
|
-
Understood. As a technical writer adhering to the specified constraints, I will transform the provided list into concise, action-oriented behavioral documentation in Ukrainian, using only bulleted markers ("name — what it does"). I will avoid all introductory/concluding remarks, code blocks, signatures, types, parameters, stdlib mentions, regex descriptions, and internal private names.
|
|
42
|
-
|
|
43
|
-
Here is the rewritten list:
|
|
44
|
-
|
|
45
|
-
* MISSING_RUST_CACHE — Ідентифікатор, що позначає відсутність кешу Rust.
|
|
46
|
-
* MISSING_RUST_CACHE_WORKSPACES — Ідентифікатор, що позначає відсутність кешу для Rust-робочих просторів.
|
|
47
|
-
* TOOLCHAIN_RE — Маркер, що вказує на інструментарій.
|
|
48
|
-
* CACHE_RE — Маркер, що стосується механізму кешування.
|
|
49
|
-
* scanToolchainSteps — Виявляє всі етапи використання `dtolnay/rust-toolchain@…` у workflow-файлі, надаючи деталі про кешування та дії Tauri у відповідних завданнях.
|
|
50
|
-
* tauriWorkspaceDir — Вказує на шлях до Rust-робочого простору для кешування, якщо `Cargo.toml` знаходиться в `src-tauri/`, інакше — не визначений.
|
|
51
|
-
* lint — Здійснює перевірку коду на відповідність встановленим стандартам.
|
|
52
|
-
|
|
53
|
-
## Гарантії поведінки
|
|
54
|
-
|
|
55
|
-
- Read-only: не виконує операцій запису (ФС/БД).
|
|
56
|
-
- Кешує результати в межах одного прогону.
|
|
57
|
-
- Свідомо пропускає шляхи: `.github`, `.git`.
|
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
/** @see ./docs/fix-toolchain_cache.md */
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* T0-autofix для `rust/toolchain_cache` — детерміновано вставляє
|
|
5
|
-
* `Swatinem/rust-cache@v2` одразу після кожного `dtolnay/rust-toolchain@…` кроку,
|
|
6
|
-
* якому його бракує у своєму job-і, і дописує `with.workspaces` у Tauri-job-ах,
|
|
7
|
-
* де Cargo.toml не в корені репо. Текстові splice-и (як `ga/workflows/fix-workflows.mjs`) —
|
|
8
|
-
* зберігають коментарі/формат, мінімальний diff. Ідемпотентно: `scanToolchainSteps`
|
|
9
|
-
* заново перевіряє стан файла на кожному прогоні.
|
|
10
|
-
*/
|
|
11
|
-
import { applyToFiles } from '../../../scripts/utils/apply-to-files.mjs'
|
|
12
|
-
|
|
13
|
-
import { MISSING_RUST_CACHE, MISSING_RUST_CACHE_WORKSPACES, scanToolchainSteps } from './main.mjs'
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Індекс першого рядка після step-блоку, що починається на `stepLine`
|
|
17
|
-
* (dash-колонка `dashCol`) — перший рядок з відступом не більшим за `dashCol`
|
|
18
|
-
* (сусідній крок того самого рівня або dedent), або EOF.
|
|
19
|
-
* @param {string[]} lines усі рядки
|
|
20
|
-
* @param {number} stepLine індекс рядка кроку (`- uses: …`)
|
|
21
|
-
* @param {number} dashCol колонка dash-а кроку
|
|
22
|
-
* @returns {number} індекс вставки (кінець блоку кроку)
|
|
23
|
-
*/
|
|
24
|
-
function stepBlockEnd(lines, stepLine, dashCol) {
|
|
25
|
-
let j = stepLine + 1
|
|
26
|
-
while (j < lines.length) {
|
|
27
|
-
const line = lines[j]
|
|
28
|
-
if (line.trim() !== '' && line.length - line.trimStart().length <= dashCol) break
|
|
29
|
-
j++
|
|
30
|
-
}
|
|
31
|
-
return j
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Вставляє `Swatinem/rust-cache@v2` (з опційним `with.workspaces`) одразу після
|
|
36
|
-
* кожного `dtolnay/rust-toolchain@…` кроку без cache-кроку в тому самому job-і.
|
|
37
|
-
* @param {string} content вміст workflow-файла
|
|
38
|
-
* @param {string} [workspaceDir] відносний шлях workspace-а для `with.workspaces` (опційно)
|
|
39
|
-
* @returns {string|null} новий вміст або null, якщо нічого не змінилось
|
|
40
|
-
*/
|
|
41
|
-
export function insertRustCache(content, workspaceDir) {
|
|
42
|
-
const lines = content.split('\n')
|
|
43
|
-
const missing = scanToolchainSteps(content).filter(s => !s.hasCache)
|
|
44
|
-
if (missing.length === 0) return null
|
|
45
|
-
|
|
46
|
-
/** @type {Array<{ at: number, text: string[] }>} */
|
|
47
|
-
const inserts = []
|
|
48
|
-
for (const step of missing) {
|
|
49
|
-
const at = stepBlockEnd(lines, step.line, step.dashCol)
|
|
50
|
-
const ind = ' '.repeat(step.dashCol)
|
|
51
|
-
const text = [`${ind}- uses: Swatinem/rust-cache@v2`]
|
|
52
|
-
if (workspaceDir && step.jobHasTauriAction) {
|
|
53
|
-
text.push(`${ind} with:`, `${ind} workspaces: ${workspaceDir}`)
|
|
54
|
-
}
|
|
55
|
-
inserts.push({ at, text })
|
|
56
|
-
}
|
|
57
|
-
inserts.sort((a, b) => b.at - a.at) // згори вниз — індекси не зсуваються під час splice
|
|
58
|
-
for (const ins of inserts) lines.splice(ins.at, 0, ...ins.text)
|
|
59
|
-
return lines.join('\n')
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Дописує `with: workspaces: <dir>` у кожен уже наявний `Swatinem/rust-cache@…`
|
|
64
|
-
* крок Tauri-job-а (`tauri-apps/tauri-action`), якому бракує `workspaces`.
|
|
65
|
-
* @param {string} content вміст workflow-файла
|
|
66
|
-
* @param {string} workspaceDir відносний шлях workspace-а
|
|
67
|
-
* @returns {string|null} новий вміст або null, якщо нічого не змінилось
|
|
68
|
-
*/
|
|
69
|
-
export function addCacheWorkspaces(content, workspaceDir) {
|
|
70
|
-
const lines = content.split('\n')
|
|
71
|
-
const targets = scanToolchainSteps(content).filter(s => s.hasCache && s.jobHasTauriAction && !s.cacheHasWorkspaces)
|
|
72
|
-
if (targets.length === 0) return null
|
|
73
|
-
|
|
74
|
-
/** @type {Array<{ at: number, text: string[] }>} */
|
|
75
|
-
const inserts = []
|
|
76
|
-
for (const step of targets) {
|
|
77
|
-
const cacheLine = lines[step.cacheLine]
|
|
78
|
-
const usesCol = cacheLine.indexOf('uses:')
|
|
79
|
-
const ind = ' '.repeat(usesCol)
|
|
80
|
-
const at = stepBlockEnd(lines, step.cacheLine, usesCol - 2)
|
|
81
|
-
inserts.push({ at, text: [`${ind}with:`, `${ind} workspaces: ${workspaceDir}`] })
|
|
82
|
-
}
|
|
83
|
-
inserts.sort((a, b) => b.at - a.at)
|
|
84
|
-
for (const ins of inserts) lines.splice(ins.at, 0, ...ins.text)
|
|
85
|
-
return lines.join('\n')
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/** @type {import('../../../scripts/lib/lint-surface/types.mjs').T0Pattern[]} */
|
|
89
|
-
export const patterns = [
|
|
90
|
-
{
|
|
91
|
-
id: 'rust-toolchain-cache-insert',
|
|
92
|
-
test: violations => violations.some(v => v.data?.kind === MISSING_RUST_CACHE && v.file),
|
|
93
|
-
apply: (violations, ctx) => {
|
|
94
|
-
const targets = violations.filter(v => v.data?.kind === MISSING_RUST_CACHE && v.file)
|
|
95
|
-
const wsTargets = violations.filter(v => v.data?.kind === MISSING_RUST_CACHE_WORKSPACES)
|
|
96
|
-
const workspaceDir = wsTargets.find(v => typeof v.data?.workspaceDir === 'string')?.data?.workspaceDir
|
|
97
|
-
const touchedFiles = applyToFiles(targets, ctx, () => content => insertRustCache(content, workspaceDir))
|
|
98
|
-
return touchedFiles.length > 0
|
|
99
|
-
? { touchedFiles, message: `Swatinem/rust-cache@v2 → ${touchedFiles.length} workflow(s)` }
|
|
100
|
-
: { touchedFiles: [] }
|
|
101
|
-
}
|
|
102
|
-
},
|
|
103
|
-
{
|
|
104
|
-
id: 'rust-toolchain-cache-workspaces',
|
|
105
|
-
test: violations => violations.some(v => v.data?.kind === MISSING_RUST_CACHE_WORKSPACES && v.file),
|
|
106
|
-
apply: (violations, ctx) => {
|
|
107
|
-
const targets = violations.filter(v => v.data?.kind === MISSING_RUST_CACHE_WORKSPACES && v.file)
|
|
108
|
-
const touchedFiles = applyToFiles(targets, ctx, () => content => {
|
|
109
|
-
const workspaceDir = targets.find(v => typeof v.data?.workspaceDir === 'string')?.data?.workspaceDir
|
|
110
|
-
return workspaceDir ? addCacheWorkspaces(content, workspaceDir) : null
|
|
111
|
-
})
|
|
112
|
-
return touchedFiles.length > 0
|
|
113
|
-
? { touchedFiles, message: `with.workspaces → ${touchedFiles.length} workflow(s)` }
|
|
114
|
-
: { touchedFiles: [] }
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
]
|