codelaw-rules-data 0.2.0__py3-none-any.whl
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.
- codelaw_rules_data/LICENSE +23 -0
- codelaw_rules_data/NOTICE +31 -0
- codelaw_rules_data/README.md +130 -0
- codelaw_rules_data/codelaw-pack.toml +6 -0
- codelaw_rules_data/corpus.toml +41 -0
- codelaw_rules_data/data/schemas/github-action.json +1 -0
- codelaw_rules_data/data/schemas/github-workflow.json +1 -0
- codelaw_rules_data/data/schemas/package.json +1 -0
- codelaw_rules_data/data/schemas/pyproject.json +1 -0
- codelaw_rules_data/data/schemas/tsconfig.json +1 -0
- codelaw_rules_data/licenses/SchemaStore-Apache-2.0.txt +202 -0
- codelaw_rules_data/presets/data/conventions.toml +5 -0
- codelaw_rules_data/presets/data/github-actions.toml +6 -0
- codelaw_rules_data/presets/data/package-json.toml +7 -0
- codelaw_rules_data/presets/data/pyproject.toml +6 -0
- codelaw_rules_data/presets/data/recommended.toml +9 -0
- codelaw_rules_data/presets/data/tsconfig.toml +5 -0
- codelaw_rules_data/presets/md/recommended.toml +20 -0
- codelaw_rules_data/rules/json/no-duplicate-keys.cases.md +27 -0
- codelaw_rules_data/rules/json/no-duplicate-keys.md +45 -0
- codelaw_rules_data/rules/json/package-deps-sorted.cases.md +90 -0
- codelaw_rules_data/rules/json/package-deps-sorted.md +54 -0
- codelaw_rules_data/rules/json/package-engines.cases.md +24 -0
- codelaw_rules_data/rules/json/package-engines.md +45 -0
- codelaw_rules_data/rules/json/package-json-schema.md +57 -0
- codelaw_rules_data/rules/json/package-scripts-sorted.cases.md +45 -0
- codelaw_rules_data/rules/json/package-scripts-sorted.md +53 -0
- codelaw_rules_data/rules/json/tsconfig-schema.md +59 -0
- codelaw_rules_data/rules/json/tsconfig-strict.cases.md +57 -0
- codelaw_rules_data/rules/json/tsconfig-strict.md +45 -0
- codelaw_rules_data/rules/md/commands-show-output.cases.md +14 -0
- codelaw_rules_data/rules/md/commands-show-output.md +39 -0
- codelaw_rules_data/rules/md/descriptive-link-text.md +41 -0
- codelaw_rules_data/rules/md/fence-language.md +47 -0
- codelaw_rules_data/rules/md/first-line-heading.cases.md +28 -0
- codelaw_rules_data/rules/md/first-line-heading.md +46 -0
- codelaw_rules_data/rules/md/heading-increment.cases.md +61 -0
- codelaw_rules_data/rules/md/heading-increment.md +46 -0
- codelaw_rules_data/rules/md/link-fragments.cases.md +57 -0
- codelaw_rules_data/rules/md/link-fragments.md +49 -0
- codelaw_rules_data/rules/md/link-image-reference-definitions.cases.md +51 -0
- codelaw_rules_data/rules/md/link-image-reference-definitions.md +40 -0
- codelaw_rules_data/rules/md/no-alt-text.md +47 -0
- codelaw_rules_data/rules/md/no-bare-urls.cases.md +37 -0
- codelaw_rules_data/rules/md/no-bare-urls.md +37 -0
- codelaw_rules_data/rules/md/no-duplicate-heading.cases.md +19 -0
- codelaw_rules_data/rules/md/no-duplicate-heading.md +61 -0
- codelaw_rules_data/rules/md/no-emphasis-as-heading.cases.md +23 -0
- codelaw_rules_data/rules/md/no-emphasis-as-heading.md +49 -0
- codelaw_rules_data/rules/md/no-empty-links.md +50 -0
- codelaw_rules_data/rules/md/no-inline-html.cases.md +13 -0
- codelaw_rules_data/rules/md/no-inline-html.md +45 -0
- codelaw_rules_data/rules/md/no-reversed-links.md +33 -0
- codelaw_rules_data/rules/md/reference-links-images.cases.md +40 -0
- codelaw_rules_data/rules/md/reference-links-images.md +44 -0
- codelaw_rules_data/rules/md/relative-links.md +46 -0
- codelaw_rules_data/rules/md/single-h1.cases.md +29 -0
- codelaw_rules_data/rules/md/single-h1.md +57 -0
- codelaw_rules_data/rules/md/table-column-count.md +43 -0
- codelaw_rules_data/rules/toml/deps-sorted.cases.md +28 -0
- codelaw_rules_data/rules/toml/deps-sorted.md +49 -0
- codelaw_rules_data/rules/toml/no-duplicate-keys.cases.md +43 -0
- codelaw_rules_data/rules/toml/no-duplicate-keys.md +43 -0
- codelaw_rules_data/rules/toml/pyproject-requires-python.cases.md +24 -0
- codelaw_rules_data/rules/toml/pyproject-requires-python.md +41 -0
- codelaw_rules_data/rules/toml/pyproject-schema.md +55 -0
- codelaw_rules_data/rules/yaml/document-start.cases.md +31 -0
- codelaw_rules_data/rules/yaml/document-start.md +36 -0
- codelaw_rules_data/rules/yaml/gha-action-schema.md +59 -0
- codelaw_rules_data/rules/yaml/gha-pin-sha.cases.md +25 -0
- codelaw_rules_data/rules/yaml/gha-pin-sha.md +57 -0
- codelaw_rules_data/rules/yaml/gha-workflow-schema.md +57 -0
- codelaw_rules_data/rules/yaml/no-ambiguous-booleans.cases.md +29 -0
- codelaw_rules_data/rules/yaml/no-ambiguous-booleans.md +43 -0
- codelaw_rules_data/rules/yaml/no-ambiguous-numbers.cases.md +24 -0
- codelaw_rules_data/rules/yaml/no-ambiguous-numbers.md +46 -0
- codelaw_rules_data/rules/yaml/no-duplicate-keys.cases.md +35 -0
- codelaw_rules_data/rules/yaml/no-duplicate-keys.md +43 -0
- codelaw_rules_data/rules/yaml/no-undeclared-alias.cases.md +13 -0
- codelaw_rules_data/rules/yaml/no-undeclared-alias.md +46 -0
- codelaw_rules_data-0.2.0.dist-info/METADATA +140 -0
- codelaw_rules_data-0.2.0.dist-info/RECORD +84 -0
- codelaw_rules_data-0.2.0.dist-info/WHEEL +4 -0
- codelaw_rules_data-0.2.0.dist-info/licenses/LICENSE +23 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: md/table-column-count
|
|
3
|
+
title: "Table rows have as many cells as the header"
|
|
4
|
+
languages: [markdown]
|
|
5
|
+
fix: manual
|
|
6
|
+
fix_reason: "which cell is missing or extra needs the author"
|
|
7
|
+
stability: preview
|
|
8
|
+
ported_from: [markdownlint/MD056]
|
|
9
|
+
since: 0.1.0
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
Every row of a pipe table has the same number of cells as its header row.
|
|
13
|
+
|
|
14
|
+
**Why:** Renderers drop extra cells and leave missing ones empty, so a misplaced pipe silently loses or shifts data.
|
|
15
|
+
|
|
16
|
+
```codelaw
|
|
17
|
+
native: md/table-column-count
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## How to fix
|
|
21
|
+
|
|
22
|
+
1. Compare the row with the header.
|
|
23
|
+
2. Add the missing cells or remove the extra ones, or add a header column if the data needs it.
|
|
24
|
+
|
|
25
|
+
## Examples
|
|
26
|
+
|
|
27
|
+
### Markdown
|
|
28
|
+
|
|
29
|
+
#### Don't
|
|
30
|
+
|
|
31
|
+
````md
|
|
32
|
+
| Name | Type |
|
|
33
|
+
| ---- | ---- |
|
|
34
|
+
| id | number | required |
|
|
35
|
+
````
|
|
36
|
+
|
|
37
|
+
#### Do
|
|
38
|
+
|
|
39
|
+
````md
|
|
40
|
+
| Name | Type | Note |
|
|
41
|
+
| ---- | ---- | ---- |
|
|
42
|
+
| id | number | required |
|
|
43
|
+
````
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# toml/deps-sorted — edge cases
|
|
2
|
+
|
|
3
|
+
### case: optional dependencies
|
|
4
|
+
|
|
5
|
+
```toml
|
|
6
|
+
[project.optional-dependencies]
|
|
7
|
+
test = ["pytest", "Coverage[toml]"]
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
```expect
|
|
11
|
+
2:1 toml/deps-sorted
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
```fixed
|
|
15
|
+
[project.optional-dependencies]
|
|
16
|
+
test = ["Coverage[toml]", "pytest"]
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
### case: names normalised
|
|
20
|
+
|
|
21
|
+
```toml
|
|
22
|
+
[project]
|
|
23
|
+
dependencies = ["typing_extensions", "Typing-Inspect"]
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
```expect
|
|
27
|
+
(none)
|
|
28
|
+
```
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: toml/deps-sorted
|
|
3
|
+
title: "pyproject.toml dependencies are sorted by name"
|
|
4
|
+
languages: [toml]
|
|
5
|
+
files: ["**/pyproject.toml"]
|
|
6
|
+
fix: auto
|
|
7
|
+
stability: preview
|
|
8
|
+
since: 0.1.0
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
The requirement lists in `[project].dependencies` and in each `[project.optional-dependencies]` extra are sorted by package name. Names compare the way pip compares them: case, `-`, `_` and `.` don't matter.
|
|
12
|
+
|
|
13
|
+
**Why:** A sorted list is quicker to scan, shows a duplicate at once and gives smaller diffs; installers don't depend on the order.
|
|
14
|
+
|
|
15
|
+
```codelaw
|
|
16
|
+
native: toml/deps-sorted
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Examples
|
|
20
|
+
|
|
21
|
+
### TOML
|
|
22
|
+
|
|
23
|
+
#### Don't
|
|
24
|
+
|
|
25
|
+
```toml path=pyproject.toml
|
|
26
|
+
[project]
|
|
27
|
+
name = "app"
|
|
28
|
+
dependencies = [
|
|
29
|
+
"requests>=2.31",
|
|
30
|
+
"click>=8",
|
|
31
|
+
"attrs",
|
|
32
|
+
]
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
#### Do
|
|
36
|
+
|
|
37
|
+
```toml path=pyproject.toml
|
|
38
|
+
[project]
|
|
39
|
+
name = "app"
|
|
40
|
+
dependencies = [
|
|
41
|
+
"attrs",
|
|
42
|
+
"click>=8",
|
|
43
|
+
"requests>=2.31",
|
|
44
|
+
]
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Notes
|
|
48
|
+
|
|
49
|
+
A list with comments in it is reported without a fix, because the comments would stay on their lines while the requirements move.
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# toml/no-duplicate-keys — edge cases
|
|
2
|
+
|
|
3
|
+
### case: array of tables repeats its header
|
|
4
|
+
|
|
5
|
+
```toml
|
|
6
|
+
[[bin]]
|
|
7
|
+
name = "a"
|
|
8
|
+
|
|
9
|
+
[[bin]]
|
|
10
|
+
name = "b"
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
```expect
|
|
14
|
+
(none)
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
### case: header after dotted keys
|
|
18
|
+
|
|
19
|
+
```toml
|
|
20
|
+
[tool]
|
|
21
|
+
x.y = 1
|
|
22
|
+
|
|
23
|
+
[tool.x]
|
|
24
|
+
z = 2
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
```expect
|
|
28
|
+
4:2 toml/no-duplicate-keys
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### case: header defined twice
|
|
32
|
+
|
|
33
|
+
```toml
|
|
34
|
+
[a]
|
|
35
|
+
x = 1
|
|
36
|
+
|
|
37
|
+
[a]
|
|
38
|
+
y = 2
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
```expect
|
|
42
|
+
4:2 toml/no-duplicate-keys
|
|
43
|
+
```
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: toml/no-duplicate-keys
|
|
3
|
+
title: "No key or table defined twice in TOML"
|
|
4
|
+
languages: [toml]
|
|
5
|
+
fix: manual
|
|
6
|
+
fix_reason: "which of the two definitions was meant can't be known from the file"
|
|
7
|
+
stability: preview
|
|
8
|
+
since: 0.1.0
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
A key is defined once in its table, and a `[table]` header appears once. That covers dotted keys (`a.b = 1` and then `a = 2`), a table defined both by a header and by dotted keys, and keys inside inline tables.
|
|
12
|
+
|
|
13
|
+
**Why:** TOML forbids defining a key or table twice and conforming parsers refuse the file, so the mistake breaks every tool that reads it.
|
|
14
|
+
|
|
15
|
+
```codelaw
|
|
16
|
+
native: toml/no-duplicate-keys
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## How to fix
|
|
20
|
+
|
|
21
|
+
1. Decide which definition is right.
|
|
22
|
+
2. Delete the other one, or merge the two tables into one.
|
|
23
|
+
|
|
24
|
+
## Examples
|
|
25
|
+
|
|
26
|
+
### TOML
|
|
27
|
+
|
|
28
|
+
#### Don't
|
|
29
|
+
|
|
30
|
+
```toml
|
|
31
|
+
[tool.pytest]
|
|
32
|
+
addopts = "-q"
|
|
33
|
+
testpaths = ["tests"]
|
|
34
|
+
addopts = "-ra"
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
#### Do
|
|
38
|
+
|
|
39
|
+
```toml
|
|
40
|
+
[tool.pytest]
|
|
41
|
+
addopts = "-ra"
|
|
42
|
+
testpaths = ["tests"]
|
|
43
|
+
```
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# toml/pyproject-requires-python — edge cases
|
|
2
|
+
|
|
3
|
+
### case: no [project] table
|
|
4
|
+
|
|
5
|
+
```toml
|
|
6
|
+
[tool.poetry]
|
|
7
|
+
name = "app"
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
```expect
|
|
11
|
+
(none)
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
### case: declared dynamic
|
|
15
|
+
|
|
16
|
+
```toml
|
|
17
|
+
[project]
|
|
18
|
+
name = "app"
|
|
19
|
+
dynamic = ["requires-python", "version"]
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
```expect
|
|
23
|
+
(none)
|
|
24
|
+
```
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: toml/pyproject-requires-python
|
|
3
|
+
title: "pyproject.toml declares requires-python"
|
|
4
|
+
languages: [toml]
|
|
5
|
+
files: ["**/pyproject.toml"]
|
|
6
|
+
fix: suggest
|
|
7
|
+
fix_reason: "the supported Python range is a project decision; the fix inserts the `python` option, which may not be the right range"
|
|
8
|
+
stability: preview
|
|
9
|
+
options:
|
|
10
|
+
python: { type: "string", default: ">=3.11", description: "the range the fix writes into `requires-python`" }
|
|
11
|
+
since: 0.1.0
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
A `pyproject.toml` with a `[project]` table says which Python versions the package supports, in `requires-python`, unless it lists the field in `dynamic`.
|
|
15
|
+
|
|
16
|
+
**Why:** pip uses `requires-python` to pick a release that works on the running interpreter; without it, users on an old Python install a version that then fails at import.
|
|
17
|
+
|
|
18
|
+
```codelaw
|
|
19
|
+
native: toml/pyproject-requires-python
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Examples
|
|
23
|
+
|
|
24
|
+
### TOML
|
|
25
|
+
|
|
26
|
+
#### Don't
|
|
27
|
+
|
|
28
|
+
```toml path=pyproject.toml
|
|
29
|
+
[project]
|
|
30
|
+
name = "app"
|
|
31
|
+
version = "1.0.0"
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
#### Do
|
|
35
|
+
|
|
36
|
+
```toml path=pyproject.toml
|
|
37
|
+
[project]
|
|
38
|
+
name = "app"
|
|
39
|
+
version = "1.0.0"
|
|
40
|
+
requires-python = ">=3.11"
|
|
41
|
+
```
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: toml/pyproject-schema
|
|
3
|
+
title: "pyproject.toml matches its schema"
|
|
4
|
+
languages: [toml]
|
|
5
|
+
files: ["**/pyproject.toml"]
|
|
6
|
+
fix: manual
|
|
7
|
+
fix_reason: "a value the schema rejects is wrong in a way only its author knows how to correct"
|
|
8
|
+
stability: preview
|
|
9
|
+
ported_from: [schemastore/pyproject.json]
|
|
10
|
+
since: 0.1.0
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
A `pyproject.toml` matches SchemaStore's schema for it: `[build-system]` and `[project]` hold the keys PEP 517, PEP 518 and PEP 621 define, each in the form they define.
|
|
14
|
+
|
|
15
|
+
**Why:** Build backends reject or ignore a `[project]` key of the wrong shape — `authors` as a string, `dependencies` as a table — and the error appears only when someone builds the package.
|
|
16
|
+
|
|
17
|
+
```codelaw
|
|
18
|
+
target: $
|
|
19
|
+
assert: { schema: schemas/pyproject }
|
|
20
|
+
message: "$ERROR"
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## How to fix
|
|
24
|
+
|
|
25
|
+
1. Read the message: it names the key and the form the schema expects.
|
|
26
|
+
2. Rewrite the value in that form, or move a tool's setting under `[tool.<name>]`.
|
|
27
|
+
3. Run `codelaw check` on the file again until it is clean.
|
|
28
|
+
|
|
29
|
+
## Examples
|
|
30
|
+
|
|
31
|
+
### TOML
|
|
32
|
+
|
|
33
|
+
#### Don't
|
|
34
|
+
|
|
35
|
+
```toml path=pyproject.toml
|
|
36
|
+
[project]
|
|
37
|
+
name = "app"
|
|
38
|
+
version = "1.0"
|
|
39
|
+
authors = "Ada Lovelace"
|
|
40
|
+
dependencies = { requests = ">=2" }
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
#### Do
|
|
44
|
+
|
|
45
|
+
```toml path=pyproject.toml
|
|
46
|
+
[project]
|
|
47
|
+
name = "app"
|
|
48
|
+
version = "1.0"
|
|
49
|
+
authors = [{ name = "Ada Lovelace" }]
|
|
50
|
+
dependencies = ["requests>=2"]
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Notes
|
|
54
|
+
|
|
55
|
+
The schema is SchemaStore's `pyproject.json` schema, shipped with the pack in `data/schemas/pyproject.json` with its descriptions removed; nothing is fetched. The `[tool.*]` tables whose schemas live in other SchemaStore files (ruff, black, mypy, poetry, setuptools, uv, …) accept any value. TOML dates and times are read as strings.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# yaml/document-start — edge cases
|
|
2
|
+
|
|
3
|
+
### case: comment and directive before the marker
|
|
4
|
+
|
|
5
|
+
```yaml
|
|
6
|
+
# CI settings
|
|
7
|
+
%YAML 1.2
|
|
8
|
+
---
|
|
9
|
+
a: 1
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
```expect
|
|
13
|
+
(none)
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
### case: comment before content
|
|
17
|
+
|
|
18
|
+
```yaml
|
|
19
|
+
# settings
|
|
20
|
+
a: 1
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
```expect
|
|
24
|
+
2:1 yaml/document-start
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
```fixed
|
|
28
|
+
# settings
|
|
29
|
+
---
|
|
30
|
+
a: 1
|
|
31
|
+
```
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: yaml/document-start
|
|
3
|
+
title: "A YAML document starts with ---"
|
|
4
|
+
languages: [yaml]
|
|
5
|
+
exclude: ["**/*.md", "**/*.mdx"]
|
|
6
|
+
fix: auto
|
|
7
|
+
stability: preview
|
|
8
|
+
since: 0.1.0
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
Every YAML document begins with an explicit `---` line. Comments and directives may come before it. Markdown front matter is not checked: its `---` belongs to the Markdown file.
|
|
12
|
+
|
|
13
|
+
**Why:** An explicit start marks where a document begins, so a file can grow to hold several documents, and tools that concatenate YAML files keep the boundaries.
|
|
14
|
+
|
|
15
|
+
```codelaw
|
|
16
|
+
native: yaml/document-start
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Examples
|
|
20
|
+
|
|
21
|
+
### YAML
|
|
22
|
+
|
|
23
|
+
#### Don't
|
|
24
|
+
|
|
25
|
+
```yaml
|
|
26
|
+
name: build
|
|
27
|
+
on: push
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
#### Do
|
|
31
|
+
|
|
32
|
+
```yaml
|
|
33
|
+
---
|
|
34
|
+
name: build
|
|
35
|
+
on: push
|
|
36
|
+
```
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: yaml/gha-action-schema
|
|
3
|
+
title: "GitHub Actions action metadata matches its schema"
|
|
4
|
+
languages: [yaml]
|
|
5
|
+
files: ["**/action.yml", "**/action.yaml"]
|
|
6
|
+
fix: manual
|
|
7
|
+
fix_reason: "a misshapen input or run step has several possible meanings; the author picks the one they intended"
|
|
8
|
+
stability: preview
|
|
9
|
+
ported_from: [schemastore/github-action.json]
|
|
10
|
+
since: 0.1.0
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
An `action.yml` matches SchemaStore's schema for action metadata: `name`, `description` and `runs` are present, and the inputs, outputs and steps have the keys and forms GitHub reads.
|
|
14
|
+
|
|
15
|
+
**Why:** GitHub reads an action's metadata only when a workflow uses it, so a misspelt `steps:` or `using:` breaks every workflow that calls the action, not the action's own repository.
|
|
16
|
+
|
|
17
|
+
```codelaw
|
|
18
|
+
target: $
|
|
19
|
+
assert: { schema: schemas/github-action }
|
|
20
|
+
message: "$ERROR"
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## How to fix
|
|
24
|
+
|
|
25
|
+
1. Read the message: it names the key and what the schema expects.
|
|
26
|
+
2. Add the missing key, or correct the key or the value.
|
|
27
|
+
3. Run `codelaw check` on the file again until it is clean.
|
|
28
|
+
|
|
29
|
+
## Examples
|
|
30
|
+
|
|
31
|
+
### YAML
|
|
32
|
+
|
|
33
|
+
#### Don't
|
|
34
|
+
|
|
35
|
+
```yaml path=action.yml
|
|
36
|
+
name: Setup
|
|
37
|
+
description: Set the toolchain up
|
|
38
|
+
runs:
|
|
39
|
+
using: composite
|
|
40
|
+
step:
|
|
41
|
+
- run: ./setup.sh
|
|
42
|
+
shell: bash
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
#### Do
|
|
46
|
+
|
|
47
|
+
```yaml path=action.yml
|
|
48
|
+
name: Setup
|
|
49
|
+
description: Set the toolchain up
|
|
50
|
+
runs:
|
|
51
|
+
using: composite
|
|
52
|
+
steps:
|
|
53
|
+
- run: ./setup.sh
|
|
54
|
+
shell: bash
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Notes
|
|
58
|
+
|
|
59
|
+
The schema is SchemaStore's `github-action.json` schema, shipped with the pack in `data/schemas/github-action.json` with its descriptions removed; nothing is fetched. `oneOf` is read as `anyOf`.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# yaml/gha-pin-sha — edge cases
|
|
2
|
+
|
|
3
|
+
### case: local action and docker image
|
|
4
|
+
|
|
5
|
+
```yaml
|
|
6
|
+
steps:
|
|
7
|
+
- uses: ./.github/actions/setup
|
|
8
|
+
- uses: docker://alpine:3.20
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
```expect
|
|
12
|
+
(none)
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
### case: reusable workflow on a branch
|
|
16
|
+
|
|
17
|
+
```yaml
|
|
18
|
+
jobs:
|
|
19
|
+
call:
|
|
20
|
+
uses: octo/repo/.github/workflows/ci.yml@main
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
```expect
|
|
24
|
+
3:11 yaml/gha-pin-sha
|
|
25
|
+
```
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: yaml/gha-pin-sha
|
|
3
|
+
title: "GitHub Actions are pinned to a commit SHA"
|
|
4
|
+
languages: [yaml]
|
|
5
|
+
files: ["**/.github/workflows/*.yml", "**/.github/workflows/*.yaml", "**/action.yml", "**/action.yaml"]
|
|
6
|
+
fix: manual
|
|
7
|
+
fix_reason: "finding the commit a tag points to needs the network, and the engine never uses it (L5)"
|
|
8
|
+
stability: preview
|
|
9
|
+
since: 0.1.0
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
A `uses:` in a GitHub Actions workflow or composite action names a full 40-character commit SHA, not a tag or branch. Local actions (`./…`) and `docker://` images are not checked.
|
|
13
|
+
|
|
14
|
+
**Why:** A tag or branch can be moved to different code at any time, so a compromised or careless upstream changes what your workflow runs; a commit SHA can't change.
|
|
15
|
+
|
|
16
|
+
```codelaw
|
|
17
|
+
match:
|
|
18
|
+
kind: flow_node
|
|
19
|
+
regex: "@"
|
|
20
|
+
inside:
|
|
21
|
+
kind: block_mapping_pair
|
|
22
|
+
has: { field: key, regex: '^uses$' }
|
|
23
|
+
all:
|
|
24
|
+
- not: { regex: '@[0-9a-fA-F]{40}' }
|
|
25
|
+
- not: { regex: '^[''"]?(\./|docker://)' }
|
|
26
|
+
message: "Pin `$$MATCH` to a full commit SHA; a tag or branch can be moved to other code"
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## How to fix
|
|
30
|
+
|
|
31
|
+
1. Look up the commit the tag points to, for example with `git ls-remote https://github.com/<owner>/<repo> <tag>`.
|
|
32
|
+
2. Replace the tag with the 40-character SHA and keep the tag as a comment: `uses: actions/checkout@<sha> # v4.2.2`.
|
|
33
|
+
3. Let Dependabot or Renovate update the pinned SHAs.
|
|
34
|
+
|
|
35
|
+
## Examples
|
|
36
|
+
|
|
37
|
+
### YAML
|
|
38
|
+
|
|
39
|
+
#### Don't
|
|
40
|
+
|
|
41
|
+
```yaml path=.github/workflows/ci.yml
|
|
42
|
+
jobs:
|
|
43
|
+
test:
|
|
44
|
+
runs-on: ubuntu-latest
|
|
45
|
+
steps:
|
|
46
|
+
- uses: actions/checkout@v4
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
#### Do
|
|
50
|
+
|
|
51
|
+
```yaml path=.github/workflows/ci.yml
|
|
52
|
+
jobs:
|
|
53
|
+
test:
|
|
54
|
+
runs-on: ubuntu-latest
|
|
55
|
+
steps:
|
|
56
|
+
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
|
57
|
+
```
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: yaml/gha-workflow-schema
|
|
3
|
+
title: "GitHub Actions workflows match their schema"
|
|
4
|
+
languages: [yaml]
|
|
5
|
+
files: ["**/.github/workflows/*.yml", "**/.github/workflows/*.yaml"]
|
|
6
|
+
fix: manual
|
|
7
|
+
fix_reason: "a misshapen job or step has several possible meanings; the author picks the one they intended"
|
|
8
|
+
stability: preview
|
|
9
|
+
ported_from: [schemastore/github-workflow.json]
|
|
10
|
+
since: 0.1.0
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
A GitHub Actions workflow matches SchemaStore's schema for workflows: every key of a trigger, a job and a step is one GitHub reads, with a value of the form it takes.
|
|
14
|
+
|
|
15
|
+
**Why:** GitHub rejects a malformed workflow only when it is pushed, and a misspelt key such as `runs_on` or `timeout-minute` fails the whole workflow file, so the mistake shows up as a red run instead of in review.
|
|
16
|
+
|
|
17
|
+
```codelaw
|
|
18
|
+
target: $
|
|
19
|
+
assert: { schema: schemas/github-workflow }
|
|
20
|
+
message: "$ERROR"
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## How to fix
|
|
24
|
+
|
|
25
|
+
1. Read the message: it names the key and what the schema expects, and suggests the key meant when the name is misspelt.
|
|
26
|
+
2. Correct the key or the value.
|
|
27
|
+
3. Run `codelaw check` on the file again until it is clean.
|
|
28
|
+
|
|
29
|
+
## Examples
|
|
30
|
+
|
|
31
|
+
### YAML
|
|
32
|
+
|
|
33
|
+
#### Don't
|
|
34
|
+
|
|
35
|
+
```yaml path=.github/workflows/ci.yml
|
|
36
|
+
on: push
|
|
37
|
+
jobs:
|
|
38
|
+
test:
|
|
39
|
+
runs_on: ubuntu-latest
|
|
40
|
+
steps:
|
|
41
|
+
- run: npm test
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
#### Do
|
|
45
|
+
|
|
46
|
+
```yaml path=.github/workflows/ci.yml
|
|
47
|
+
on: push
|
|
48
|
+
jobs:
|
|
49
|
+
test:
|
|
50
|
+
runs-on: ubuntu-latest
|
|
51
|
+
steps:
|
|
52
|
+
- run: npm test
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Notes
|
|
56
|
+
|
|
57
|
+
The schema is SchemaStore's `github-workflow.json` schema, shipped with the pack in `data/schemas/github-workflow.json` with its descriptions removed; nothing is fetched. YAML is read as YAML 1.2, as GitHub reads it, so `on:` is a key. `oneOf` is read as `anyOf`.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# yaml/no-ambiguous-booleans — edge cases
|
|
2
|
+
|
|
3
|
+
### case: GitHub Actions trigger key
|
|
4
|
+
|
|
5
|
+
```yaml
|
|
6
|
+
on:
|
|
7
|
+
push:
|
|
8
|
+
branches: [main]
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
```expect
|
|
12
|
+
(none)
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
### case: quoted and sequence values
|
|
16
|
+
|
|
17
|
+
```yaml
|
|
18
|
+
a: "yes"
|
|
19
|
+
b: [on, 'off']
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
```expect
|
|
23
|
+
2:5 yaml/no-ambiguous-booleans
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
```fixed
|
|
27
|
+
a: "yes"
|
|
28
|
+
b: ["on", 'off']
|
|
29
|
+
```
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: yaml/no-ambiguous-booleans
|
|
3
|
+
title: "No yes/no/on/off as unquoted values"
|
|
4
|
+
languages: [yaml]
|
|
5
|
+
fix: suggest
|
|
6
|
+
fix_reason: "quoting keeps the YAML 1.2 meaning (a string); if a boolean was meant, write `true` or `false` instead"
|
|
7
|
+
stability: preview
|
|
8
|
+
since: 0.1.0
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
A value is not a bare `yes`, `no`, `on` or `off` (in any of their capitalisations). Quote it if it is text, or write `true` or `false` if it is a boolean. Keys are not checked, so a GitHub Actions `on:` is fine.
|
|
12
|
+
|
|
13
|
+
**Why:** YAML 1.2 reads these words as strings, but YAML 1.1 loaders, still common (PyYAML, Ruby's Psych, many tools built on them), read them as booleans: `country: no` becomes `false`.
|
|
14
|
+
|
|
15
|
+
```codelaw
|
|
16
|
+
native: yaml/no-ambiguous-booleans
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Examples
|
|
20
|
+
|
|
21
|
+
### YAML
|
|
22
|
+
|
|
23
|
+
#### Don't
|
|
24
|
+
|
|
25
|
+
```yaml
|
|
26
|
+
country: no
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
#### Do
|
|
30
|
+
|
|
31
|
+
```yaml
|
|
32
|
+
country: "no"
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
#### Do
|
|
36
|
+
|
|
37
|
+
```yaml
|
|
38
|
+
enabled: true
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Differences from the source
|
|
42
|
+
|
|
43
|
+
The idea comes from the YAML 1.1 and 1.2 specifications. `y` and `n` are not reported: the YAML 1.1 type repository lists them, but the common 1.1 loaders don't treat them as booleans.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# yaml/no-ambiguous-numbers — edge cases
|
|
2
|
+
|
|
3
|
+
### case: plain numbers and times that are not base 60
|
|
4
|
+
|
|
5
|
+
```yaml
|
|
6
|
+
a: 0
|
|
7
|
+
b: 10:75
|
|
8
|
+
c: 0:30
|
|
9
|
+
d: 1.5
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
```expect
|
|
13
|
+
(none)
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
### case: negative leading zero
|
|
17
|
+
|
|
18
|
+
```yaml
|
|
19
|
+
offset: -010
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
```expect
|
|
23
|
+
1:9 yaml/no-ambiguous-numbers
|
|
24
|
+
```
|