pyossmtool 0.0.1__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.
- pyossmtool/__init__.py +3 -0
- pyossmtool/bundle/catalog/checks/bandit.scan.yaml +13 -0
- pyossmtool/bundle/catalog/checks/codespell.spelling.yaml +12 -0
- pyossmtool/bundle/catalog/checks/deadcode.scan.yaml +13 -0
- pyossmtool/bundle/catalog/checks/gate.acronym-allowlist.yaml +14 -0
- pyossmtool/bundle/catalog/checks/gate.folder-breadth.yaml +14 -0
- pyossmtool/bundle/catalog/checks/gate.module-private-vars.yaml +14 -0
- pyossmtool/bundle/catalog/checks/gate.module-size.yaml +14 -0
- pyossmtool/bundle/catalog/checks/gitleaks.secrets.yaml +21 -0
- pyossmtool/bundle/catalog/checks/hadolint.dockerfile.yaml +16 -0
- pyossmtool/bundle/catalog/checks/jscpd.duplication.yaml +19 -0
- pyossmtool/bundle/catalog/checks/markdownlint.check.yaml +17 -0
- pyossmtool/bundle/catalog/checks/mdformat.apply.yaml +10 -0
- pyossmtool/bundle/catalog/checks/mdformat.format.yaml +14 -0
- pyossmtool/bundle/catalog/checks/mutmut.run.yaml +13 -0
- pyossmtool/bundle/catalog/checks/pydeps.cycles.yaml +14 -0
- pyossmtool/bundle/catalog/checks/pytest.coverage.yaml +19 -0
- pyossmtool/bundle/catalog/checks/pytest.test.yaml +14 -0
- pyossmtool/bundle/catalog/checks/radon.cc.yaml +13 -0
- pyossmtool/bundle/catalog/checks/radon.mi.yaml +13 -0
- pyossmtool/bundle/catalog/checks/ruff.format.apply.yaml +11 -0
- pyossmtool/bundle/catalog/checks/ruff.format.yaml +14 -0
- pyossmtool/bundle/catalog/checks/ruff.lint.yaml +15 -0
- pyossmtool/bundle/catalog/checks/ruff.unused.yaml +17 -0
- pyossmtool/bundle/catalog/checks/semgrep.scan.yaml +18 -0
- pyossmtool/bundle/catalog/checks/shellcheck.yaml +13 -0
- pyossmtool/bundle/catalog/checks/shfmt.apply.yaml +11 -0
- pyossmtool/bundle/catalog/checks/shfmt.format.yaml +14 -0
- pyossmtool/bundle/catalog/checks/sourcery.review.yaml +14 -0
- pyossmtool/bundle/catalog/checks/ty.check.yaml +15 -0
- pyossmtool/bundle/catalog/checks/vulture.scan.yaml +16 -0
- pyossmtool/bundle/catalog/checks/yamlfmt.apply.yaml +10 -0
- pyossmtool/bundle/catalog/checks/yamlfmt.format.yaml +14 -0
- pyossmtool/bundle/catalog/checks/yamllint.check.yaml +16 -0
- pyossmtool/bundle/catalog/tools/bandit.yaml +20 -0
- pyossmtool/bundle/catalog/tools/codespell.yaml +17 -0
- pyossmtool/bundle/catalog/tools/deadcode.yaml +13 -0
- pyossmtool/bundle/catalog/tools/gitleaks.yaml +9 -0
- pyossmtool/bundle/catalog/tools/hadolint.yaml +11 -0
- pyossmtool/bundle/catalog/tools/jscpd.yaml +15 -0
- pyossmtool/bundle/catalog/tools/markdownlint.yaml +18 -0
- pyossmtool/bundle/catalog/tools/mdformat.yaml +13 -0
- pyossmtool/bundle/catalog/tools/mutmut.yaml +10 -0
- pyossmtool/bundle/catalog/tools/pydeps.yaml +10 -0
- pyossmtool/bundle/catalog/tools/pytest.yaml +12 -0
- pyossmtool/bundle/catalog/tools/radon.yaml +10 -0
- pyossmtool/bundle/catalog/tools/ruff.yaml +26 -0
- pyossmtool/bundle/catalog/tools/script.yaml +8 -0
- pyossmtool/bundle/catalog/tools/semgrep.yaml +21 -0
- pyossmtool/bundle/catalog/tools/shellcheck.yaml +10 -0
- pyossmtool/bundle/catalog/tools/shfmt.yaml +13 -0
- pyossmtool/bundle/catalog/tools/sourcery.yaml +10 -0
- pyossmtool/bundle/catalog/tools/ty.yaml +20 -0
- pyossmtool/bundle/catalog/tools/vulture.yaml +13 -0
- pyossmtool/bundle/catalog/tools/yamlfmt.yaml +24 -0
- pyossmtool/bundle/catalog/tools/yamllint.yaml +24 -0
- pyossmtool/bundle/defaults/allowlists/acronyms.yaml +10 -0
- pyossmtool/bundle/defaults/allowlists/folder-breadth.txt +1 -0
- pyossmtool/bundle/defaults/allowlists/module-private-vars.txt +1 -0
- pyossmtool/bundle/defaults/allowlists/module-size.txt +1 -0
- pyossmtool/bundle/defaults/configs/bandit.yaml +5 -0
- pyossmtool/bundle/defaults/configs/gates/acronym-allowlist.yaml +4 -0
- pyossmtool/bundle/defaults/configs/gates/folder-breadth.yaml +12 -0
- pyossmtool/bundle/defaults/configs/gates/module-private-vars.yaml +4 -0
- pyossmtool/bundle/defaults/configs/gates/module-size.yaml +6 -0
- pyossmtool/bundle/defaults/configs/markdownlint.json +8 -0
- pyossmtool/bundle/defaults/configs/ruff.toml +8 -0
- pyossmtool/bundle/defaults/configs/ty.toml +5 -0
- pyossmtool/bundle/defaults/configs/yamlfmt.yaml +4 -0
- pyossmtool/bundle/defaults/configs/yamllint.yaml +12 -0
- pyossmtool/bundle/defaults/gates/README.md +150 -0
- pyossmtool/bundle/defaults/gates/acronym-allowlist.sh +15 -0
- pyossmtool/bundle/defaults/gates/folder-breadth.sh +22 -0
- pyossmtool/bundle/defaults/gates/lib.sh +116 -0
- pyossmtool/bundle/defaults/gates/module-private-vars.sh +77 -0
- pyossmtool/bundle/defaults/gates/module-size.sh +60 -0
- pyossmtool/bundle/defaults/semgrep/python-quality.yml +19 -0
- pyossmtool/bundle/suites/demo.yaml +11 -0
- pyossmtool/bundle/suites/extended.yaml +34 -0
- pyossmtool/bundle/suites/format.yaml +10 -0
- pyossmtool/bundle/suites/formatting.yaml +10 -0
- pyossmtool/bundle/suites/policy.yaml +11 -0
- pyossmtool/bundle/suites/python-quality.yaml +9 -0
- pyossmtool/bundle/suites/reslab-parity.yaml +41 -0
- pyossmtool/bundle/suites/standard.yaml +45 -0
- pyossmtool/cli.py +233 -0
- pyossmtool/config_resolver.py +117 -0
- pyossmtool/discovery.py +50 -0
- pyossmtool/gate_config.py +119 -0
- pyossmtool/gates.py +102 -0
- pyossmtool/ignore.py +270 -0
- pyossmtool/ignore_materialize.py +184 -0
- pyossmtool/installer.py +119 -0
- pyossmtool/models.py +279 -0
- pyossmtool/parsers/__init__.py +76 -0
- pyossmtool/parsers/analysis.py +329 -0
- pyossmtool/parsers/base.py +29 -0
- pyossmtool/parsers/common.py +57 -0
- pyossmtool/parsers/format_text.py +67 -0
- pyossmtool/parsers/gates.py +92 -0
- pyossmtool/parsers/patterns.py +78 -0
- pyossmtool/parsers/prose.py +193 -0
- pyossmtool/parsers/ruff.py +103 -0
- pyossmtool/parsers/shell.py +83 -0
- pyossmtool/policy/__init__.py +0 -0
- pyossmtool/policy/acronym_allowlist.py +322 -0
- pyossmtool/policy/folder_breadth.py +306 -0
- pyossmtool/registry.py +72 -0
- pyossmtool/reporter.py +87 -0
- pyossmtool/resolver.py +146 -0
- pyossmtool/runner.py +482 -0
- pyossmtool/runner_script.py +131 -0
- pyossmtool/target_expand.py +112 -0
- pyossmtool-0.0.1.dist-info/METADATA +94 -0
- pyossmtool-0.0.1.dist-info/RECORD +119 -0
- pyossmtool-0.0.1.dist-info/WHEEL +5 -0
- pyossmtool-0.0.1.dist-info/entry_points.txt +2 -0
- pyossmtool-0.0.1.dist-info/licenses/LICENSE +21 -0
- pyossmtool-0.0.1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
id: pytest
|
|
2
|
+
name: pytest
|
|
3
|
+
description: Python test runner with optional coverage via pytest-cov plugin.
|
|
4
|
+
install:
|
|
5
|
+
method: pip
|
|
6
|
+
package: pytest>=8.0 pytest-cov>=6.0
|
|
7
|
+
binary: pytest
|
|
8
|
+
documentation_url: https://docs.pytest.org/
|
|
9
|
+
ignore:
|
|
10
|
+
kind: flag_pairs
|
|
11
|
+
flag: --ignore
|
|
12
|
+
files: []
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
id: ruff
|
|
2
|
+
name: Ruff
|
|
3
|
+
description: Fast Python linter and formatter.
|
|
4
|
+
install:
|
|
5
|
+
method: pip
|
|
6
|
+
package: ruff>=0.15.0
|
|
7
|
+
binary: ruff
|
|
8
|
+
documentation_url: https://docs.astral.sh/ruff/
|
|
9
|
+
config:
|
|
10
|
+
flag: --config
|
|
11
|
+
bundled: ruff.toml
|
|
12
|
+
repo_files:
|
|
13
|
+
- ruff.toml
|
|
14
|
+
pyproject:
|
|
15
|
+
- tool
|
|
16
|
+
- ruff
|
|
17
|
+
ignore:
|
|
18
|
+
kind: config_overlay
|
|
19
|
+
format: toml
|
|
20
|
+
file: ruff.toml
|
|
21
|
+
flag: --config
|
|
22
|
+
key: extend-exclude
|
|
23
|
+
extend_from: base_or_pyproject
|
|
24
|
+
extend_key: extend
|
|
25
|
+
files:
|
|
26
|
+
- '**/*.py'
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
id: semgrep
|
|
2
|
+
name: Semgrep
|
|
3
|
+
description: Static analysis for security and code quality patterns.
|
|
4
|
+
install:
|
|
5
|
+
method: pip
|
|
6
|
+
package: semgrep>=1.79.0
|
|
7
|
+
binary: semgrep
|
|
8
|
+
documentation_url: https://semgrep.dev/
|
|
9
|
+
config:
|
|
10
|
+
flag: --config
|
|
11
|
+
bundled_path: defaults/semgrep/python-quality.yml
|
|
12
|
+
pass_flag: false
|
|
13
|
+
repo_dirs:
|
|
14
|
+
- .semgrep
|
|
15
|
+
- .tools/semgrep
|
|
16
|
+
ignore:
|
|
17
|
+
kind: flag_pairs
|
|
18
|
+
flag: --exclude
|
|
19
|
+
post_subcommand: true
|
|
20
|
+
files:
|
|
21
|
+
- '**/*.py'
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
id: shfmt
|
|
2
|
+
name: shfmt
|
|
3
|
+
description: Shell script formatter (via shfmt-py).
|
|
4
|
+
install:
|
|
5
|
+
method: pip
|
|
6
|
+
package: shfmt-py>=4.0.0
|
|
7
|
+
binary: shfmt
|
|
8
|
+
documentation_url: https://github.com/mvdan/sh
|
|
9
|
+
config:
|
|
10
|
+
repo_files:
|
|
11
|
+
- .editorconfig
|
|
12
|
+
files:
|
|
13
|
+
- '**/*.{sh,bash,ksh,zsh}'
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
id: ty
|
|
2
|
+
name: ty
|
|
3
|
+
description: Astral static type checker for Python.
|
|
4
|
+
install:
|
|
5
|
+
method: pip
|
|
6
|
+
package: ty>=0.0.50
|
|
7
|
+
binary: ty
|
|
8
|
+
documentation_url: https://docs.astral.sh/ty/
|
|
9
|
+
config:
|
|
10
|
+
flag: --config-file
|
|
11
|
+
bundled: ty.toml
|
|
12
|
+
pyproject:
|
|
13
|
+
- tool
|
|
14
|
+
- ty
|
|
15
|
+
ignore:
|
|
16
|
+
kind: flag_pairs
|
|
17
|
+
flag: --exclude
|
|
18
|
+
post_subcommand: true
|
|
19
|
+
files:
|
|
20
|
+
- "**/*.py"
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
id: vulture
|
|
2
|
+
name: Vulture
|
|
3
|
+
description: Find dead Python code with high confidence.
|
|
4
|
+
install:
|
|
5
|
+
method: pip
|
|
6
|
+
package: vulture>=2.14
|
|
7
|
+
binary: vulture
|
|
8
|
+
documentation_url: https://github.com/jendrikseipp/vulture
|
|
9
|
+
ignore:
|
|
10
|
+
kind: prefix
|
|
11
|
+
prefix: --exclude=
|
|
12
|
+
files:
|
|
13
|
+
- '**/*.py'
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
id: yamlfmt
|
|
2
|
+
name: yamlfmt
|
|
3
|
+
description: YAML formatter and linter from Google.
|
|
4
|
+
install:
|
|
5
|
+
method: system
|
|
6
|
+
package: yamlfmt
|
|
7
|
+
binary: yamlfmt
|
|
8
|
+
documentation_url: https://github.com/google/yamlfmt
|
|
9
|
+
config:
|
|
10
|
+
flag: -conf
|
|
11
|
+
bundled: yamlfmt.yaml
|
|
12
|
+
repo_files:
|
|
13
|
+
- .yamlfmt.yaml
|
|
14
|
+
- .yamlfmt.yml
|
|
15
|
+
- yamlfmt.yaml
|
|
16
|
+
ignore:
|
|
17
|
+
kind: config_overlay
|
|
18
|
+
format: yaml
|
|
19
|
+
file: yamlfmt.yaml
|
|
20
|
+
flag: -conf
|
|
21
|
+
key: exclude
|
|
22
|
+
key_style: list
|
|
23
|
+
files:
|
|
24
|
+
- '**/*.{yml,yaml}'
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
id: yamllint
|
|
2
|
+
name: yamllint
|
|
3
|
+
description: YAML syntax and style linter.
|
|
4
|
+
install:
|
|
5
|
+
method: pip
|
|
6
|
+
package: yamllint>=1.38.0
|
|
7
|
+
binary: yamllint
|
|
8
|
+
documentation_url: https://yamllint.readthedocs.io/
|
|
9
|
+
config:
|
|
10
|
+
flag: -c
|
|
11
|
+
bundled: yamllint.yaml
|
|
12
|
+
repo_files:
|
|
13
|
+
- .yamllint
|
|
14
|
+
- .yamllint.yaml
|
|
15
|
+
- .yamllint.yml
|
|
16
|
+
ignore:
|
|
17
|
+
kind: config_overlay
|
|
18
|
+
format: yaml
|
|
19
|
+
file: yamllint.yaml
|
|
20
|
+
flag: -c
|
|
21
|
+
key: ignore
|
|
22
|
+
key_style: block
|
|
23
|
+
files:
|
|
24
|
+
- '**/*.{yml,yaml}'
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Directory paths exempt from folder breadth limits (repo-relative).
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# One repo-relative file path per line (whole-file exemption).
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# One repo-relative path per line (optional). Lines starting with # are ignored.
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
# Script gates
|
|
2
|
+
|
|
3
|
+
Shell-based policy checks integrated with pyossmtool failure reports.
|
|
4
|
+
|
|
5
|
+
## Bundled policy gates
|
|
6
|
+
|
|
7
|
+
| Check | Script | Config |
|
|
8
|
+
| -------------------------- | --------------------------------------- | ------------------------------------------------- |
|
|
9
|
+
| `gate.module-size` | `defaults/gates/module-size.sh` | `defaults/configs/gates/module-size.yaml` |
|
|
10
|
+
| `gate.module-private-vars` | `defaults/gates/module-private-vars.sh` | `defaults/configs/gates/module-private-vars.yaml` |
|
|
11
|
+
| `gate.folder-breadth` | `defaults/gates/folder-breadth.sh` | `defaults/configs/gates/folder-breadth.yaml` |
|
|
12
|
+
| `gate.acronym-allowlist` | `defaults/gates/acronym-allowlist.sh` | `defaults/configs/gates/acronym-allowlist.yaml` |
|
|
13
|
+
|
|
14
|
+
Run via suite `policy` or as part of `standard`.
|
|
15
|
+
|
|
16
|
+
### Configure per repo
|
|
17
|
+
|
|
18
|
+
Each gate check declares where config lives (see `config:` on `catalog/checks/gate.*.yaml`):
|
|
19
|
+
|
|
20
|
+
```yaml
|
|
21
|
+
config:
|
|
22
|
+
bundled: gates/module-size.yaml
|
|
23
|
+
project_file: .pyossmtool/configs/gates/gate.module-size.yaml
|
|
24
|
+
allowlist_bundled: module-size.txt
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Resolution order: `configs.mode: paths` override → `project_file` if present → `bundled` under `defaults/configs/`.
|
|
28
|
+
|
|
29
|
+
Override bundled defaults by adding the project file:
|
|
30
|
+
|
|
31
|
+
```yaml
|
|
32
|
+
# .pyossmtool/configs/gates/gate.module-size.yaml
|
|
33
|
+
scan_roots:
|
|
34
|
+
- src/myapp
|
|
35
|
+
- scripts
|
|
36
|
+
portfolio_max_lines: 800
|
|
37
|
+
new_file_max_lines: 400
|
|
38
|
+
base_branch: main
|
|
39
|
+
allowlist_file: .pyossmtool/allowlists/module-size.txt
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Or set explicit paths in `pyossmtool.yaml`:
|
|
43
|
+
|
|
44
|
+
```yaml
|
|
45
|
+
configs:
|
|
46
|
+
mode: paths
|
|
47
|
+
paths:
|
|
48
|
+
gate.module-size: .pyossmtool/configs/gates/gate.module-size.yaml
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Config keys are exported to gate scripts as `GATE_<KEY>` environment variables (lists become space-separated).
|
|
52
|
+
|
|
53
|
+
## Quick start (custom gate)
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
pyossmtool gate init module-size --description "Cap Python module line counts"
|
|
57
|
+
# edit .pyossmtool/gates/module-size.sh
|
|
58
|
+
# add to pyossmtool.yaml checks: - id: gate.module-size
|
|
59
|
+
pyossmtool run --check gate.module-size --target src/
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Layout
|
|
63
|
+
|
|
64
|
+
```text
|
|
65
|
+
.pyossmtool/
|
|
66
|
+
gates/ # your bash scripts
|
|
67
|
+
module-size.sh
|
|
68
|
+
catalog/
|
|
69
|
+
checks/ # gate.<name>.yaml registrations
|
|
70
|
+
gate.module-size.yaml
|
|
71
|
+
reports/ # structured JSON written by lib.sh (gitignore this)
|
|
72
|
+
gate.module-size.json
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Project catalog entries **override** bundled checks with the same id.
|
|
76
|
+
|
|
77
|
+
## Gate script contract
|
|
78
|
+
|
|
79
|
+
1. Source `defaults/gates/lib.sh` via `pyossmtool gates lib-path`
|
|
80
|
+
1. Call `gate_init "<name>"`
|
|
81
|
+
1. Use `gate_fail` / `gate_warn` for findings
|
|
82
|
+
1. Call `gate_finish` (exits 0 on pass, 1 on fail)
|
|
83
|
+
|
|
84
|
+
### Environment (set by runner)
|
|
85
|
+
|
|
86
|
+
| Variable | Meaning |
|
|
87
|
+
| --------------------------- | ------------------------------------------------------------ |
|
|
88
|
+
| `PYOSSMTOOL_ROOT` | Repository root |
|
|
89
|
+
| `PYOSSMTOOL_TARGET` | Resolved scan target for this check |
|
|
90
|
+
| `PYOSSMTOOL_CHECK_ID` | Catalog check id |
|
|
91
|
+
| `PYOSSMTOOL_REPORT` | Path to write structured JSON findings |
|
|
92
|
+
| `PYOSSMTOOL_IGNORE_PROFILES` | Newline-separated ignore profile files (`.gitignore` syntax) |
|
|
93
|
+
| `PYOSSMTOOL_IGNORE_PATHS` | Newline-separated repo-relative paths/globs to skip |
|
|
94
|
+
|
|
95
|
+
Use `gate_path_ignored "<repo-relative-path>"` in bash gates to skip ignored files.
|
|
96
|
+
|
|
97
|
+
### Structured output
|
|
98
|
+
|
|
99
|
+
`gate_fail` / `gate_warn` append to `PYOSSMTOOL_REPORT`:
|
|
100
|
+
|
|
101
|
+
```json
|
|
102
|
+
{
|
|
103
|
+
"findings": [
|
|
104
|
+
{
|
|
105
|
+
"rule_id": "module-size",
|
|
106
|
+
"severity": "error",
|
|
107
|
+
"message": "src/foo.py has 1200 lines (cap 1000)",
|
|
108
|
+
"location": { "file": "src/foo.py", "line": 1 }
|
|
109
|
+
}
|
|
110
|
+
]
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
On failure, pyossmtool normalizes this into `FailureReport` v1 under `reports/failures/`.
|
|
115
|
+
|
|
116
|
+
### Legacy scripts (no lib)
|
|
117
|
+
|
|
118
|
+
Existing bash gates that print `FAIL ...` lines still work when registered with `parser: script_text`.
|
|
119
|
+
|
|
120
|
+
## Catalog entry
|
|
121
|
+
|
|
122
|
+
```yaml
|
|
123
|
+
id: gate.module-size
|
|
124
|
+
tool: script
|
|
125
|
+
name: Module Size Gate
|
|
126
|
+
description: Enforce per-file line limits.
|
|
127
|
+
script: .pyossmtool/gates/module-size.sh
|
|
128
|
+
parser: gate_json
|
|
129
|
+
output_file: .pyossmtool/reports/gate.module-size.json
|
|
130
|
+
argv: []
|
|
131
|
+
success:
|
|
132
|
+
exit_codes: [0]
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Optional `argv` entries are passed after the script path; use `{target}` and `{cov}` placeholders.
|
|
136
|
+
|
|
137
|
+
## Wrapping existing reslab gates
|
|
138
|
+
|
|
139
|
+
Keep `bin/gates/module-size-check.sh` as-is and register it:
|
|
140
|
+
|
|
141
|
+
```yaml
|
|
142
|
+
id: gate.module-size
|
|
143
|
+
tool: script
|
|
144
|
+
name: Module Size Gate
|
|
145
|
+
script: bin/gates/module-size-check.sh
|
|
146
|
+
parser: script_text
|
|
147
|
+
argv: []
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
Use `parser: gate_json` after migrating the script to call `gate_fail` / `gate_finish`.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Documented-acronym gate for contributor-facing prose.
|
|
3
|
+
set -euo pipefail
|
|
4
|
+
|
|
5
|
+
# shellcheck source=/dev/null
|
|
6
|
+
source "$(pyossmtool gates lib-path)"
|
|
7
|
+
|
|
8
|
+
gate_init "acronym-allowlist"
|
|
9
|
+
|
|
10
|
+
CONFIG="${PYOSSMTOOL_GATE_CONFIG:?PYOSSMTOOL_GATE_CONFIG is required}"
|
|
11
|
+
ROOT="${PYOSSMTOOL_ROOT:?PYOSSMTOOL_ROOT is required}"
|
|
12
|
+
REPORT="${PYOSSMTOOL_REPORT:?PYOSSMTOOL_REPORT is required}"
|
|
13
|
+
|
|
14
|
+
"${PYOSSMTOOL_PYTHON:?PYOSSMTOOL_PYTHON is required}" -m pyossmtool.policy.acronym_allowlist --root "${ROOT}" --config "${CONFIG}" --report "${REPORT}"
|
|
15
|
+
exit $?
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Folder breadth gate — caps direct sibling file counts per directory.
|
|
3
|
+
set -euo pipefail
|
|
4
|
+
|
|
5
|
+
# shellcheck source=/dev/null
|
|
6
|
+
source "$(pyossmtool gates lib-path)"
|
|
7
|
+
|
|
8
|
+
gate_init "folder-breadth"
|
|
9
|
+
|
|
10
|
+
CONFIG="${PYOSSMTOOL_GATE_CONFIG:?PYOSSMTOOL_GATE_CONFIG is required}"
|
|
11
|
+
ROOT="${PYOSSMTOOL_ROOT:?PYOSSMTOOL_ROOT is required}"
|
|
12
|
+
REPORT="${PYOSSMTOOL_REPORT:?PYOSSMTOOL_REPORT is required}"
|
|
13
|
+
|
|
14
|
+
ARGS=(--root "${ROOT}" --config "${CONFIG}" --report "${REPORT}")
|
|
15
|
+
if [[ ${GATE_STRICT:-1} == "1" ]]; then
|
|
16
|
+
ARGS+=(--strict)
|
|
17
|
+
else
|
|
18
|
+
ARGS+=(--advisory)
|
|
19
|
+
fi
|
|
20
|
+
|
|
21
|
+
"${PYOSSMTOOL_PYTHON:?PYOSSMTOOL_PYTHON is required}" -m pyossmtool.policy.folder_breadth "${ARGS[@]}"
|
|
22
|
+
exit $?
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# pyossmtool script-gate helper library.
|
|
3
|
+
# Source from project gates: source "$(pyossmtool gates lib-path)"
|
|
4
|
+
set -euo pipefail
|
|
5
|
+
|
|
6
|
+
gate_init() {
|
|
7
|
+
GATE_NAME="${1:-script-gate}"
|
|
8
|
+
GATE_FINDING_COUNT=0
|
|
9
|
+
if [[ -z "${PYOSSMTOOL_REPORT:-}" ]]; then
|
|
10
|
+
echo "gate_init: PYOSSMTOOL_REPORT is not set (pyossmtool runner should set this)" >&2
|
|
11
|
+
exit 2
|
|
12
|
+
fi
|
|
13
|
+
mkdir -p "$(dirname "${PYOSSMTOOL_REPORT}")"
|
|
14
|
+
printf '%s\n' '{"findings":[]}' >"${PYOSSMTOOL_REPORT}"
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
_gate_append_finding() {
|
|
18
|
+
local rule_id="$1"
|
|
19
|
+
local severity="$2"
|
|
20
|
+
local message="$3"
|
|
21
|
+
local file="${4:-}"
|
|
22
|
+
local line="${5:-}"
|
|
23
|
+
python3 - "${PYOSSMTOOL_REPORT}" "${rule_id}" "${severity}" "${message}" "${file}" "${line}" <<'PY'
|
|
24
|
+
import json
|
|
25
|
+
import sys
|
|
26
|
+
from pathlib import Path
|
|
27
|
+
|
|
28
|
+
report_path, rule_id, severity, message, file, line = sys.argv[1:7]
|
|
29
|
+
payload = json.loads(Path(report_path).read_text(encoding="utf-8"))
|
|
30
|
+
finding = {
|
|
31
|
+
"rule_id": rule_id,
|
|
32
|
+
"severity": severity,
|
|
33
|
+
"message": message,
|
|
34
|
+
}
|
|
35
|
+
if file:
|
|
36
|
+
location = {"file": file}
|
|
37
|
+
if line:
|
|
38
|
+
try:
|
|
39
|
+
location["line"] = int(line)
|
|
40
|
+
except ValueError:
|
|
41
|
+
pass
|
|
42
|
+
finding["location"] = location
|
|
43
|
+
payload.setdefault("findings", []).append(finding)
|
|
44
|
+
Path(report_path).write_text(json.dumps(payload, indent=2) + "\n", encoding="utf-8")
|
|
45
|
+
PY
|
|
46
|
+
GATE_FINDING_COUNT=$((GATE_FINDING_COUNT + 1))
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
gate_fail() {
|
|
50
|
+
local rule_id="${1:-gate}"
|
|
51
|
+
local message="${2:-gate failed}"
|
|
52
|
+
local file="${3:-}"
|
|
53
|
+
local line="${4:-}"
|
|
54
|
+
_gate_append_finding "${rule_id}" "error" "${message}" "${file}" "${line}"
|
|
55
|
+
echo "FAIL ${rule_id}: ${message}" >&2
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
gate_warn() {
|
|
59
|
+
local rule_id="${1:-gate}"
|
|
60
|
+
local message="${2:-gate warning}"
|
|
61
|
+
local file="${3:-}"
|
|
62
|
+
local line="${4:-}"
|
|
63
|
+
_gate_append_finding "${rule_id}" "warning" "${message}" "${file}" "${line}"
|
|
64
|
+
echo "WARN ${rule_id}: ${message}" >&2
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
gate_path_ignored() {
|
|
68
|
+
local rel_path="${1#./}"
|
|
69
|
+
"${PYOSSMTOOL_PYTHON:-python3}" - "${rel_path}" <<'PY'
|
|
70
|
+
import fnmatch
|
|
71
|
+
import os
|
|
72
|
+
import sys
|
|
73
|
+
from pathlib import Path
|
|
74
|
+
|
|
75
|
+
try:
|
|
76
|
+
import pathspec
|
|
77
|
+
except ImportError:
|
|
78
|
+
pathspec = None
|
|
79
|
+
|
|
80
|
+
rel = sys.argv[1].replace("\\", "/").lstrip("./")
|
|
81
|
+
patterns: list[str] = [
|
|
82
|
+
p.strip() for p in os.environ.get("PYOSSMTOOL_IGNORE_PATHS", "").splitlines() if p.strip()
|
|
83
|
+
]
|
|
84
|
+
for profile in os.environ.get("PYOSSMTOOL_IGNORE_PROFILES", "").splitlines():
|
|
85
|
+
path = Path(profile.strip())
|
|
86
|
+
if not path.is_file():
|
|
87
|
+
continue
|
|
88
|
+
for line in path.read_text(encoding="utf-8").splitlines():
|
|
89
|
+
stripped = line.strip()
|
|
90
|
+
if stripped and not stripped.startswith("#") and not stripped.startswith("!"):
|
|
91
|
+
patterns.append(stripped)
|
|
92
|
+
|
|
93
|
+
if not patterns:
|
|
94
|
+
raise SystemExit(1)
|
|
95
|
+
|
|
96
|
+
if pathspec is not None:
|
|
97
|
+
matcher = pathspec.PathSpec.from_lines("gitignore", patterns)
|
|
98
|
+
raise SystemExit(0 if matcher.match_file(rel) else 1)
|
|
99
|
+
|
|
100
|
+
for pattern in patterns:
|
|
101
|
+
normalized = pattern.rstrip("/")
|
|
102
|
+
if rel == normalized or rel.startswith(f"{normalized}/"):
|
|
103
|
+
raise SystemExit(0)
|
|
104
|
+
if "*" in pattern and fnmatch.fnmatch(rel, pattern):
|
|
105
|
+
raise SystemExit(0)
|
|
106
|
+
raise SystemExit(1)
|
|
107
|
+
PY
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
gate_finish() {
|
|
111
|
+
if ((GATE_FINDING_COUNT > 0)); then
|
|
112
|
+
echo "gate '${GATE_NAME}' failed with ${GATE_FINDING_COUNT} finding(s)" >&2
|
|
113
|
+
exit 1
|
|
114
|
+
fi
|
|
115
|
+
exit 0
|
|
116
|
+
}
|