pre-commit-bigfix 2.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.
- pre_commit_bigfix/__init__.py +3 -0
- pre_commit_bigfix/bes_actionscript_lint_schclass.py +937 -0
- pre_commit_bigfix/bes_actionscript_validate_prefetch.py +1258 -0
- pre_commit_bigfix/bes_actionscript_validate_script.py +2871 -0
- pre_commit_bigfix/bes_common.py +271 -0
- pre_commit_bigfix/bes_conventions_check.py +3484 -0
- pre_commit_bigfix/bes_relevance_convert_group.py +407 -0
- pre_commit_bigfix/bes_relevance_lint.py +402 -0
- pre_commit_bigfix/bes_schema_validate.py +84 -0
- pre_commit_bigfix/bes_siterepo_validate_layout.py +1203 -0
- pre_commit_bigfix/run_all.py +305 -0
- pre_commit_bigfix/schclass.py +284 -0
- pre_commit_bigfix/schclass_data/ExpandedActionScript.schclass +412 -0
- pre_commit_bigfix/schclass_data/bigfix_overrides.schclass +43 -0
- pre_commit_bigfix/schclass_tokenizer.py +321 -0
- pre_commit_bigfix-2.0.1.dist-info/METADATA +821 -0
- pre_commit_bigfix-2.0.1.dist-info/RECORD +21 -0
- pre_commit_bigfix-2.0.1.dist-info/WHEEL +5 -0
- pre_commit_bigfix-2.0.1.dist-info/entry_points.txt +10 -0
- pre_commit_bigfix-2.0.1.dist-info/licenses/LICENSE +21 -0
- pre_commit_bigfix-2.0.1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,821 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pre-commit-bigfix
|
|
3
|
+
Version: 2.0.1
|
|
4
|
+
Summary: pre-commit hooks for BigFix content
|
|
5
|
+
Home-page: https://github.com/jgstew/pre-commit-bigfix
|
|
6
|
+
Author: JGStew
|
|
7
|
+
Author-email: noreply@jgstew.com
|
|
8
|
+
Project-URL: Bug Tracker, https://github.com/jgstew/pre-commit-bigfix/issues
|
|
9
|
+
Project-URL: Source, https://github.com/jgstew/pre-commit-bigfix
|
|
10
|
+
Keywords: pre-commit hooks python bigfix bes
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
19
|
+
Classifier: Operating System :: OS Independent
|
|
20
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
21
|
+
Classifier: Intended Audience :: Developers
|
|
22
|
+
Requires-Python: >=3.8
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
License-File: LICENSE
|
|
25
|
+
Requires-Dist: bigfix_prefetch>=1.1.5
|
|
26
|
+
Requires-Dist: lxml
|
|
27
|
+
Requires-Dist: validate_bes_xml<3,>=2.4.1
|
|
28
|
+
Requires-Dist: bigfix-relevance-analyzer<2,>=1.23.1; python_version >= "3.11"
|
|
29
|
+
Provides-Extra: test
|
|
30
|
+
Requires-Dist: pytest; extra == "test"
|
|
31
|
+
Dynamic: license-file
|
|
32
|
+
|
|
33
|
+
# pre-commit-bigfix
|
|
34
|
+
|
|
35
|
+
pre commit hooks for BigFix content
|
|
36
|
+
|
|
37
|
+
Moved from [pre-commit-jgstew](https://github.com/jgstew/pre-commit-jgstew).
|
|
38
|
+
|
|
39
|
+
## Usage
|
|
40
|
+
|
|
41
|
+
Add this to your `.pre-commit-config.yaml`:
|
|
42
|
+
|
|
43
|
+
```yaml
|
|
44
|
+
repos:
|
|
45
|
+
- repo: https://github.com/jgstew/pre-commit-bigfix
|
|
46
|
+
rev: v2.0.0
|
|
47
|
+
hooks:
|
|
48
|
+
- id: bes-schema-validate
|
|
49
|
+
- id: bes-conventions-check
|
|
50
|
+
- id: bes-actionscript-lint-schclass
|
|
51
|
+
- id: bes-actionscript-validate-prefetch
|
|
52
|
+
- id: bes-actionscript-validate-script
|
|
53
|
+
- id: bes-relevance-lint
|
|
54
|
+
- id: bes-relevance-convert-group
|
|
55
|
+
# only in a Git External Custom Site (repository site) repo:
|
|
56
|
+
- id: bes-siterepo-validate-layout
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
The hooks were renamed to a consistent `bes-<aspect>-<action>` scheme in
|
|
60
|
+
v0.3.0. The deprecated aliases for the previous ids (`validate-bes`,
|
|
61
|
+
`check-bes-conventions`) have since been removed, along with the console
|
|
62
|
+
scripts of the same names: a config using them now fails with pre-commit's
|
|
63
|
+
"hook id not found" error. Use `bes-schema-validate` and
|
|
64
|
+
`bes-conventions-check` instead.
|
|
65
|
+
|
|
66
|
+
## Run without pre-commit
|
|
67
|
+
|
|
68
|
+
The `pre-commit-bigfix` command runs every hook over a folder, without
|
|
69
|
+
pre-commit or a git commit:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
uvx --from git+https://github.com/jgstew/pre-commit-bigfix pre-commit-bigfix
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Once the package is on PyPI, this is just `uvx pre-commit-bigfix`. Give one or
|
|
76
|
+
more files or folders to check (default: the current folder). Each hook gets
|
|
77
|
+
the files its `files` pattern matches, with its default `args`, and a summary
|
|
78
|
+
line per hook is printed at the end. The exit code is 1 if any hook fails, and
|
|
79
|
+
2 for a path that does not exist or a bad option.
|
|
80
|
+
|
|
81
|
+
- It is **read-only**. Under pre-commit several hooks fix files in place; here
|
|
82
|
+
each is run with `--auto-fix=no` (or `--check` for
|
|
83
|
+
`bes-relevance-convert-group` and `bes-siterepo-validate-layout`), so
|
|
84
|
+
fixable problems are reported, not fixed. Run a hook directly, or use
|
|
85
|
+
pre-commit, to apply fixes.
|
|
86
|
+
- Hidden folders (a name starting with `.`, or the hidden flag on macOS and
|
|
87
|
+
Windows) are not searched; pass `--include-hidden` to search them.
|
|
88
|
+
`__pycache__` and `node_modules` are never searched. A folder named on the
|
|
89
|
+
command line is always searched.
|
|
90
|
+
- Symlinked files found while searching are skipped, as pre-commit skips
|
|
91
|
+
them. A file named on the command line that no hook checks is reported.
|
|
92
|
+
- `bes-siterepo-validate-layout` runs once in each git repo that holds a given
|
|
93
|
+
path, and is skipped when none does.
|
|
94
|
+
- `--skip HOOK` (repeatable) leaves a hook out.
|
|
95
|
+
|
|
96
|
+
## Hooks
|
|
97
|
+
|
|
98
|
+
### bes-schema-validate
|
|
99
|
+
|
|
100
|
+
Validates that BigFix XML files are well-formed and satisfy their schema, via
|
|
101
|
+
the [validate_bes_xml](https://pypi.org/project/validate-bes-xml/) package
|
|
102
|
+
(`>= 2.4.1`). It checks these files:
|
|
103
|
+
|
|
104
|
+
| Files | Root tag | Schema |
|
|
105
|
+
|---|---|---|
|
|
106
|
+
| `*.bes` | `<BES>` | `BES.xsd` |
|
|
107
|
+
| `*.ojo` | any | `BESOJO.xsd` |
|
|
108
|
+
| `siteConfig.xml` (Git External Custom Site) | `<SiteConfig>` | `SiteConfig.xsd` |
|
|
109
|
+
| `site.xml` (Git External Custom Site) | `<Site>` | `Site.xsd` |
|
|
110
|
+
| `digest.xml` (Git External Custom Site) | `<Digest>` | `Digest.xsd` |
|
|
111
|
+
| `Signatures/*.xml` (BigFix Inventory signatures) | `<SoftwareIdentityCatalog>` | `SoftwareIdentityCatalog.xsd` |
|
|
112
|
+
|
|
113
|
+
The file names only decide which files the hook sees. Apart from `.ojo`
|
|
114
|
+
files, which always use `BESOJO.xsd`, the schema is picked by the root tag:
|
|
115
|
+
the bundled schema with the same name, ignoring case. So a `digest.xml` whose
|
|
116
|
+
root is `<SiteConfig>` is checked against `SiteConfig.xsd`, and a `.bes` file
|
|
117
|
+
whose root is `<BESAPI>` against `BESAPI.xsd`.
|
|
118
|
+
|
|
119
|
+
The hook's `files` pattern is:
|
|
120
|
+
|
|
121
|
+
```text
|
|
122
|
+
\.(bes|ojo)$|(^|/)(siteConfig|site|digest)\.xml$|(^|/)Signatures/[^/]+\.xml$
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
The `.xml` names are matched case-sensitively, as BigFix documents them, and
|
|
126
|
+
only signature files directly inside a `Signatures/` folder are matched. Keep
|
|
127
|
+
signatures elsewhere? Set `files:` in your own config.
|
|
128
|
+
|
|
129
|
+
Only the schemas bundled with validate_bes_xml are used. A `*.xsd` in the
|
|
130
|
+
repo (a copy of `site.xsd` from RepositorySiteExample, say) is ignored, so a
|
|
131
|
+
`.bes` file whose root tag has no bundled schema fails here as it would
|
|
132
|
+
anywhere else.
|
|
133
|
+
|
|
134
|
+
A `.xml` file that is not a BigFix file, such as a sitemap or a Maven site
|
|
135
|
+
descriptor named `site.xml`, has no bundled schema for its root tag and is
|
|
136
|
+
skipped. An Eclipse update-site `site.xml` is the exception: its root is a
|
|
137
|
+
plain `<site>`, which matches `Site.xsd` (schema names match without regard
|
|
138
|
+
to case), so it is validated and fails. If your repo holds Eclipse update
|
|
139
|
+
sites, exclude them:
|
|
140
|
+
|
|
141
|
+
```yaml
|
|
142
|
+
- id: bes-schema-validate
|
|
143
|
+
exclude: ^eclipse/.*site\.xml$
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
Files that pass print nothing. Each error is printed as `path:line: message`,
|
|
147
|
+
or `path: message` when there is no line number, and the exit code is the
|
|
148
|
+
number of files that failed:
|
|
149
|
+
|
|
150
|
+
```text
|
|
151
|
+
Sites/Foo/siteConfig.xml:4: Element 'BesFileDir': This element is not expected. Expected is one of ( NonClientFilesDir, OtherFilesDir ).
|
|
152
|
+
Sites/Foo/Fixlets/A/digest.xml:4: Element 'DigestRelevanceEvaluationPeriod': [facet 'enumeration'] The value 'PT10M' is not an element of the set {...}.
|
|
153
|
+
unknown.bes: no schema to validate this file against
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Renamed from `validate-bes`, whose deprecated alias has been removed.
|
|
157
|
+
|
|
158
|
+
### bes-conventions-check
|
|
159
|
+
|
|
160
|
+
Picky, opinionated content checks + auto-fixes for BigFix BES files that the
|
|
161
|
+
BES.xsd schema (`bes-schema-validate`) cannot express: ActionScript MIMEType,
|
|
162
|
+
value formats for SourceReleaseDate / x-fixlet-modification-time / DownloadSize /
|
|
163
|
+
action-ui-metadata / CPE-2.3 / CVENames / x-relevance-evaluation-period,
|
|
164
|
+
prefetch-line shape (URL schemes overridable with `--prefetch-url-schemes`)
|
|
165
|
+
and https URLs, CDATA usage, blank-line and
|
|
166
|
+
trailing-whitespace spacing, empty ActionScript, dynamic download statements,
|
|
167
|
+
a UTF-8 XML declaration, Title placeholders / whitespace / TODO markers,
|
|
168
|
+
non-trivial non-empty Relevance with no stray whitespace, unique MIMEField
|
|
169
|
+
names, unique Analysis Property names/IDs, unique Action IDs, action link text
|
|
170
|
+
free of empty-substitution gaps, SuccessCriteria body/Option consistency, a
|
|
171
|
+
SourceSeverity vocabulary (default Low/Moderate/Important/High/Critical,
|
|
172
|
+
overridable with `--severity-values`; `Unspecified` is auto-fixed to empty), description placeholders / empty
|
|
173
|
+
descriptions, a Description `<script>` block free of `//` line comments
|
|
174
|
+
(lost when the file is converted to FXF, since Description newlines are
|
|
175
|
+
collapsed), and Task/Fixlet release-date / modification-time presence and order
|
|
176
|
+
(a SourceReleaseDate later than the modification time warns `W219`), and a
|
|
177
|
+
`DownloadSize` that does not match the prefetches' total (`W220`, only when
|
|
178
|
+
that total is knowable), and a Relevance that waits for a client setting value
|
|
179
|
+
the action never sets (`W221`).
|
|
180
|
+
|
|
181
|
+
Auto-fixes the fixable ones in place and exits 1 when anything was fixed so
|
|
182
|
+
the change is reviewed and re-staged. Only rewrites whose right answer is
|
|
183
|
+
knowable from the file are made: besides the whitespace, CDATA, date-insert
|
|
184
|
+
and XML-declaration fixes, a missing ActionScript MIMEType gets the
|
|
185
|
+
Windows-Shell default (`E200`), an unambiguous year-first SourceReleaseDate
|
|
186
|
+
or a loosely-formatted timestamp is respelled (`E201`/`E202`/`E216` - a wrong
|
|
187
|
+
day-of-week is dropped, not recomputed), a `cve-` prefix is uppercased
|
|
188
|
+
(`E209`, several `<CVENames>` are not merged), an evaluation period is
|
|
189
|
+
zero-padded (`E219`), a case-only SourceSeverity mismatch is respelled
|
|
190
|
+
(`W216`), and a DownloadSize that disagrees with a knowable prefetch total is
|
|
191
|
+
set to it (`W220`). E-codes fail the hook; pass `--strict`
|
|
192
|
+
to also fail on warnings, or `--errors-only` to leave W-codes out of the report
|
|
193
|
+
entirely (the checks and their auto-fixes still run, unlike `--disable`).
|
|
194
|
+
`--check-filename` (off by default) additionally checks that a file's
|
|
195
|
+
basename matches its first content object's Title. Unparsable files are
|
|
196
|
+
skipped (`bes-schema-validate` owns validity).
|
|
197
|
+
|
|
198
|
+
Renamed from `check-bes-conventions`, whose deprecated alias has been
|
|
199
|
+
removed. The file-level opt-out marker moved with it, from `pre-commit-skip:
|
|
200
|
+
bes-conventions` to `pre-commit-skip: bes-conventions-check`.
|
|
201
|
+
|
|
202
|
+
See the docstring in
|
|
203
|
+
[bes_conventions_check.py](https://github.com/jgstew/pre-commit-bigfix/blob/main/pre_commit_bigfix/bes_conventions_check.py)
|
|
204
|
+
for the full list of check codes, opt-out markers, and options.
|
|
205
|
+
|
|
206
|
+
Auto-fixes are checked against BES.xsd in three groups: all the per-block
|
|
207
|
+
fixes together, the trailing-whitespace strip, and the XML declaration. A
|
|
208
|
+
group that would turn a schema-valid file into an invalid one is not written
|
|
209
|
+
and is reported as `E222`; the other groups still are (`--disable E222` writes
|
|
210
|
+
it anyway). Because the per-block fixes are one group, one bad block fix holds
|
|
211
|
+
back every block fix in the file.
|
|
212
|
+
|
|
213
|
+
### bes-actionscript-lint-schclass
|
|
214
|
+
|
|
215
|
+
Lints every `<ActionScript>` body in BES files against the BigFix console's
|
|
216
|
+
own lexical grammar: the vendored
|
|
217
|
+
[ExpandedActionScript.schclass](https://github.com/jgstew/pre-commit-bigfix/blob/main/pre_commit_bigfix/schclass_data/ExpandedActionScript.schclass)
|
|
218
|
+
(the lex schema the console's editor uses, 323 command verbs) merged with a
|
|
219
|
+
[small override file](https://github.com/jgstew/pre-commit-bigfix/blob/main/pre_commit_bigfix/schclass_data/bigfix_overrides.schclass)
|
|
220
|
+
of validation corrections the display grammar needs.
|
|
221
|
+
|
|
222
|
+
The rule: the first token of every line must be a known command verb, a `//`
|
|
223
|
+
comment, a `{...}` relevance substitution, a continuation, or the line must be
|
|
224
|
+
blank (E300; the message quotes the whole offending line and, when the
|
|
225
|
+
grammar narrows it to a handful of known commands, offers a `did you mean` --
|
|
226
|
+
e.g. `action log commands` suggests `action log command`). A `{...}`
|
|
227
|
+
substitution must close before line end (E301), and a
|
|
228
|
+
`createfile until <MARKER>` block must reach its bare marker line (E302; the
|
|
229
|
+
block's raw content is excluded from linting). An `override run` / `override
|
|
230
|
+
wait` line opens a block whose following `keyword=value` lines are options
|
|
231
|
+
rather than commands, checked against the
|
|
232
|
+
[documented keywords and values](https://developer.bigfix.com/action-script/reference/execution/override.html)
|
|
233
|
+
(E303) -- a value in `{...}` is a relevance substitution and is accepted
|
|
234
|
+
unchecked. Verbs match case-insensitively but a non-lowercase verb warns
|
|
235
|
+
(W302), an override option keyword or value that is not lowercase warns (W303),
|
|
236
|
+
and an unbalanced `"` warns (W301). ActionScript has no escape character, so
|
|
237
|
+
`"C:\Bes\"` is a closed string; only a `regset`/`regset64` value, which uses
|
|
238
|
+
`.reg`-file syntax, treats `\"` as an escaped quote, and `appendfile` content
|
|
239
|
+
is raw file text that is not checked.
|
|
240
|
+
Only `application/x-Fixlet-Windows-Shell` (or missing-MIMEType) bodies are
|
|
241
|
+
BigFix ActionScript and are linted; `x-sh`, `x-AppleScript`,
|
|
242
|
+
`x-Fixlet-Windows-PowerShell`, and `text/x-uri` bodies are other languages and
|
|
243
|
+
are skipped. E-codes fail the hook; pass `--strict` to also fail on warnings.
|
|
244
|
+
Unparsable files are skipped (`bes-schema-validate` owns validity). Non-`.bes`
|
|
245
|
+
paths passed explicitly are linted as raw ActionScript text, so you can widen the
|
|
246
|
+
hook's `files` pattern to cover standalone ActionScript files.
|
|
247
|
+
|
|
248
|
+
The underlying schclass loader ([schclass.py](https://github.com/jgstew/pre-commit-bigfix/blob/main/pre_commit_bigfix/schclass.py))
|
|
249
|
+
and tokenizer engine
|
|
250
|
+
([schclass_tokenizer.py](https://github.com/jgstew/pre-commit-bigfix/blob/main/pre_commit_bigfix/schclass_tokenizer.py)) are
|
|
251
|
+
generic: point them at any `.schclass` file and they lex that language.
|
|
252
|
+
|
|
253
|
+
This hook's scope is deliberately limited to what the schclass grammar can
|
|
254
|
+
decide - the lexical validity of each line. ActionScript checks that need
|
|
255
|
+
knowledge the grammar does not carry (per-verb argument shapes, `if`/`endif`
|
|
256
|
+
and prefetch-block pairing, the `]]></ActionScript>` closing-tag whitespace
|
|
257
|
+
trap, http->https escalation, and any content-changing auto-fixes) belong in
|
|
258
|
+
a separate ActionScript hook, so this one stays a thin consumer of the grammar
|
|
259
|
+
files and needs no code changes when BigFix ships new command verbs. Its one
|
|
260
|
+
auto-fix changes only case: `--auto-fix` (on by default when files are given,
|
|
261
|
+
as pre-commit does) lowercases a `W302` verb or `W303` override option in
|
|
262
|
+
place, and an auto-fixed file fails the hook so it is reviewed and re-staged;
|
|
263
|
+
`args: ["--auto-fix", "no"]` reports them without rewriting.
|
|
264
|
+
|
|
265
|
+
See the docstring in
|
|
266
|
+
[bes_actionscript_lint_schclass.py](https://github.com/jgstew/pre-commit-bigfix/blob/main/pre_commit_bigfix/bes_actionscript_lint_schclass.py)
|
|
267
|
+
for the full list of check codes, opt-out markers, and options.
|
|
268
|
+
|
|
269
|
+
The case fixes are checked against BES.xsd together. If they would turn a
|
|
270
|
+
schema-valid file into an invalid one, none of them are written and `E304` is
|
|
271
|
+
reported (`--disable E304` writes them anyway).
|
|
272
|
+
|
|
273
|
+
### bes-actionscript-validate-prefetch
|
|
274
|
+
|
|
275
|
+
Validates every prefetch line in every `<ActionScript>` body with
|
|
276
|
+
`validate_prefetch()` from the
|
|
277
|
+
[bigfix_prefetch](https://pypi.org/project/bigfix-prefetch/) package, which is
|
|
278
|
+
the reference implementation of what a valid prefetch is. Both spellings are
|
|
279
|
+
covered:
|
|
280
|
+
|
|
281
|
+
```text
|
|
282
|
+
prefetch <name> sha1:<40> size:<n> <url> sha256:<64>
|
|
283
|
+
add prefetch item name=<name> sha1=<40> size=<n> url=<url> sha256=<64>
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
A line that fails validation is `E400`, carrying the reason `bigfix_prefetch`
|
|
287
|
+
reported: a missing size or a size that is not > 0, a hash of the wrong
|
|
288
|
+
length, or a line that could not be parsed at all.
|
|
289
|
+
|
|
290
|
+
A missing sha256 is `E401`. `bigfix_prefetch` calls sha256 optional unless
|
|
291
|
+
asked, but in 2026 it is treated as mandatory here. It gets its own code
|
|
292
|
+
rather than being folded into `E400` so that a repo which still wants it
|
|
293
|
+
optional can turn just that off:
|
|
294
|
+
|
|
295
|
+
```yaml
|
|
296
|
+
- id: bes-actionscript-validate-prefetch
|
|
297
|
+
args: ["--disable", "E401"]
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
A prefetch block item with no sha1 warns (`W402`); a prefetch *statement* with
|
|
301
|
+
no sha1 warns (`W405`) instead of failing the line - current BigFix clients
|
|
302
|
+
accept a statement with sha256 alone, so this is unusual but valid. A
|
|
303
|
+
declared name whose extension differs from the extension of the URL's file
|
|
304
|
+
warns (`W406`) - e.g. `<sha1>.msi` fetched from `ccsetup531.exe` - since the
|
|
305
|
+
extension decides how the file is run or unpacked. An extension is a trailing
|
|
306
|
+
`.` plus 1-4 characters including a letter; names or URLs without one, and
|
|
307
|
+
server-side script URLs such as `download.php`, are not compared, and a URL
|
|
308
|
+
that is the declared name with one more extension appended (`7z.dll.txt`, a
|
|
309
|
+
way past web filtering) counts as a match. Text the prefetch syntax does not
|
|
310
|
+
define is `E403` - a stray token (an AutoPkg template's
|
|
311
|
+
`vs_SSMS.exe; filename*=UTF-8''vs_SSMS.exe`), a misspelt field (`sha2:`), an
|
|
312
|
+
unencoded space splitting the URL - since the reference parser silently
|
|
313
|
+
ignores it; a space-separated trailing `// comment` is fine. The two shapes
|
|
314
|
+
with one meaning each are auto-fixed offline: `sha2:` before a 64-hex value
|
|
315
|
+
becomes `sha256:`, and a space directly after the URL becomes `%20`; any
|
|
316
|
+
other stray text is left for a human. An
|
|
317
|
+
`add nohash prefetch item` line is reported rather than validated (`W403`),
|
|
318
|
+
since it is hashless by definition and its download cannot be verified.
|
|
319
|
+
|
|
320
|
+
`--auto-fix-network` (off by default) adds the missing sha256 of an `E401` for
|
|
321
|
+
you, which means downloading the file to hash it - there is no other way to
|
|
322
|
+
learn a sha256. The download is handed to `add_sha256_prefetch()` from
|
|
323
|
+
`bigfix_prefetch` (v1.1.5+), which streams the file, checks it against the size
|
|
324
|
+
and sha1 already on the line, and re-emits the prefetch with sha256 added, in
|
|
325
|
+
the same spelling and keeping the line's own download name. A download that
|
|
326
|
+
does not happen or does not match is `W404`: the line is left alone and its
|
|
327
|
+
`E401` stands. Each URL is fetched at most once per run, and each download
|
|
328
|
+
gives up after 60 seconds.
|
|
329
|
+
|
|
330
|
+
The same flag switches an `http://` prefetch URL to `https://` (the fix for
|
|
331
|
+
`bes-conventions-check`'s `W207`), but only once the https copy is proven to be
|
|
332
|
+
the same file: a HEAD request must report a `Content-Length` equal to the
|
|
333
|
+
line's size - checked *before* anything is downloaded - and must not redirect
|
|
334
|
+
off https; then the download's size and every hash on the line must match.
|
|
335
|
+
Only the scheme changes. Anything else is `W407` and the line stays on http;
|
|
336
|
+
`--disable W407` turns this part off.
|
|
337
|
+
|
|
338
|
+
```yaml
|
|
339
|
+
- id: bes-actionscript-validate-prefetch
|
|
340
|
+
args: ["--auto-fix-network", "yes"]
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
Because this reaches out to whatever URLs the content names, it is opt-in and
|
|
344
|
+
never the default - think about it before turning it on for a repo whose
|
|
345
|
+
prefetches point at hosts you do not control.
|
|
346
|
+
|
|
347
|
+
A prefetch that downloads the retired `unzip-5.52.exe` from the BigFix redist
|
|
348
|
+
folder is `E402` - `unzip-6.0.exe` is the current one - and it is auto-fixed
|
|
349
|
+
offline. Auto-fix is on by default; the line is rewritten in place to
|
|
350
|
+
|
|
351
|
+
```text
|
|
352
|
+
add prefetch item name=unzip.exe sha1=84debf12767785cd9b43811022407de7413beb6f size=204800 url=http://software.bigfix.com/download/redist/unzip-6.0.exe sha256=2122557d350fd1c59fb0ef32125330bde673e9331eb9371b454c2ad2d82091ac
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
or the `prefetch ... sha1:... size:...` statement equivalent, whichever
|
|
356
|
+
spelling the line already used - the replacement string is built by
|
|
357
|
+
`prefetch_from_dictionary()` from `bigfix_prefetch`, so its shape is the
|
|
358
|
+
reference implementation's. The original download's *name* is kept (the rest
|
|
359
|
+
of the ActionScript refers to the file by that name), while the url, size,
|
|
360
|
+
sha1, and sha256 become the current file's. An `add nohash prefetch item` on
|
|
361
|
+
the old URL is reported but not rewritten: swapping in a hashed prefetch would
|
|
362
|
+
change what the line does, not just which file it fetches. To report `E402`
|
|
363
|
+
without rewriting anything:
|
|
364
|
+
|
|
365
|
+
```yaml
|
|
366
|
+
- id: bes-actionscript-validate-prefetch
|
|
367
|
+
args: ["--auto-fix", "no"]
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
A file whose prefetches knowingly do not meet these rules opts out of every
|
|
371
|
+
check in this hook with `prefetch-ok` anywhere in it (e.g.
|
|
372
|
+
`<!-- prefetch-ok -->`) - the same marker that opts out of the prefetch-shape
|
|
373
|
+
warning `W206` in `bes-conventions-check`, since it is the same judgement.
|
|
374
|
+
The usual `<!-- pre-commit-skip: bes-actionscript-validate-prefetch -->` skips
|
|
375
|
+
the file too.
|
|
376
|
+
|
|
377
|
+
The scope of the *checks* is internal validity only, and they are offline: no
|
|
378
|
+
check downloads a URL or verifies that the hashes match the real file. The one
|
|
379
|
+
thing that touches the network is `--auto-fix-network`, above, and only when it
|
|
380
|
+
is asked for. Dynamic
|
|
381
|
+
prefetches (a line holding a `{...}` relevance substitution), `//` comments,
|
|
382
|
+
and the raw content of a `createfile until` block are skipped - none of them
|
|
383
|
+
carry a fixed size and hash to check. The line's overall shape and its
|
|
384
|
+
http-vs-https scheme are `W206`/`W207` in `bes-conventions-check`, and its
|
|
385
|
+
lexical validity is `E300` in `bes-actionscript-lint-schclass`: three
|
|
386
|
+
altitudes on the same line, all intentional.
|
|
387
|
+
|
|
388
|
+
`E402`, the two `E403` shapes above, and (with `--auto-fix-network`) `E401`
|
|
389
|
+
and the `W207` https switch are the only auto-fixes, and no others are
|
|
390
|
+
planned - `E400`'s correct size and hashes are properties of the
|
|
391
|
+
real file, and a hook has no way to know which file was meant. E-codes and any
|
|
392
|
+
auto-fix fail the hook; pass `--strict` to also fail on warnings. Unparsable
|
|
393
|
+
files are skipped (`bes-schema-validate` owns validity).
|
|
394
|
+
|
|
395
|
+
See the docstring in
|
|
396
|
+
[bes_actionscript_validate_prefetch.py](https://github.com/jgstew/pre-commit-bigfix/blob/main/pre_commit_bigfix/bes_actionscript_validate_prefetch.py)
|
|
397
|
+
for the full list of check codes, opt-out markers, and options.
|
|
398
|
+
|
|
399
|
+
Auto-fixes are checked against BES.xsd one pass at a time, in the order
|
|
400
|
+
`E403`, `E402`, `E401`, `W407`. A pass that would turn a schema-valid file
|
|
401
|
+
into an invalid one is not written and is reported as `E404`; the other passes
|
|
402
|
+
still are (`--disable E404` writes it anyway).
|
|
403
|
+
|
|
404
|
+
### bes-actionscript-validate-script
|
|
405
|
+
|
|
406
|
+
Checks every `<ActionScript>` body of a BES file for balanced `if`/`endif` and
|
|
407
|
+
`begin prefetch block`/`end prefetch block` pairing - the sibling hook named
|
|
408
|
+
in `bes-actionscript-lint-schclass`'s SCOPE note for checks that need pairing,
|
|
409
|
+
ordering, and block-interleaving knowledge the lexical grammar does not
|
|
410
|
+
carry, and meant to grow more per-script checks over time. An unbalanced
|
|
411
|
+
block is a real defect, not a style nit: the BigFix agent fails the action at
|
|
412
|
+
runtime on a dangling `if`, and a missing `endif` silently changes which
|
|
413
|
+
statements are conditional.
|
|
414
|
+
|
|
415
|
+
An unclosed `if` is `E500`; a stray `endif` with no open `if` is `E501`. An
|
|
416
|
+
unclosed `begin prefetch block` is `E502`; a stray `end prefetch block` is
|
|
417
|
+
`E503`; a `begin prefetch block` nested inside another one is `E504`, since
|
|
418
|
+
prefetch blocks do not nest. An `else` or `elseif` outside any open `if` is
|
|
419
|
+
`E505`; an `elseif` after `else`, or a second `else` for the same `if`, is
|
|
420
|
+
`E506`. An `if` opened inside a prefetch block that is still open at that
|
|
421
|
+
block's `end prefetch block` is `E507`, since blocks interleave rather than
|
|
422
|
+
nest.
|
|
423
|
+
|
|
424
|
+
Within a single line, a `{...}` relevance substitution that is never closed
|
|
425
|
+
before end of line is `E508`, and a `}` reached with no substitution open is
|
|
426
|
+
`E509`: a substitution is evaluated per line and cannot span lines. `E508`
|
|
427
|
+
also applies to `createfile until` content, which the agent substitutes too,
|
|
428
|
+
so a literal `{` in an embedded script must be written `{{` (a lone `}` there
|
|
429
|
+
is literal and is not `E509`). `{{` (and
|
|
430
|
+
`}}`) is an escape that passes a literal brace through to the command, so it
|
|
431
|
+
neither opens nor closes a substitution, and a later lone `}` pairs with that
|
|
432
|
+
escape instead of being reported as stray. The `}}` escape holds *inside* an
|
|
433
|
+
open substitution too - a quoted literal like `{ ... "@{'k'='v'}}" ... }`
|
|
434
|
+
(a PowerShell hashtable nested inside a substitution) does not close on the
|
|
435
|
+
first `}` of that `}}`.
|
|
436
|
+
|
|
437
|
+
An `add prefetch item` or `collect prefetch items` outside an open prefetch
|
|
438
|
+
block is `E510`/`E511` - the agent rejects them there. Two prefetch/download
|
|
439
|
+
producers declaring the same download name in the same conditional context is
|
|
440
|
+
`E512` (the second silently overwrites the first); declarations reached
|
|
441
|
+
through different `if`/`elseif`/`else` branch choices are not compared, since
|
|
442
|
+
cross-platform content routinely declares the same `name=` once per OS in a
|
|
443
|
+
separate `if` per platform, and a `__Download\<name>` reference that nothing
|
|
444
|
+
prefetches or downloads warns `W507` - a typo catcher that is skipped entirely
|
|
445
|
+
whenever any producer's names are unknowable (an `extract`/`unarchive`/
|
|
446
|
+
`archive now`/`utility` command, a `download` with no `as <name>` and no
|
|
447
|
+
literal URL basename, or a `{...}` substitution in a name or URL); a
|
|
448
|
+
`delete` or `folder delete` of a `__Download\<name>` is cleanup, not
|
|
449
|
+
consumption, and never counts as a reference. A script can create files under
|
|
450
|
+
`__Download` too, so `copy`/`move` destinations (including from
|
|
451
|
+
`__createfile`) and shell redirection targets (`... > __Download\<name>`)
|
|
452
|
+
count as producers. An
|
|
453
|
+
`if`/`elseif` whose condition is not a `{...}` relevance substitution is
|
|
454
|
+
`E514`, and `else if` written as two words (not a chained branch; use
|
|
455
|
+
`elseif`) is `E524`. A `begin prefetch block` that is not at the top of the script is
|
|
456
|
+
`E515`: only blank lines, `//` comments, `action parameter query` lines, and
|
|
457
|
+
`parameter` assignments may precede it - plain `prefetch` statements are legal
|
|
458
|
+
anywhere in a script and are not placement-checked.
|
|
459
|
+
|
|
460
|
+
Two `parameter "name" = ...` assignments to the same name that can co-execute
|
|
461
|
+
(the same conditional-context rule as `E512`) is `E516` - action parameters
|
|
462
|
+
are write-once, and the second assignment silently overwrites the first. A
|
|
463
|
+
`parameter "name"` reference before that name's assignment elsewhere in the
|
|
464
|
+
body is `E517`; a name never assigned in-script (a secure parameter supplied
|
|
465
|
+
from the Description page, say) is not `E517`, since this hook cannot see it -
|
|
466
|
+
but if the name occurs nowhere else in the whole file (not assigned, queried,
|
|
467
|
+
or mentioned by a Description form) it warns `W508`: that is almost always
|
|
468
|
+
copy-paste from a sibling fixlet, and the substitution fails at runtime. The
|
|
469
|
+
platform-supplied `action issue date` is exempt. A `continue if` or `pause while` condition that is not a `{...}`
|
|
470
|
+
relevance substitution is `E518` - the same rule `E514` applies to `if`/
|
|
471
|
+
`elseif`, extended to these two other condition-bearing verbs.
|
|
472
|
+
|
|
473
|
+
A command referencing `__createfile` or `__appendfile` when the body has no
|
|
474
|
+
matching `createfile until` / `appendfile` line anywhere is `E519` - the
|
|
475
|
+
`W507` rule reapplied to these two scratch-file verbs, with the same
|
|
476
|
+
`delete`/`folder delete` cleanup exemption. Any `__Download`, `__createfile`,
|
|
477
|
+
or `__appendfile` reference whose case does not match exactly warns `W503`:
|
|
478
|
+
Windows tolerates the mismatch, a case-sensitive Linux/macOS filesystem does
|
|
479
|
+
not. It is auto-fixed (see below).
|
|
480
|
+
|
|
481
|
+
A `setting` line that is not the documented
|
|
482
|
+
`setting "name"="value" on "{...}" for client|user|action` shape is `E520` -
|
|
483
|
+
a missing effective-date clause fails at runtime. A
|
|
484
|
+
`regset`/`regset64`/`regdelete`/`regdelete64` key that is not a quoted,
|
|
485
|
+
bracketed `"[HKEY_...]..."` keyname is `E521`. An
|
|
486
|
+
`action uses wow64 redirection` argument that is not `true`, `false`, or a
|
|
487
|
+
`{...}` substitution is `E523`.
|
|
488
|
+
|
|
489
|
+
A `wait`/`run` of cmd.exe that passes a command line but no `/c` warns
|
|
490
|
+
`W505`: without the switch cmd.exe opens an interactive shell and never runs
|
|
491
|
+
the command, so the action reports success having done nothing. `/k` is
|
|
492
|
+
likewise flagged: it does run the command, but leaves the shell open
|
|
493
|
+
afterward, so the action hangs instead of completing.
|
|
494
|
+
|
|
495
|
+
A `move`/`copy` of any source (a `__createfile`/`__appendfile` scratch file,
|
|
496
|
+
a download, ...) onto a destination that is not cleared earlier in the body
|
|
497
|
+
warns `W506` - cleared meaning a `delete` of it (including one that looks the
|
|
498
|
+
same file up by relevance), a shell `rm`/`del` naming it, or a `move` of it
|
|
499
|
+
elsewhere. Both verbs fail when the
|
|
500
|
+
destination already exists, so such an action works the first time and fails
|
|
501
|
+
on every later run; the documented pattern is to `delete` the destination
|
|
502
|
+
first. A destination inside the action's own download folder is exempt, being
|
|
503
|
+
action-scoped rather than a persistent location, and a `folder delete` of an
|
|
504
|
+
ancestor counts as clearing it.
|
|
505
|
+
|
|
506
|
+
An `override wait` / `override run` block not terminated by its own matching
|
|
507
|
+
verb - it hits end of body, is terminated by the *other* verb's command, or
|
|
508
|
+
is reopened by another `override` before any command runs - is `E522`.
|
|
509
|
+
`bes-actionscript-lint-schclass` validates the `keyword=value` option lines
|
|
510
|
+
inside a block (its `E303`); this is the pairing check that block's state
|
|
511
|
+
machine cannot express.
|
|
512
|
+
|
|
513
|
+
A command after an unconditional `exit`, `restart`, or `shutdown` (one outside
|
|
514
|
+
any `if`) can never run and warns `W501` (first unreachable line only); an
|
|
515
|
+
`action parameter query` after the first execution command warns `W502` -
|
|
516
|
+
these are console-time prompts and belong at the top.
|
|
517
|
+
|
|
518
|
+
A `parameter "<name>" = <value>` whose value is not double-quoted is `E527`:
|
|
519
|
+
the agent substitutes `{...}` first and then parses the line, so an unquoted
|
|
520
|
+
value - even a singular `{"a"}` - is invalid `parameter` syntax and the line
|
|
521
|
+
fails at runtime. A trailing `// comment` on a `parameter` line is `E528`:
|
|
522
|
+
only fixed-syntax lines (`if`/`elseif`/`else`/`endif`, the prefetch block,
|
|
523
|
+
`override`) accept one, so the line fails even with a quoted value.
|
|
524
|
+
|
|
525
|
+
`--auto-fix` (`W503`, `W506`, `E525`, `E528`, `E527`, `E524`, `W505`, `E521`), on by default when files are given (as
|
|
526
|
+
pre-commit does) and off when auto-discovering, rewrites every wrong-case
|
|
527
|
+
`__download`/`__createfile`/`__appendfile` reference to its canonical
|
|
528
|
+
spelling, inserts a `delete <destination>` before each `W506` move/copy, and
|
|
529
|
+
quotes each unquoted `folder create`/`folder delete` path (`E525` - quoted even
|
|
530
|
+
when today's value has no spaces, since a user profile or parameter can),
|
|
531
|
+
moves a `parameter` line's trailing comment onto its own line above (`E528`),
|
|
532
|
+
quotes an unquoted `parameter` value (`E527` - `"` in an entity-escaped
|
|
533
|
+
body; a value holding a `"` outside `{...}` or `%22` is reported, not fixed),
|
|
534
|
+
joins `else if` into `elseif` (`E524`, unless a stray `endif` shows a real
|
|
535
|
+
nested `if`), turns a waiting cmd.exe's `/k` into `/c` or inserts a missing
|
|
536
|
+
`/c` after its leading switches (`W505`), and quotes a bracketed-but-unquoted
|
|
537
|
+
registry key (`E521`), in place; an auto-fixed file fails the hook so the
|
|
538
|
+
change is reviewed and re-staged. No other check here has an auto-fix: a hook
|
|
539
|
+
has no way to know where a missing `endif` or `end prefetch block` was meant
|
|
540
|
+
to go, and guessing could silently change what the action does.
|
|
541
|
+
|
|
542
|
+
Only `application/x-Fixlet-Windows-Shell` (matched case-insensitively - it is
|
|
543
|
+
valid BigFix content either way) or missing-MIMEType bodies are checked;
|
|
544
|
+
bodies are extracted with lxml, so entities are decoded, CDATA sections
|
|
545
|
+
merged, and line numbers map back to the file. Lines inside a
|
|
546
|
+
`createfile until` block are file content, not ActionScript, and are not
|
|
547
|
+
scanned; that block's own well-formedness is `bes-actionscript-lint-schclass`'s
|
|
548
|
+
`E302`, not reported here. Unparsable files are `W500` (`bes-schema-validate`
|
|
549
|
+
owns validity).
|
|
550
|
+
|
|
551
|
+
A file opts out of every check here with
|
|
552
|
+
`<!-- pre-commit-skip: bes-actionscript-validate-script -->` anywhere in it,
|
|
553
|
+
or out of one family with `actionscript-if-ok` (`E500`, `E501`, `E505`,
|
|
554
|
+
`E506`, `E514`, `E518`, `E524`), `actionscript-prefetch-block-ok` (`E502`, `E503`,
|
|
555
|
+
`E504`), `actionscript-block-nesting-ok` (`E507`), `actionscript-substitution-ok`
|
|
556
|
+
(`E508`, `E509` - the same marker `bes-actionscript-lint-schclass` uses for
|
|
557
|
+
its `E301`, so one marker covers both hooks),
|
|
558
|
+
`actionscript-prefetch-placement-ok` (`E510`, `E511`, `E515`),
|
|
559
|
+
`actionscript-download-ok` (`E512`, `W507`), `actionscript-parameter-ok`
|
|
560
|
+
(`E516`, `E517`, `E527`, `E528`, `W508`), `actionscript-scratch-ok` (`E519`, `W503`),
|
|
561
|
+
`actionscript-scratch-dest-ok` (`W506`),
|
|
562
|
+
`actionscript-command-shape-ok` (`E520`, `E521`, `E523`, `E525`),
|
|
563
|
+
`actionscript-cmd-ok` (`W505`),
|
|
564
|
+
`actionscript-override-ok` (`E522` - shared with
|
|
565
|
+
`bes-actionscript-lint-schclass`'s `E303`), `actionscript-unreachable-ok`
|
|
566
|
+
(`W501`), or `actionscript-parameter-query-ok` (`W502`). E-codes fail the
|
|
567
|
+
hook; pass
|
|
568
|
+
`--strict` to also fail on warnings.
|
|
569
|
+
|
|
570
|
+
See the docstring in
|
|
571
|
+
[bes_actionscript_validate_script.py](https://github.com/jgstew/pre-commit-bigfix/blob/main/pre_commit_bigfix/bes_actionscript_validate_script.py)
|
|
572
|
+
for the full list of check codes, opt-out markers, and options.
|
|
573
|
+
|
|
574
|
+
Auto-fixes are checked against BES.xsd one pass at a time: `W503`, `W506`,
|
|
575
|
+
`E525`, `E528`, `E527`, then the `E524`/`W505`/`E521` line rewrites as one pass. A pass that
|
|
576
|
+
would turn a schema-valid file into an invalid one is not written and is
|
|
577
|
+
reported as `E526`; the other passes still are (`--disable E526` writes it
|
|
578
|
+
anyway).
|
|
579
|
+
|
|
580
|
+
### bes-relevance-lint
|
|
581
|
+
|
|
582
|
+
Every other hook here treats relevance as opaque - `{...}` is a lexer state
|
|
583
|
+
mechanically identical to a string literal, and the most any check proves about
|
|
584
|
+
a condition is that it starts with a brace. This hook is where that stops. It
|
|
585
|
+
hands each statement to
|
|
586
|
+
[bigfix-relevance-analyzer](https://github.com/jgstew/bigfix-relevance-analyzer),
|
|
587
|
+
which parses it, binds `it`, resolves every inspector against the client dumps,
|
|
588
|
+
type-checks the result, and scores what it costs to evaluate.
|
|
589
|
+
|
|
590
|
+
Every site the analyzer's extractor recognizes is checked - `<Relevance>`
|
|
591
|
+
bodies, `<SuccessCriteria Option="CustomRelevance">` bodies, Analysis
|
|
592
|
+
`<Property>` bodies, and the `{...}` substitutions inside `<ActionScript>` - so
|
|
593
|
+
a defect in a substitution is reported at the line it lives on, not at the top
|
|
594
|
+
of the file.
|
|
595
|
+
|
|
596
|
+
| code | meaning |
|
|
597
|
+
| --- | --- |
|
|
598
|
+
| `E600` | the statement could not be parsed |
|
|
599
|
+
| `E601` | the statement contains text that could not be lexed |
|
|
600
|
+
| `E602` | `it` is used where there is no context to bind it to |
|
|
601
|
+
| `E603` | the type checker reported a problem beyond an unbound `it` |
|
|
602
|
+
| `E604` | the complexity score is above the ceiling (raise with `--max-score`) |
|
|
603
|
+
| `E605` | the evaluation cost is above the ceiling (raise with `--max-evaluation-cost`) |
|
|
604
|
+
| `E606` | a directory tree was deeper than `--max-depth`, so it was not fully scanned (auto-discovery only; pre-commit always passes filenames) |
|
|
605
|
+
| `E607` | a path given to the linter does not exist, could not be read, or is not a file type the analyzer recognizes (the hook's `files:` pattern keeps those away under pre-commit) |
|
|
606
|
+
| `E608` | the value does not fit the kind of site it came from: a `<Relevance>` that is not a boolean, or an `if`/`elseif`/`continue if` condition that is not a boolean or string |
|
|
607
|
+
| `E609` | inspectors exclusive to client relevance and to session relevance in one statement, which no engine can answer |
|
|
608
|
+
| `E610` | an ActionScript command word used as a relevance name, usually an ActionScript line pasted or doubled into relevance |
|
|
609
|
+
| `E611` | a plural operand where the engine requires a single value, which it refuses before evaluating anything; a `unique value of` (or singular-aggregate) rewrite is printed as a suggested fix where safe |
|
|
610
|
+
| `E612` | an ActionScript `{` with anything after it on its line and no `}` to close it there, which fails the action |
|
|
611
|
+
| `E613` | a `<?Relevance` with no closing `?>`, so its relevance was not linted |
|
|
612
|
+
| `E614` | a BES file that is not well-formed XML, so nothing in it was linted (**off by default**; `--enable E614`) |
|
|
613
|
+
| `W600` | a name no inspector dump defines |
|
|
614
|
+
| `W601` | a property written singular over an object that may be plural |
|
|
615
|
+
| `W602` | a singular spelling mid-chain (under a `whose` filter, or where a plural is built from it), where the plural reads safer |
|
|
616
|
+
| `W603` | two version-looking strings compared as strings, not as versions |
|
|
617
|
+
| `W604` | a version comparison that truncates to the shorter operand's components |
|
|
618
|
+
| `W605` | an ordinary ActionScript substitution's value is an opaque object with no text form |
|
|
619
|
+
| `W606` | an ordinary ActionScript substitution's value may be more than one value; the client joins them with no separator |
|
|
620
|
+
| `W607` | a relevance-tagged markdown code fence that is never closed, so its relevance was not linted (manual runs on markdown only) |
|
|
621
|
+
|
|
622
|
+
`W600` is a warning rather than an error because a repo running a newer client
|
|
623
|
+
than the analyzer's dump snapshot legitimately uses names it has never heard
|
|
624
|
+
of. `W601` is **disabled by default** in the hook declaration: across 1,108
|
|
625
|
+
`.bes` files of real content it fires 6,127 times, which drowns everything
|
|
626
|
+
else. Switch it back on with `--enable W601`.
|
|
627
|
+
|
|
628
|
+
Unparsable XML is skipped rather than reported (`E614` is off by default) -
|
|
629
|
+
`bes-schema-validate` owns file validity. That does mean a truncated file passes this hook: a clean run
|
|
630
|
+
says the relevance that could be extracted is sound, not that the file parses.
|
|
631
|
+
|
|
632
|
+
A file opts out of every check here with
|
|
633
|
+
`<!-- pre-commit-skip: bes-relevance-lint -->` anywhere in it. There is no
|
|
634
|
+
per-rule marker: `--disable` takes a code repo-wide, and a single file that
|
|
635
|
+
legitimately needs relevance this complex is what `--max-score` is for. Files
|
|
636
|
+
are never rewritten, but where the analyzer can work out a safe rewrite of a
|
|
637
|
+
whole statement (today, the singular spellings behind `W602`) the fixed
|
|
638
|
+
statement is printed once under its first finding as `suggested fix: ...`.
|
|
639
|
+
E-codes fail the hook; pass `--strict` to also fail on warnings.
|
|
640
|
+
|
|
641
|
+
This hook needs **Python 3.11 or newer** - the analyzer requires it, while the
|
|
642
|
+
rest of this package still runs on 3.8. No specific interpreter is pinned, since
|
|
643
|
+
`language_version` names an exact executable and pinning `python3.11` would
|
|
644
|
+
break machines that only have something newer; set it yourself
|
|
645
|
+
(`language_version: python3.12`) if pre-commit's default is too old. The
|
|
646
|
+
dependency carries a matching environment marker, so the other hooks stay
|
|
647
|
+
installable on 3.8-3.10; run this one there anyway and it prints why it cannot
|
|
648
|
+
run and skips (exit 0) - no config on a 3.8-3.10 interpreter can make it pass,
|
|
649
|
+
so failing there would only be an unfixable red build. On 3.11+ a missing
|
|
650
|
+
analyzer is a broken install, and the hook still fails.
|
|
651
|
+
|
|
652
|
+
See the docstring in
|
|
653
|
+
[bes_relevance_lint.py](https://github.com/jgstew/pre-commit-bigfix/blob/main/pre_commit_bigfix/bes_relevance_lint.py) for the full
|
|
654
|
+
list of check codes and options.
|
|
655
|
+
|
|
656
|
+
### bes-relevance-convert-group
|
|
657
|
+
|
|
658
|
+
The BigFix console can save applicability as a computer-group style
|
|
659
|
+
`<GroupRelevance>`: a list of search components, each already carrying its own
|
|
660
|
+
`<Relevance>`, joined by intersection or union. BES.xsd allows either that or a
|
|
661
|
+
run of `<Relevance>` elements in the same place, and plain relevance is what
|
|
662
|
+
reads and diffs well, so this hook rewrites each `/BES/*/GroupRelevance` in
|
|
663
|
+
place:
|
|
664
|
+
|
|
665
|
+
| `JoinByIntersection` | components | becomes |
|
|
666
|
+
| --- | --- | --- |
|
|
667
|
+
| `true` | any | one `<Relevance>` per component (sibling Relevance must all hold) |
|
|
668
|
+
| `false` | one | `<Relevance>s1</Relevance>` |
|
|
669
|
+
| `false` | two or more | `<Relevance>(s1) OR (s2) OR ...</Relevance>` |
|
|
670
|
+
|
|
671
|
+
Each component's relevance is copied verbatim - CDATA stays CDATA, escaped
|
|
672
|
+
stays escaped - except an OR-join of several, which is decoded, joined, and
|
|
673
|
+
written once: as CDATA when any input was CDATA or the text holds `<`, `>` or
|
|
674
|
+
`&`, and entity-escaped if it contains `]]>`. The splice leaves everything
|
|
675
|
+
outside the replaced block byte-identical, line endings included. A long union
|
|
676
|
+
can become one large statement; `bes-relevance-lint` may then report `E604`.
|
|
677
|
+
|
|
678
|
+
| code | meaning |
|
|
679
|
+
| --- | --- |
|
|
680
|
+
| `E700` | a GroupRelevance was converted (under `--check`: needs converting) |
|
|
681
|
+
| `E701` | a GroupRelevance holds a `SearchComponentGroupReference`; group membership is not converted yet, so it is left unchanged |
|
|
682
|
+
| `E702` | `JoinByIntersection` is not a boolean, or is missing with two or more components (BES.xsd documents no default; a single component converts either way); left unchanged |
|
|
683
|
+
| `E703` | a GroupRelevance has no components, or one with an empty Relevance; left unchanged |
|
|
684
|
+
| `E704` | the converted file would turn a schema-valid file invalid, so nothing is written |
|
|
685
|
+
| `W700` | skipped: file missing or not parseable XML, or a GroupRelevance that could not be located |
|
|
686
|
+
|
|
687
|
+
The hook converts by default and exits 1 when it changed anything, so the
|
|
688
|
+
rewrite shows up for review; `--check` only reports. With no files given it
|
|
689
|
+
checks every `*.bes` below the current folder and never rewrites. A file opts
|
|
690
|
+
out with `<!-- pre-commit-skip: bes-relevance-convert-group -->`.
|
|
691
|
+
|
|
692
|
+
### bes-siterepo-validate-layout
|
|
693
|
+
|
|
694
|
+
For a BigFix [Git External Custom Site](https://help.hcl-software.com/bigfix/11.0/platform/Platform/Config/c_repository_site_git.html)
|
|
695
|
+
("repository site", BigFix 11.0.7+) repo. The root server gathers the site
|
|
696
|
+
from git, and one bad file can fail the whole sync, so this hook checks the
|
|
697
|
+
site as a whole: it runs once per commit (`pass_filenames: false`,
|
|
698
|
+
`always_run: true`) on the files `git ls-files` lists, so untracked and
|
|
699
|
+
ignored files do not count.
|
|
700
|
+
|
|
701
|
+
The site root is the repo root, or each `--site-root DIR` (repeatable, for a
|
|
702
|
+
repo of several sites like CommunityContent's `Sites/<name>/`). Its
|
|
703
|
+
`siteConfig.xml`, if tracked, names the folders (`BesFileDir`,
|
|
704
|
+
`NonClientFilesDir`, `OtherFilesDir`); the defaults are `Fixlets`,
|
|
705
|
+
`NonClientFiles` and `OtherFiles`.
|
|
706
|
+
|
|
707
|
+
A root server can run Windows or RHEL, and one repo site may serve both, so
|
|
708
|
+
names and paths must be valid on both: the stricter limit always applies.
|
|
709
|
+
Folder names, the `.bes` extension and `digest.xml` match ignoring case, as
|
|
710
|
+
on Windows, so nothing goes unchecked; one that matches only that way is a
|
|
711
|
+
warning (`W808`), since RHEL is case-sensitive.
|
|
712
|
+
|
|
713
|
+
| code | meaning |
|
|
714
|
+
| --- | --- |
|
|
715
|
+
| `E800` | a `.bes` file in the `.bes` folder whose name does not start with a numeric ID and a space or hyphen; `42- Name.bes` and `42 Name.bes` both work |
|
|
716
|
+
| `E801` | two or more `.bes` files in one site share an ID, compared as integers, so `0042` and `42` collide; each names the others |
|
|
717
|
+
| `E802` | a `.bes` file's server path is too long and the rename cannot fix it: even `<ID> X.bes` is too long (the folders are), it has no ID, or `E805` is disabled. Renaming a folder changes its `.fxf` or digest, so that is left to you |
|
|
718
|
+
| `E803` | fix: zero padding in the ID (`0042- X.bes` -> `42- X.bes`); done even when the ID is a duplicate (`E801`), since the ID does not change |
|
|
719
|
+
| `E804` | fix: non-ASCII characters in the name, folded to ASCII |
|
|
720
|
+
| `E805` | fix: the server path is too long, or the name is over 255 bytes, so the file is renamed `<ID> <Title>.bes` |
|
|
721
|
+
| `E806` | a rename was skipped: the new name is taken (ignoring case), the file has unstaged changes pre-commit set aside, the commit uses a temporary index (`git commit -a`, `git commit <paths>`), or the rename failed |
|
|
722
|
+
| `E807` | another tracked file's server path is too long, inside the site roots or not (the server clones the whole repo). It is not renamed, since actions may refer to it by name |
|
|
723
|
+
| `E808` | a file or folder name over 255 bytes in UTF-8 (Linux `NAME_MAX`) that the rename cannot fix; each folder once |
|
|
724
|
+
| `W800` | a `.bes` file outside the `.bes` folder; the server does not gather it |
|
|
725
|
+
| `W801` | a `.bes` file directly in the `.bes` folder, or deeper than `<BesFileDir>/<fxf>/<digest>/` (how the server handles either is undocumented) |
|
|
726
|
+
| `W802` | a file in the `.bes` folder other than `.bes` or `digest.xml`; an `.xsd` too, since `bes-schema-validate` already has the schemas |
|
|
727
|
+
| `W803` | a folder `siteConfig.xml` renames has no files (a default name spelled out, as the template does, is not checked: those folders are optional) |
|
|
728
|
+
| `W804` | the site has no content: no `.bes` files and no files in the NonClient or Other folders. A site of server files only passes |
|
|
729
|
+
| `W806` | an ID outside 1..2147483647 (the range is undocumented) |
|
|
730
|
+
| `W807` | `siteConfig.xml` is not readable XML; the default folders are used (`bes-schema-validate` reports why) |
|
|
731
|
+
| `W808` | a folder, `.bes` extension or `digest.xml` that matches the expected name only when case is ignored (`fixlets/` for `Fixlets`, `.BES`); a RHEL server may not find it |
|
|
732
|
+
|
|
733
|
+
**Path and name limits.** The server clones the whole repo to
|
|
734
|
+
`<server-root>\RepositorySiteGather\Sites\<repo>_<branch>_<8 hex>\Source\`,
|
|
735
|
+
and each file's path relative to the repo root (not the site root) is added
|
|
736
|
+
to that. The result must be at most 259 characters (`MAX_PATH` is 260 with
|
|
737
|
+
the terminating NUL); paths over it fail on 11.0.7 even with Windows long
|
|
738
|
+
paths enabled. For example, `bigfix-site-reporting-jgstew` on the `main`
|
|
739
|
+
branch is cloned to
|
|
740
|
+
`C:\Program Files (x86)\BigFix Enterprise\BES Server\RepositorySiteGather\Sites\bigfix-site-reporting-jgstew_main_27eb797e\Source\`,
|
|
741
|
+
129 characters, leaving 130 for the path in the repo. `<repo>` is the git
|
|
742
|
+
repo's name, not the site's name in BigFix. The length is counted in UTF-16
|
|
743
|
+
units, as Windows counts it. Only this Windows layout is confirmed (the
|
|
744
|
+
clone path on a RHEL server is not), so it is the path that is measured. On
|
|
745
|
+
Linux each file and folder name must also be at most 255 bytes in UTF-8
|
|
746
|
+
(`NAME_MAX`); Linux's 4096-byte `PATH_MAX` cannot be reached once the
|
|
747
|
+
Windows limit holds. In a repo of several sites, paths are still measured
|
|
748
|
+
from the repo root: CommunityContent's `Sites/<name>/Fixlets/...` paths
|
|
749
|
+
count in full. The options:
|
|
750
|
+
|
|
751
|
+
| option | default |
|
|
752
|
+
| --- | --- |
|
|
753
|
+
| `--server-root` | `C:\Program Files (x86)\BigFix Enterprise\BES Server` |
|
|
754
|
+
| `--repo-name` | the last part of the `origin` remote URL without `.git`, or the repo folder's name |
|
|
755
|
+
| `--branch` | `main` |
|
|
756
|
+
| `--max-path` | `259` |
|
|
757
|
+
|
|
758
|
+
**Renames.** By default each `.bes` file in the `.bes` folder is renamed at
|
|
759
|
+
most once, combining the fixes it needs: zero padding stripped from the ID
|
|
760
|
+
(`E803`), non-ASCII folded to ASCII (`E804`: the euro sign becomes `EUR`, a
|
|
761
|
+
curly apostrophe `'`, accents are dropped, and `_` stands in when there is no
|
|
762
|
+
equivalent), and, if the path or name is still too long, `<ID> <Title>.bes`
|
|
763
|
+
cut to fit both limits (`E805`). The title comes from the file's `<Title>`,
|
|
764
|
+
or from its current name if the title has no letter or digit; it is made
|
|
765
|
+
ASCII and safe on Windows, cut short, and any trailing space, dot or hyphen
|
|
766
|
+
is dropped. A name that already fits is left alone, even when it differs
|
|
767
|
+
from the title. The ID never changes and no file moves between folders.
|
|
768
|
+
|
|
769
|
+
Tracked files are renamed with `git mv`, so the renames are staged and the
|
|
770
|
+
next commit carries them whole; a plain rename would leave an unstaged
|
|
771
|
+
deletion that `git commit -a` could commit without the new file. Nothing is
|
|
772
|
+
renamed (`E806`) where the rename would be lost:
|
|
773
|
+
|
|
774
|
+
- `git commit -a` and `git commit <paths>` run the hook on a temporary index
|
|
775
|
+
that git throws away when the hook fails. `git add` the changes and run a
|
|
776
|
+
plain `git commit` (or `pre-commit run`) to get the renames.
|
|
777
|
+
- A file with unstaged changes that pre-commit set aside for the run: it
|
|
778
|
+
could not put them back on a renamed file. The hook finds pre-commit's
|
|
779
|
+
stash file by the pid of its parent, grandparent or great-grandparent (a
|
|
780
|
+
Windows `.exe` launcher sits in between); this is verified on macOS only.
|
|
781
|
+
`pre-commit try-repo` keeps its stash in a temporary cache that the hook
|
|
782
|
+
cannot see, so there such a file is renamed and pre-commit then fails to
|
|
783
|
+
restore the changes (they stay in its patch file).
|
|
784
|
+
Any rename makes the hook exit 1, so review the renames and commit again.
|
|
785
|
+
`--check` is a dry run that reports what would be renamed.
|
|
786
|
+
|
|
787
|
+
Files with no ID are reported (`E800`), not given one. An opt-in
|
|
788
|
+
`--assign-ids` is deferred: choosing IDs is a policy decision, best backed
|
|
789
|
+
by a counter file as CommunityContent does, since taking the highest ID plus
|
|
790
|
+
one could reuse a deleted item's ID.
|
|
791
|
+
|
|
792
|
+
Not checked here: more than one object in a `.bes` file, or Baselines
|
|
793
|
+
(repository sites are thought to handle both); schemas, GroupRelevance and
|
|
794
|
+
`//` comments (`bes-schema-validate`, `bes-relevance-convert-group`,
|
|
795
|
+
`bes-conventions-check`); setting up a blank repo. For names that differ
|
|
796
|
+
only by case, and names Windows forbids, add these companions from
|
|
797
|
+
[pre-commit-hooks](https://github.com/pre-commit/pre-commit-hooks)
|
|
798
|
+
(`>= 5.0.0`):
|
|
799
|
+
|
|
800
|
+
```yaml
|
|
801
|
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
802
|
+
rev: v6.0.0
|
|
803
|
+
hooks:
|
|
804
|
+
- id: check-case-conflict
|
|
805
|
+
- id: check-illegal-windows-names
|
|
806
|
+
```
|
|
807
|
+
|
|
808
|
+
A repo with several sites:
|
|
809
|
+
|
|
810
|
+
```yaml
|
|
811
|
+
- id: bes-siterepo-validate-layout
|
|
812
|
+
args: [--site-root, "Sites/Site A", --site-root, "Sites/Site B"]
|
|
813
|
+
```
|
|
814
|
+
|
|
815
|
+
## Development
|
|
816
|
+
|
|
817
|
+
```bash
|
|
818
|
+
pip install -e .[test]
|
|
819
|
+
python -m pytest
|
|
820
|
+
pre-commit run --all-files
|
|
821
|
+
```
|