@gspothq/cli 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +58 -11
- package/configurations/database/postgres/manifest.toml +51 -57
- package/configurations/database/postgres/rules/POSTGRES.md +14 -13
- package/configurations/framework/astro/manifest.toml +33 -35
- package/configurations/framework/astro/rules/ASTRO.md +2 -2
- package/configurations/framework/expo/manifest.toml +19 -19
- package/configurations/framework/express/manifest.toml +10 -4
- package/configurations/framework/express/rules/EXPRESS.md +9 -7
- package/configurations/framework/fastapi/manifest.toml +9 -3
- package/configurations/framework/fastapi/rules/FASTAPI.md +19 -18
- package/configurations/framework/nestjs/manifest.toml +12 -12
- package/configurations/framework/nestjs/rules/NESTJS.md +9 -9
- package/configurations/framework/nextjs/manifest.toml +39 -79
- package/configurations/framework/nextjs/rules/NEXTJS.md +9 -7
- package/configurations/framework/nextjs/tool-files/semgrep/nextjs.yml +35 -0
- package/configurations/framework/react/manifest.toml +33 -43
- package/configurations/framework/react/rules/REACT.md +14 -20
- package/configurations/framework/react-dom/manifest.toml +6 -6
- package/configurations/framework/react-native/manifest.toml +11 -11
- package/configurations/framework/react-native/rules/REACT-NATIVE.md +3 -5
- package/configurations/framework/site/manifest.toml +57 -110
- package/configurations/framework/site/rules/SITE.md +1 -1
- package/configurations/framework/svelte/manifest.toml +29 -31
- package/configurations/framework/svelte/rules/SVELTE.md +6 -6
- package/configurations/framework/vue/manifest.toml +37 -37
- package/configurations/framework/vue/rules/VUE.md +6 -6
- package/configurations/general/commits/manifest.toml +20 -84
- package/configurations/general/commits/rules/GIT.md +24 -13
- package/configurations/general/coverage/manifest.toml +1 -1
- package/configurations/general/dependencies/manifest.toml +47 -107
- package/configurations/general/dependencies/rules/DEPENDENCIES.md +13 -7
- package/configurations/general/docs/manifest.toml +28 -43
- package/configurations/general/docs/rules/DOCS.md +16 -9
- package/configurations/general/duplication/manifest.toml +12 -14
- package/configurations/general/engineering/manifest.toml +6 -2
- package/configurations/general/engineering/rules/agent/PLANNING.md +9 -6
- package/configurations/general/engineering/rules/agent/SUPPRESSIONS.md +20 -11
- package/configurations/general/engineering/rules/agent/TASKS.md +6 -2
- package/configurations/general/engineering/rules/agent/WORKING.md +34 -29
- package/configurations/general/engineering/rules/code/ACCESSIBILITY.md +9 -7
- package/configurations/general/engineering/rules/code/CLI.md +12 -9
- package/configurations/general/engineering/rules/code/COMMENTS.md +11 -1
- package/configurations/general/engineering/rules/code/CONFIGURATION.md +2 -0
- package/configurations/general/engineering/rules/code/ERRORS.md +5 -3
- package/configurations/general/engineering/rules/code/HTTP.md +9 -10
- package/configurations/general/engineering/rules/code/LOGGING.md +10 -9
- package/configurations/general/engineering/rules/code/TESTING.md +18 -11
- package/configurations/general/files/manifest.toml +45 -73
- package/configurations/general/files/rules/YAML.md +20 -10
- package/configurations/general/format/manifest.toml +53 -106
- package/configurations/general/gspot/manifest.toml +19 -39
- package/configurations/general/gspot/rules/GENERATED.md +14 -4
- package/configurations/general/licenses/manifest.toml +12 -14
- package/configurations/general/naming/defaults.json +14 -13
- package/configurations/general/naming/manifest.toml +17 -17
- package/configurations/general/naming/rules/NAMING.md +87 -67
- package/configurations/general/prose/manifest.toml +166 -25
- package/configurations/general/prose/rules/WRITING.md +6 -2
- package/configurations/general/repository/manifest.toml +12 -12
- package/configurations/general/secrets/manifest.toml +52 -73
- package/configurations/general/secrets/rules/SECRETS.md +3 -1
- package/configurations/general/security/manifest.toml +29 -52
- package/configurations/general/security/rules/SECURITY.md +8 -6
- package/configurations/general/spelling/manifest.toml +15 -25
- package/configurations/general/structure/manifest.toml +31 -31
- package/configurations/infrastructure/ansible/manifest.toml +15 -15
- package/configurations/infrastructure/docker/manifest.toml +55 -67
- package/configurations/infrastructure/docker/rules/DOCKER.md +15 -13
- package/configurations/infrastructure/github-actions/manifest.toml +21 -41
- package/configurations/infrastructure/github-actions/rules/GITHUB-ACTIONS.md +16 -12
- package/configurations/infrastructure/github-actions/tool-files/zizmor.yml +5 -0
- package/configurations/infrastructure/nginx/manifest.toml +20 -20
- package/configurations/infrastructure/nginx/rules/NGINX.md +5 -4
- package/configurations/infrastructure/openapi/manifest.toml +20 -20
- package/configurations/infrastructure/openapi/rules/OPENAPI.md +3 -1
- package/configurations/infrastructure/xcode/manifest.toml +55 -75
- package/configurations/infrastructure/xcode/rules/XCODE.md +5 -3
- package/configurations/language/bash/manifest.toml +89 -170
- package/configurations/language/bash/rules/BASH.md +79 -17
- package/configurations/language/bash/rules/LANGUAGE.md +30 -26
- package/configurations/language/bash/rules/OPERATIONS.md +10 -8
- package/configurations/language/bash/rules/SAFETY.md +39 -35
- package/configurations/language/css/manifest.toml +22 -61
- package/configurations/language/css/rules/CSS.md +21 -2
- package/configurations/language/css/rules/TAILWIND.md +7 -5
- package/configurations/language/html/manifest.toml +16 -35
- package/configurations/language/html/rules/HTML.md +23 -5
- package/configurations/language/javascript/eslint-runtime-names.json +66 -61
- package/configurations/language/javascript/eslint-runtime.mjs +118 -0
- package/configurations/language/javascript/manifest.toml +135 -207
- package/configurations/language/javascript/rules/BUN.md +2 -2
- package/configurations/language/javascript/rules/COMPONENTS.md +4 -4
- package/configurations/language/javascript/rules/DENO.md +1 -1
- package/configurations/language/javascript/rules/JAVASCRIPT.md +30 -17
- package/configurations/language/javascript/rules/NODE.md +2 -2
- package/configurations/language/javascript/rules/PLAYWRIGHT.md +10 -9
- package/configurations/language/markdown/manifest.toml +20 -51
- package/configurations/language/python/manifest.toml +231 -342
- package/configurations/language/python/rules/DESIGN.md +40 -33
- package/configurations/language/python/rules/FLOW.md +8 -6
- package/configurations/language/python/rules/PACKAGING.md +14 -7
- package/configurations/language/python/rules/PYTHON.md +83 -33
- package/configurations/language/python/rules/TYPING.md +25 -23
- package/configurations/language/sql/manifest.toml +19 -37
- package/configurations/language/sql/rules/SQL.md +90 -2
- package/configurations/language/swift/manifest.toml +67 -78
- package/configurations/language/swift/rules/SWIFT.md +138 -40
- package/configurations/language/swift/rules/SWIFTUI.md +11 -9
- package/configurations/language/swift/rules/UIKIT.md +21 -19
- package/configurations/language/typescript/manifest.toml +34 -34
- package/configurations/language/typescript/rules/TYPESCRIPT.md +62 -10
- package/configurations/library/drizzle/manifest.toml +25 -38
- package/configurations/library/drizzle/rules/DRIZZLE.md +4 -2
- package/configurations/library/react-hook-form/manifest.toml +4 -4
- package/configurations/library/react-hook-form/rules/REACT-HOOK-FORM.md +15 -13
- package/configurations/library/tanstack-query/manifest.toml +6 -6
- package/configurations/library/tanstack-query/rules/TANSTACK-QUERY.md +5 -3
- package/configurations/library/testing-library/manifest.toml +6 -6
- package/configurations/library/translations/manifest.toml +22 -22
- package/configurations/library/translations/rules/NEXT-INTL.md +6 -8
- package/configurations/library/translations/rules/TRANSLATIONS.md +22 -23
- package/configurations/library/trpc/manifest.toml +3 -3
- package/configurations/library/trpc/rules/TRPC.md +8 -6
- package/configurations/library/zod/manifest.toml +6 -6
- package/configurations/library/zod/rules/ZOD.md +4 -2
- package/configurations/library/zustand/manifest.toml +4 -4
- package/configurations/library/zustand/rules/ZUSTAND.md +16 -14
- package/configurations/platform/cloudflare/manifest.toml +28 -47
- package/configurations/platform/cloudflare/rules/CLOUDFLARE.md +11 -6
- package/configurations/platform/supabase/manifest.toml +48 -61
- package/configurations/platform/supabase/rules/SUPABASE.md +27 -28
- package/configurations/testing/jest/manifest.toml +21 -22
- package/configurations/testing/pytest/manifest.toml +28 -28
- package/configurations/testing/swift-tests/manifest.toml +18 -29
- package/configurations/testing/swift-tests/rules/SWIFT-TESTS.md +7 -5
- package/configurations/testing/vitest/manifest.toml +32 -32
- package/configurations/testing/vitest/rules/VITEST.md +3 -1
- package/dist/gspot.js +22297 -24707
- package/dist/{linkinator-program.js → linkinator-process.js} +5 -7
- package/dist/{purgecss-program.js → purgecss-process.js} +12 -12
- package/package.json +7 -9
- package/configurations/infrastructure/github-actions/zizmor.yml +0 -3
- package/configurations/language/bash/rules/NAMING.md +0 -62
- package/configurations/language/css/rules/NAMING.md +0 -17
- package/configurations/language/html/rules/NAMING.md +0 -16
- package/configurations/language/javascript/rules/NAMING.md +0 -31
- package/configurations/language/markdown/markdownlint-cli2.mjs +0 -19
- package/configurations/language/python/rules/NAMING.md +0 -53
- package/configurations/language/sql/rules/NAMING.md +0 -90
- package/configurations/language/swift/rules/NAMING.md +0 -88
- package/configurations/language/typescript/rules/NAMING.md +0 -73
- package/configurations/library/swift-snapshot-testing/manifest.toml +0 -32
- package/dist/THIRD-PARTY-NOTICES.md +0 -25
- package/dist/eslint-rule-levels.json +0 -10
- package/dist/tool-versions.json +0 -3
- package/gspot.schema.json +0 -45991
- /package/{dist/LICENSE.md → LICENSE.md} +0 -0
- /package/configurations/framework/express/{semgrep → tool-files/semgrep}/express.yml +0 -0
- /package/configurations/framework/fastapi/{semgrep → tool-files/semgrep}/fastapi.yml +0 -0
- /package/configurations/general/dependencies/{syncpack.json → tool-files/syncpack.json} +0 -0
- /package/configurations/general/prose/{vale → tool-files/vale}/styles/LICENSES.md +0 -0
- /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/ampm.yml +0 -0
- /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/conscious-language.yml +0 -0
- /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/contractions.yml +0 -0
- /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/currency.yml +0 -0
- /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/dashes.yml +0 -0
- /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/date-ordinals.yml +0 -0
- /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/dates.yml +0 -0
- /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/file-paths.yml +0 -0
- /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/future.yml +0 -0
- /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/hedging.yml +0 -0
- /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/history.yml +0 -0
- /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/idioms.yml +0 -0
- /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/interface-verbs.yml +0 -0
- /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/jargon.yml +0 -0
- /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/leading-conjunctions.yml +0 -0
- /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/link-text.yml +0 -0
- /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/locations.yml +0 -0
- /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/marketing.yml +0 -0
- /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/merge-conflict-markers.yml +0 -0
- /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/militaristic-language.yml +0 -0
- /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/modals.yml +0 -0
- /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/numbered-units.yml +0 -0
- /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/obvious-fields.yml +0 -0
- /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/ordinal-adverbs.yml +0 -0
- /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/percentage-numbers.yml +0 -0
- /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/placeholders.yml +0 -0
- /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/product-centric-writing.yml +0 -0
- /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/punctuated-headings.yml +0 -0
- /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/self-reference.yml +0 -0
- /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/session-identifiers.yml +0 -0
- /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/since.yml +0 -0
- /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/straight-quotes.yml +0 -0
- /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/suspended-hyphens.yml +0 -0
- /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/symbols.yml +0 -0
- /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/time-ranges.yml +0 -0
- /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/url-prepositions.yml +0 -0
- /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/version-range.yml +0 -0
- /package/configurations/general/secrets/{gitleaks.toml → tool-files/gitleaks.toml} +0 -0
- /package/configurations/infrastructure/docker/{trivyignore → tool-files/trivyignore} +0 -0
- /package/configurations/language/bash/{semgrep → tool-files/semgrep}/bash.yml +0 -0
- /package/configurations/language/javascript/{semgrep → tool-files/semgrep}/javascript.yml +0 -0
- /package/configurations/language/swift/{semgrep → tool-files/semgrep}/swift.yml +0 -0
- /package/configurations/platform/cloudflare/{semgrep → tool-files/semgrep}/cloudflare.yml +0 -0
- /package/configurations/platform/supabase/{semgrep → tool-files/semgrep}/supabase.yml +0 -0
|
@@ -1,46 +1,36 @@
|
|
|
1
1
|
[configuration]
|
|
2
|
-
title = "Spelling"
|
|
3
2
|
always_selected = true
|
|
4
|
-
description = "typos over every text file, with the words
|
|
3
|
+
description = "Runs typos over every text file, with the allowed words and a reason for each."
|
|
4
|
+
title = "Spelling"
|
|
5
5
|
|
|
6
6
|
[files]
|
|
7
7
|
paths = ["**"]
|
|
8
8
|
|
|
9
9
|
[[tool]]
|
|
10
|
-
name = "typos"
|
|
11
|
-
version = "1.43.5"
|
|
12
|
-
mise = "typos"
|
|
13
10
|
brew = "typos-cli"
|
|
14
11
|
cargo = "typos-cli"
|
|
15
|
-
winget = "crate-ci.typos"
|
|
16
|
-
scoop = "typos"
|
|
17
12
|
github = { name = "crate-ci/typos", version = "v1.43.5" }
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
shared = false
|
|
25
|
-
|
|
26
|
-
[[tool.replace]]
|
|
27
|
-
file = "_typos.toml"
|
|
28
|
-
shared = false
|
|
13
|
+
mise = "typos"
|
|
14
|
+
name = "typos"
|
|
15
|
+
replace = ["typos.toml", ".typos.toml", "_typos.toml"]
|
|
16
|
+
scoop = "typos"
|
|
17
|
+
version = "1.43.5"
|
|
18
|
+
winget = "crate-ci.typos"
|
|
29
19
|
|
|
30
20
|
[[tool_file]]
|
|
21
|
+
per_scope = true
|
|
31
22
|
target = ".gspot/config/typos.toml"
|
|
32
23
|
tool = "typos"
|
|
33
|
-
per_scope = true
|
|
34
24
|
|
|
35
25
|
[[check]]
|
|
36
|
-
name = "typos"
|
|
37
|
-
example = "A misspelled word in selected text reports a spelling finding. Correct it and rerun. Filename findings require a manual rename and reference updates."
|
|
38
|
-
level = "recommended"
|
|
39
|
-
stage = "commit"
|
|
40
26
|
command = ["typos", "--isolated", "--config", "{tool_file:typos}", "--force-exclude", "--format", "json", "--color", "never", "{files}"]
|
|
41
|
-
|
|
27
|
+
example = "A misspelled word reports a finding. Correct it, and for a file name, rename the file and update each reference to it."
|
|
42
28
|
exit_codes = [2]
|
|
29
|
+
fix = ["typos", "--isolated", "--config", "{tool_file:typos}", "--force-exclude", "--no-check-filenames", "--write-changes", "--color", "never", "{files}"]
|
|
30
|
+
help = "Fix the spelling, or write the real name and its reason in the root allowed_words setting."
|
|
31
|
+
level = "recommended"
|
|
32
|
+
name = "typos"
|
|
43
33
|
output = { format = "typos" }
|
|
34
|
+
stage = "commit"
|
|
44
35
|
summary = "Finds misspelled words in code, comments, and documentation."
|
|
45
36
|
why = "A typo in an identifier spreads to every caller; in prose it costs the reader a second look."
|
|
46
|
-
help = "Fix the spelling, or write the real name and its reason in the root allowed_words setting."
|
|
@@ -1,70 +1,70 @@
|
|
|
1
1
|
[configuration]
|
|
2
|
-
title = "Structure"
|
|
3
2
|
always_selected = true
|
|
4
|
-
description = "
|
|
3
|
+
description = "Structural rules that no standard linter ships, for every language: wrappers, barrels, lone files, and size limits."
|
|
4
|
+
title = "Structure"
|
|
5
5
|
|
|
6
6
|
[files]
|
|
7
7
|
languages = true
|
|
8
8
|
|
|
9
9
|
[[check]]
|
|
10
|
+
example = "With TypeScript at level `all`, a `feature/only.ts` alone in its folder reports `lone-file`. Move it up beside related code, and update its imports."
|
|
11
|
+
help = "Move the file up beside its neighbors, or use `gspot ignore structure/lone-files` with paths and a reason."
|
|
12
|
+
level = "all"
|
|
10
13
|
name = "lone-files"
|
|
11
|
-
example = "With the TypeScript configuration at level `all`, `feature/only.ts` reports `lone-file` when it is the folder's only code file. Move it beside related files and update references, or keep the folder when a second substantial file belongs to that feature. Adding `feature/second.ts` makes this folder contain two code files."
|
|
12
14
|
runs = "scope"
|
|
13
|
-
level = "all"
|
|
14
15
|
stage = "commit"
|
|
15
16
|
summary = "Finds a folder that holds one code file and nothing else."
|
|
16
|
-
why = "A folder
|
|
17
|
-
help = "Move the file up beside its neighbors, or use gspot ignore structure/lone-files with paths and a reason."
|
|
17
|
+
why = "A folder with one file adds a level to every import path and groups nothing."
|
|
18
18
|
|
|
19
19
|
[[check]]
|
|
20
|
-
name = "shared-prefixes"
|
|
21
20
|
example = "Sibling files `asset-card.ts`, `asset-list.ts`, and `asset-row.ts` share a repeated prefix. Move them into `asset/` with names `card.ts`, `list.ts`, and `row.ts`, then update imports."
|
|
22
|
-
|
|
21
|
+
help = "Move the files into a folder named after the shared prefix, or allow the set with a reason."
|
|
23
22
|
level = "all"
|
|
23
|
+
name = "shared-prefixes"
|
|
24
|
+
runs = "scope"
|
|
24
25
|
stage = "commit"
|
|
25
|
-
summary = "Finds sibling files that share a name prefix,
|
|
26
|
-
why = "
|
|
27
|
-
help = "Move the files into a folder named after the shared prefix, or allow the set with a reason."
|
|
26
|
+
summary = "Finds sibling files that share a name prefix, such as `asset-card`, `asset-list`, and `asset-row`."
|
|
27
|
+
why = "Sibling files with one prefix split a single concept by suffix, and a folder of that name groups them."
|
|
28
28
|
|
|
29
29
|
[[check]]
|
|
30
|
+
example = "A `report.ts` beside a `report/` folder reports a clash. Rename one after its job, and update each reference."
|
|
31
|
+
help = "Rename the file or the folder so their stems differ."
|
|
32
|
+
level = "all"
|
|
30
33
|
name = "file-folder-clashes"
|
|
31
|
-
example = "Sibling entries `report.ts` and `report/` have the same stem and report a collision. Rename the file or directory after its distinct responsibility and update every reference."
|
|
32
34
|
runs = "scope"
|
|
33
|
-
level = "all"
|
|
34
35
|
stage = "commit"
|
|
35
|
-
summary = "Finds a file and a folder
|
|
36
|
+
summary = "Finds a file and a folder with one stem in the same place, such as `turn.ts` beside `turn/`."
|
|
36
37
|
why = "An import of ./turn names both, and a reader cannot tell which one loads."
|
|
37
|
-
help = "Rename the file or the folder so their stems differ."
|
|
38
38
|
|
|
39
39
|
[[check]]
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
example = "A Python file over its line limit reports the count. Split it by responsibility."
|
|
41
|
+
files = { extensions = [".sh", ".bash", ".zsh", ".bats", ".py", ".pyi", ".sql", ".pgsql", ".psql"], tags = ["shebang:shell"], kinds = ["source"] }
|
|
42
|
+
help = "Split the file by responsibility, or raise limits.`<language>`.file_lines with a reason."
|
|
42
43
|
level = "all"
|
|
43
|
-
|
|
44
|
+
name = "long-files"
|
|
44
45
|
runs = "scope"
|
|
45
|
-
|
|
46
|
-
summary = "Checks
|
|
46
|
+
stage = "commit"
|
|
47
|
+
summary = "Checks the code line count of each file against the limit for its language."
|
|
47
48
|
why = "A long file hides independent responsibilities from the reader."
|
|
48
|
-
help = "Split the file by its responsibility, or raise its limits.`<language>`.file_lines with a reason."
|
|
49
49
|
|
|
50
50
|
[[check]]
|
|
51
|
-
|
|
52
|
-
|
|
51
|
+
example = "A Bash function that only calls another reports a finding. Inline the call at each caller, and delete the wrapper."
|
|
52
|
+
files = { extensions = [".ts", ".tsx", ".js", ".mjs", ".cjs", ".py", ".swift", ".sh", ".bash", ".zsh", ".bats"], tags = ["shell"], kinds = ["source"] }
|
|
53
|
+
help = "Inline a forwarding function at its calls and delete it. Split independent statements into the files that use them."
|
|
53
54
|
level = "all"
|
|
54
|
-
|
|
55
|
+
name = "trivial-functions"
|
|
55
56
|
runs = "scope"
|
|
56
|
-
|
|
57
|
+
stage = "commit"
|
|
57
58
|
summary = "Finds functions with too few statements and files that only forward to other code."
|
|
58
59
|
why = "A function of one statement makes the reader jump for nothing."
|
|
59
|
-
help = "Inline a forwarding function at its calls and delete it. Split independent statements into the files that use them."
|
|
60
60
|
|
|
61
61
|
[[check]]
|
|
62
|
-
|
|
63
|
-
|
|
62
|
+
example = "A Python file that uses `os.environ` outside `architecture.roles.environment_readers` reports a finding. Move that access into an environment reader, and pass the value to callers."
|
|
63
|
+
files = { extensions = [".py", ".swift", ".sh", ".bash", ".zsh", ".bats"], tags = ["shell"], kinds = ["source"] }
|
|
64
|
+
help = "Move the environment read into a file listed in architecture.roles.environment_readers, then pass the value to callers."
|
|
64
65
|
level = "all"
|
|
65
|
-
|
|
66
|
+
name = "environment-readers"
|
|
66
67
|
runs = "scope"
|
|
67
|
-
|
|
68
|
+
stage = "commit"
|
|
68
69
|
summary = "Finds environment reads outside the files listed in architecture.roles.environment_readers."
|
|
69
70
|
why = "Environment reads spread through the code hide which settings a program needs."
|
|
70
|
-
help = "Move the environment read into a file listed in architecture.roles.environment_readers, then pass the value to callers."
|
|
@@ -1,33 +1,33 @@
|
|
|
1
1
|
[configuration]
|
|
2
|
-
title = "Ansible"
|
|
3
2
|
description = "Ansible playbooks, roles, and collections checked by ansible-lint."
|
|
3
|
+
title = "Ansible"
|
|
4
4
|
|
|
5
5
|
[files]
|
|
6
6
|
paths = ["**/ansible.cfg", "**/galaxy.yml", "**/requirements.yml", "**/roles/*/tasks/main.yml"]
|
|
7
7
|
|
|
8
8
|
[[tool]]
|
|
9
|
-
name = "ansible-lint"
|
|
10
|
-
version = "26.8.0"
|
|
11
|
-
min_version = "24.0.0"
|
|
12
|
-
pypi = "ansible-lint"
|
|
13
|
-
mise = "pipx:ansible-lint"
|
|
14
9
|
brew = "ansible-lint"
|
|
15
10
|
builds = ["macos", "linux"]
|
|
11
|
+
min_version = "24.0.0"
|
|
12
|
+
mise = "pipx:ansible-lint"
|
|
13
|
+
name = "ansible-lint"
|
|
14
|
+
pypi = "ansible-lint"
|
|
15
|
+
version = "26.8.0"
|
|
16
16
|
|
|
17
17
|
[[tool_file]]
|
|
18
|
+
per_scope = true
|
|
18
19
|
target = ".gspot/config/ansible-lint.yml"
|
|
19
20
|
tool = "ansible-lint"
|
|
20
|
-
per_scope = true
|
|
21
21
|
|
|
22
22
|
[[check]]
|
|
23
|
-
|
|
24
|
-
example = "A task
|
|
23
|
+
command = ["ansible-lint", "-c", "{tool_file:ansible-lint}", "--offline", "--nocolor", "-f", "pep8", "--profile", "{level:moderate:production}"]
|
|
24
|
+
example = "A task with `ansible.builtin.command: systemctl restart nginx` reports `command-instead-of-module`. Use `ansible.builtin.systemd` with `name: nginx` and `state: restarted` instead."
|
|
25
|
+
files = { extensions = [".yml", ".yaml", ".cfg", ".j2"] }
|
|
26
|
+
help = "Change the task the way the rule says. Turn one rule off with `gspot ignore ansible/ansible-lint --rule <id> --reason \"<why>\"`."
|
|
25
27
|
level = "recommended"
|
|
26
|
-
|
|
28
|
+
name = "ansible-lint"
|
|
27
29
|
runs = "scope"
|
|
30
|
+
stage = "commit"
|
|
31
|
+
summary = "Runs the moderate ansible-lint profile at recommended and production at all, beside each ansible.cfg or at the scope root."
|
|
28
32
|
tool = "ansible-lint"
|
|
29
|
-
|
|
30
|
-
files = { extensions = [".yml", ".yaml", ".cfg", ".j2"] }
|
|
31
|
-
summary = "Runs the moderate ansible-lint profile at recommended and production at all, beside each ansible.cfg or at the selected scope root."
|
|
32
|
-
why = "A playbook runs as root on production hosts, and a task that is not idempotent changes them on every run."
|
|
33
|
-
help = "Change the task the way the rule says. Turn one rule off with gspot ignore ansible/ansible-lint --rule `<id>` --reason \"`<why>`\"."
|
|
33
|
+
why = "Playbooks run as root on production hosts, and a non-idempotent task changes them each time."
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
prefix_collisions = { prefixes = ["docker"] }
|
|
2
|
-
|
|
3
1
|
allowed_words = ["Docker", "Trivy"]
|
|
2
|
+
|
|
4
3
|
[configuration]
|
|
4
|
+
description = "Dockerfiles and Compose files: hadolint, Compose parsing, a `.dockerignore` beside each Dockerfile, and Trivy scans."
|
|
5
5
|
title = "Docker"
|
|
6
|
-
description = "Dockerfiles and Compose files: hadolint, a Compose file that parses, an ignore file beside every Dockerfile, and Trivy over the configuration."
|
|
7
6
|
|
|
8
7
|
[detect]
|
|
9
8
|
paths = ["**/Dockerfile", "**/Dockerfile.*", "**/*.dockerfile", "**/docker-compose*.yml", "**/docker-compose*.yaml", "**/compose*.yml", "**/compose*.yaml", "!**/*.dockerignore"]
|
|
@@ -11,117 +10,106 @@ paths = ["**/Dockerfile", "**/Dockerfile.*", "**/*.dockerfile", "**/docker-compo
|
|
|
11
10
|
[files]
|
|
12
11
|
paths = ["**/Dockerfile", "**/Dockerfile.*", "**/*.dockerfile", "**/docker-compose*.yml", "**/docker-compose*.yaml", "**/compose*.yml", "**/compose*.yaml", "**/.dockerignore", "**/*.dockerignore"]
|
|
13
12
|
|
|
13
|
+
[shared_prefixes]
|
|
14
|
+
prefixes = ["docker"]
|
|
15
|
+
|
|
14
16
|
[[tool]]
|
|
15
|
-
name = "hadolint"
|
|
16
|
-
version = "2.14.0"
|
|
17
|
-
mise = "hadolint"
|
|
18
17
|
brew = "hadolint"
|
|
19
18
|
github = { name = "hadolint/hadolint", version = "v2.14.0" }
|
|
19
|
+
mise = "hadolint"
|
|
20
|
+
name = "hadolint"
|
|
21
|
+
replace = [".hadolint.yaml", ".hadolint.yml"]
|
|
20
22
|
scoop = "hadolint"
|
|
21
|
-
|
|
22
|
-
file = ".hadolint.yaml"
|
|
23
|
-
shared = false
|
|
24
|
-
|
|
25
|
-
[[tool.replace]]
|
|
26
|
-
file = ".hadolint.yml"
|
|
27
|
-
shared = false
|
|
23
|
+
version = "2.14.0"
|
|
28
24
|
|
|
29
25
|
[[tool]]
|
|
30
|
-
name = "trivy"
|
|
31
|
-
version = "0.69.3"
|
|
32
|
-
mise = "trivy"
|
|
33
26
|
brew = "trivy"
|
|
34
27
|
github = { name = "aquasecurity/trivy", version = "v0.69.3" }
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
[[tool.replace]]
|
|
40
|
-
file = ".trivyignore"
|
|
41
|
-
shared = false
|
|
28
|
+
mise = "trivy"
|
|
29
|
+
name = "trivy"
|
|
30
|
+
replace = ["trivy.yaml", ".trivyignore"]
|
|
31
|
+
version = "0.69.3"
|
|
42
32
|
|
|
43
33
|
[[tool]]
|
|
44
|
-
name = "docker"
|
|
45
34
|
install_hint = "install Docker Desktop or the docker engine"
|
|
35
|
+
name = "docker"
|
|
46
36
|
system = true
|
|
47
37
|
|
|
48
38
|
[[tool_file]]
|
|
39
|
+
per_scope = true
|
|
49
40
|
target = ".gspot/config/hadolint.yml"
|
|
50
41
|
tool = "hadolint"
|
|
51
|
-
per_scope = true
|
|
52
|
-
rule_keys = ["ignored"]
|
|
53
42
|
|
|
54
43
|
[[tool_file]]
|
|
44
|
+
per_scope = true
|
|
55
45
|
target = ".gspot/config/trivy.yml"
|
|
56
46
|
tool = "trivy"
|
|
57
|
-
per_scope = true
|
|
58
47
|
|
|
59
48
|
[[tool_file]]
|
|
60
|
-
|
|
49
|
+
per_scope = true
|
|
61
50
|
target = ".gspot/config/trivyignore"
|
|
62
51
|
tool = "trivy"
|
|
63
|
-
per_scope = true
|
|
64
52
|
|
|
65
53
|
[[check]]
|
|
66
|
-
name = "hadolint"
|
|
67
|
-
example = "The instruction `FROM node:latest` reports DL3007 because the tag changes over time. Select a reviewed, explicit version tag or digest and rerun."
|
|
68
|
-
level = "recommended"
|
|
69
|
-
stage = "commit"
|
|
70
54
|
command = ["hadolint", "--no-color", "--config", "{tool_file:hadolint}", "{files}"]
|
|
55
|
+
example = "`FROM node:latest` reports DL3007, because that tag moves. Pin an explicit version tag or a digest."
|
|
71
56
|
files = { paths = ["**/Dockerfile", "**/Dockerfile.*", "**/*.dockerfile", "!**/*.dockerignore"] }
|
|
57
|
+
help = "Change the instruction the way the rule says. Turn one rule off with `gspot ignore docker/hadolint --rule <id> --reason \"<why>\"`."
|
|
58
|
+
level = "recommended"
|
|
59
|
+
name = "hadolint"
|
|
72
60
|
output = { format = "regex", pattern = "^(?<file>.+?):(?<line>\\d+) (?<rule>[A-Z]+\\d+) [a-z]+: (?<message>.*)$" }
|
|
61
|
+
stage = "commit"
|
|
73
62
|
summary = "Lints every Dockerfile, and runs ShellCheck over its RUN lines."
|
|
74
|
-
why = "An unpinned base image
|
|
75
|
-
help = "Change the instruction the way the rule says. Turn one rule off with gspot ignore docker/hadolint --rule `<id>` --reason \"`<why>`\"."
|
|
63
|
+
why = "An unpinned base image makes a build nobody can repeat, and a cache left in a layer bloats the result."
|
|
76
64
|
|
|
77
65
|
[[check]]
|
|
78
|
-
name = "compose"
|
|
79
|
-
example = "A Compose service with an unknown key such as `bogus` fails configuration validation. Remove the key or replace it with the supported setting for the intended behavior."
|
|
80
|
-
level = "recommended"
|
|
81
|
-
stage = "push"
|
|
82
|
-
needs = ["docker"]
|
|
83
|
-
tool = "docker"
|
|
84
|
-
runs = "scope"
|
|
85
66
|
command = ["docker", "compose", "-f", "{file}", "config", "--quiet", "--no-env-resolution"]
|
|
67
|
+
example = "A Compose service with the unknown key `bogus` fails to parse. Remove the key, or use a supported one."
|
|
86
68
|
files = { paths = ["**/docker-compose*.yml", "**/docker-compose*.yaml", "**/compose*.yml", "**/compose*.yaml"] }
|
|
87
|
-
output = { format = "lines" }
|
|
88
|
-
summary = "Asks Docker Compose to parse every Compose file, which needs no running daemon."
|
|
89
|
-
why = "A Compose file that is valid YAML can still name a key Compose refuses, and the first person to learn that is deploying."
|
|
90
69
|
help = "Read the message Compose prints; it names the key and the service."
|
|
70
|
+
level = "recommended"
|
|
71
|
+
name = "compose"
|
|
72
|
+
needs = ["docker"]
|
|
73
|
+
output = { format = "lines" }
|
|
74
|
+
runs = "scope"
|
|
75
|
+
stage = "push"
|
|
76
|
+
summary = "Parses every Compose file with `docker compose config`, which needs no running daemon."
|
|
77
|
+
tool = "docker"
|
|
78
|
+
why = "Valid YAML can still hold a key that Compose rejects, and otherwise the first sign comes during a deploy."
|
|
91
79
|
|
|
92
80
|
[[check]]
|
|
93
|
-
|
|
94
|
-
|
|
81
|
+
example = "A Dockerfile with no `.dockerignore` beside it reports a finding. Add one that excludes the paths the finding names, such as `.git` and installed dependencies."
|
|
82
|
+
help = "Add a .dockerignore beside the Dockerfile with the paths the message names."
|
|
95
83
|
level = "recommended"
|
|
96
|
-
|
|
84
|
+
name = "dockerignore"
|
|
97
85
|
runs = "once"
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
86
|
+
stage = "commit"
|
|
87
|
+
summary = "Checks that an ignore file sits beside every Dockerfile and keeps the `.git` folder, installed dependencies, and environment files out of the build."
|
|
88
|
+
why = "Without it, the daemon receives the whole folder, and a `COPY` of it puts the history and secrets into the image."
|
|
101
89
|
|
|
102
90
|
[[check]]
|
|
103
|
-
name = "trivy-config"
|
|
104
|
-
example = "A Dockerfile whose final application stage runs as root can report a container-security finding. Create an unprivileged user, grant it only required file access, and select it with `USER` before running the application."
|
|
105
|
-
level = "recommended"
|
|
106
|
-
stage = "push"
|
|
107
|
-
runs = "scope"
|
|
108
|
-
run_in_copy = true
|
|
109
91
|
command = ["trivy", "config", "--misconfig-scanners", "dockerfile", "--quiet", "--skip-check-update", "--config", "{tool_file:trivy}", "--ignorefile", "{tool_file:trivyignore}", "--exit-code", "10", "--format", "sarif", "{root}"]
|
|
110
|
-
|
|
92
|
+
example = "A Dockerfile whose final stage runs as root reports a finding. Create an unprivileged user, and switch to it with `USER` before the application starts."
|
|
111
93
|
exit_codes = [10]
|
|
94
|
+
help = "Change the file the way the message says. Accept one advisory with `gspot ignore docker/trivy-config --rule <id> --reason \"...\"`."
|
|
95
|
+
level = "recommended"
|
|
96
|
+
name = "trivy-config"
|
|
112
97
|
output = { format = "sarif" }
|
|
98
|
+
run_in_copy = true
|
|
99
|
+
runs = "scope"
|
|
100
|
+
stage = "push"
|
|
113
101
|
summary = "Scans Dockerfiles for HIGH and CRITICAL misconfigurations, including a root user and exposed secrets."
|
|
114
|
-
|
|
115
|
-
|
|
102
|
+
tool = "trivy"
|
|
103
|
+
why = "A root user turns any bug in the service into full control of the container."
|
|
116
104
|
|
|
117
105
|
[[check]]
|
|
118
|
-
|
|
119
|
-
|
|
106
|
+
example = "An image with a vulnerable package reports the advisory. Move to an image version with the fixed package."
|
|
107
|
+
help = "Move to a newer tag of the image. Accept one advisory with `gspot ignore docker/trivy-image --rule <id> --reason \"...\"`."
|
|
120
108
|
level = "recommended"
|
|
121
|
-
|
|
122
|
-
runs = "scope"
|
|
109
|
+
name = "trivy-image"
|
|
123
110
|
needs = ["docker"]
|
|
124
|
-
|
|
111
|
+
runs = "scope"
|
|
112
|
+
stage = "manual"
|
|
125
113
|
summary = "Scans every image a Compose file names for known vulnerabilities in its packages."
|
|
126
|
-
|
|
127
|
-
|
|
114
|
+
tool = "trivy"
|
|
115
|
+
why = "A base image carries hundreds of packages, and new advisories keep arriving after you pick it."
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
# Docker
|
|
2
2
|
|
|
3
|
+
Read this rule when you change a Dockerfile, a Compose file, or `.dockerignore`.
|
|
4
|
+
|
|
3
5
|
## Image inputs
|
|
4
6
|
|
|
5
|
-
Select a base image that supports the application's runtime, target architecture,
|
|
7
|
+
Select a base image that supports the application's runtime, target architecture, system libraries,
|
|
6
8
|
and certificate requirements. Tags can change, so pin a reviewed digest when the build requires
|
|
7
9
|
immutable input, and keep an update process for security fixes: a digest never patches itself.
|
|
8
10
|
|
|
9
|
-
Use a supported runtime release. For
|
|
11
|
+
Use a supported runtime release. For compiled modules, keep the build and runtime operating system,
|
|
10
12
|
libc, and architecture compatible. Alpine, Debian, and distroless images have different runtime
|
|
11
13
|
and operational requirements; no single variant fits every application.
|
|
12
14
|
|
|
@@ -48,7 +50,7 @@ CMD ["node", "dist/main.js"]
|
|
|
48
50
|
Use the package manager the project declares; for Bun, its pinned version with
|
|
49
51
|
`bun install --frozen-lockfile`, adding `--production` for runtime dependencies. The final image
|
|
50
52
|
holds a package-manager binary only when the runtime uses it. A statically linked `server` built
|
|
51
|
-
for the target
|
|
53
|
+
for the target system needs no package manager or shell, only the certificates, time-zone data,
|
|
52
54
|
or other runtime files it reads.
|
|
53
55
|
|
|
54
56
|
```dockerfile
|
|
@@ -61,11 +63,11 @@ ENTRYPOINT ["/server"]
|
|
|
61
63
|
## Package installation and downloads
|
|
62
64
|
|
|
63
65
|
hadolint reports unpinned images and packages, apt cleanup, `ADD` for local files, and shell-form
|
|
64
|
-
commands.
|
|
66
|
+
commands. Also apply these requirements:
|
|
65
67
|
|
|
66
68
|
- Install application dependencies from the declared lockfile without updating it during the build.
|
|
67
|
-
- Refresh repository metadata and install packages in the same `RUN`, so
|
|
68
|
-
|
|
69
|
+
- Refresh repository metadata and install packages in the same `RUN`, so a stale cache cannot
|
|
70
|
+
pick an unintended version.
|
|
69
71
|
- Refresh base images for operating-system fixes. A targeted package upgrade needs an explicit
|
|
70
72
|
dependency change, never an unbounded distribution upgrade in every build.
|
|
71
73
|
- Verify a downloaded executable's digest or signature before installing it.
|
|
@@ -77,7 +79,7 @@ commands. Review these additional requirements:
|
|
|
77
79
|
|
|
78
80
|
Put stable build inputs before frequently changing application source when that improves cache
|
|
79
81
|
reuse. Put substantial shell behavior in an existing script. Keep the final image's user,
|
|
80
|
-
working
|
|
82
|
+
working folder, environment, and startup command in documented locations. Do not add a wrapper script
|
|
81
83
|
for a command the container can run directly.
|
|
82
84
|
|
|
83
85
|
## Build context and ignore files
|
|
@@ -92,11 +94,11 @@ Dockerfile that uses it. A deny-by-default context suits a small, stable input s
|
|
|
92
94
|
|
|
93
95
|
Use BuildKit secret mounts for private registry authentication and other build credentials.
|
|
94
96
|
Read the secret only inside the `RUN` instruction that requires it. Copying it into a layer keeps
|
|
95
|
-
it in image history even
|
|
97
|
+
it in image history even after a later step removes it.
|
|
96
98
|
|
|
97
99
|
## Shell and process behavior
|
|
98
100
|
|
|
99
|
-
|
|
101
|
+
Match `RUN` syntax to the configured shell; the default one does not run Bash. A required
|
|
100
102
|
entrypoint script validates configuration and uses `exec` for its final handoff. A documented
|
|
101
103
|
process supervisor forwards signals and reaps its children, and no init wrapper hides missing
|
|
102
104
|
shutdown behavior in the application.
|
|
@@ -110,9 +112,9 @@ The application's shutdown limit fits the orchestrator's grace period.
|
|
|
110
112
|
service sets `NODE_ENV=production` where the runtime expects it.
|
|
111
113
|
- Expose only the required ports, and bind private local services to localhost. Never add Linux
|
|
112
114
|
capabilities, public debug ports, or disabled TLS verification to make a build or service work.
|
|
113
|
-
- Resource limits fit the deployment and leave room for
|
|
114
|
-
overhead beyond
|
|
115
|
-
when the task
|
|
115
|
+
- Resource limits fit the deployment and leave room for off-heap memory, buffers, and runtime
|
|
116
|
+
overhead beyond the language heap. Ask the user for memory measurements before changing a limit
|
|
117
|
+
when the task has none.
|
|
116
118
|
|
|
117
119
|
## Compose
|
|
118
120
|
|
|
@@ -123,7 +125,7 @@ development source or host dependencies.
|
|
|
123
125
|
|
|
124
126
|
## Verification
|
|
125
127
|
|
|
126
|
-
Do not build or run images unless the user asks or the repository's checks require it. Give the user a
|
|
128
|
+
Do not build or run images unless the user asks or the repository's checks require it. Give the user a checklist: image user, command, runtime files, permissions, exposed ports, startup,
|
|
127
129
|
readiness, shutdown, and resource limits. Image documentation names the current build arguments,
|
|
128
130
|
supported platforms, runtime environment, and artifact paths.
|
|
129
131
|
|
|
@@ -1,76 +1,56 @@
|
|
|
1
1
|
allowed_words = ["GitHub"]
|
|
2
|
+
|
|
2
3
|
[configuration]
|
|
4
|
+
description = "GitHub Actions workflows: actionlint for syntax and expressions, and zizmor for security audits and action pins."
|
|
3
5
|
title = "GitHub Actions"
|
|
4
|
-
description = "GitHub Actions workflows: actionlint for syntax and expressions, pinact for the commits actions are pinned to, and zizmor for security audits."
|
|
5
6
|
|
|
6
7
|
[files]
|
|
7
8
|
paths = ["**/.github/workflows/*.{yml,yaml}", "**/action.{yml,yaml}"]
|
|
8
9
|
|
|
9
10
|
[[tool]]
|
|
10
|
-
name = "actionlint"
|
|
11
|
-
version = "1.7.12"
|
|
12
|
-
mise = "actionlint"
|
|
13
11
|
brew = "actionlint"
|
|
14
12
|
github = { name = "rhysd/actionlint", version = "v1.7.12" }
|
|
13
|
+
mise = "actionlint"
|
|
14
|
+
name = "actionlint"
|
|
15
|
+
version = "1.7.12"
|
|
15
16
|
|
|
16
17
|
[[tool]]
|
|
17
18
|
name = "shellcheck"
|
|
18
19
|
|
|
19
20
|
[[tool]]
|
|
20
|
-
name = "pinact"
|
|
21
|
-
crash_pattern = '(?:ERROR|FATAL).*?(?:\b(?:401|403|408|429|5[0-9]{2})\b|dial tcp|TLS handshake|x509:|context deadline exceeded|connection reset|no such host)'
|
|
22
|
-
version = "5.0.0"
|
|
23
|
-
mise = "pinact"
|
|
24
|
-
brew = "pinact"
|
|
25
|
-
github = { name = "suzuki-shunsuke/pinact", version = "v5.0.0" }
|
|
26
|
-
|
|
27
|
-
[[tool]]
|
|
28
|
-
name = "zizmor"
|
|
29
|
-
version = "1.30.1"
|
|
30
|
-
mise = "zizmor"
|
|
31
|
-
pypi = "zizmor"
|
|
32
21
|
brew = "zizmor"
|
|
33
22
|
cargo = "zizmor"
|
|
23
|
+
mise = "zizmor"
|
|
24
|
+
name = "zizmor"
|
|
25
|
+
pypi = "zizmor"
|
|
26
|
+
version = "1.30.1"
|
|
34
27
|
|
|
35
28
|
[[tool_file]]
|
|
36
|
-
source = "zizmor.yml"
|
|
37
29
|
target = ".gspot/config/zizmor.yml"
|
|
38
30
|
tool = "zizmor"
|
|
39
31
|
|
|
40
32
|
[[check]]
|
|
41
|
-
name = "actionlint"
|
|
42
|
-
example = "A workflow using an unknown expression context such as `${{ unknown.value }}` reports an actionlint error. Replace it with a supported context and property for that workflow location."
|
|
43
|
-
level = "recommended"
|
|
44
|
-
stage = "commit"
|
|
45
|
-
tool = ["actionlint", "shellcheck"]
|
|
46
33
|
command = ["actionlint", "-no-color", "{files}"]
|
|
47
|
-
|
|
34
|
+
example = "A workflow expression with the unknown context `${{ unknown.value }}` reports an error. Use a supported context and property there instead."
|
|
48
35
|
exit_codes = [1]
|
|
36
|
+
files = { paths = ["**/.github/workflows/*.{yml,yaml}"] }
|
|
37
|
+
help = "Fix the line actionlint names."
|
|
38
|
+
level = "recommended"
|
|
39
|
+
name = "actionlint"
|
|
49
40
|
output = { format = "regex", pattern = "^(?<file>[^:]+):(?<line>\\d+):(?<column>\\d+): (?<message>.*?) \\[(?<rule>[a-z-]+)\\]$" }
|
|
41
|
+
stage = "commit"
|
|
50
42
|
summary = "Checks every GitHub Actions workflow with actionlint: syntax, expressions, action inputs, and shell steps."
|
|
43
|
+
tool = ["actionlint", "shellcheck"]
|
|
51
44
|
why = "A workflow error surfaces on the first push after the change, in CI, where it costs a round trip."
|
|
52
|
-
help = "Fix the line actionlint names."
|
|
53
45
|
|
|
54
46
|
[[check]]
|
|
55
|
-
name = "pinact"
|
|
56
|
-
example = "An action reference such as `actions/checkout@v4` without a full commit pin reports an unpinned action. Resolve a reviewed release to its full commit SHA and record the matching version comment beside the pin."
|
|
57
|
-
level = "recommended"
|
|
58
|
-
stage = "push"
|
|
59
|
-
needs = ["network"]
|
|
60
|
-
command = ["pinact", "run", "--verify-comment", "--check", "{files}"]
|
|
61
|
-
output = { format = "lines" }
|
|
62
|
-
summary = "Checks that each GitHub action has a full commit pin that exists and a matching version comment."
|
|
63
|
-
why = "A tag can move between runs, a nonexistent commit prevents the workflow from starting, and a wrong version comment hides the intended release."
|
|
64
|
-
help = "Replace the invalid action pin with a verified commit and its matching version comment."
|
|
65
|
-
|
|
66
|
-
[[check]]
|
|
67
|
-
name = "zizmor"
|
|
68
|
-
example = "A workflow interpolating pull-request text directly into a shell command can report a template-injection audit. Pass the text through a step environment variable and quote its expansion instead of interpolating it into shell code."
|
|
69
|
-
level = "recommended"
|
|
70
|
-
stage = "commit"
|
|
71
47
|
command = ["zizmor", "--offline", "--no-progress", "--format", "github", "--config", "{tool_file:zizmor}", "{files}"]
|
|
48
|
+
example = "A workflow that puts pull request text straight into a shell command reports `template-injection`. Pass the text through a step environment variable, and quote its expansion."
|
|
72
49
|
exit_codes = [11, 12, 13, 14]
|
|
50
|
+
help = "Apply the fix zizmor names, or turn one audit off with `gspot ignore github-actions/zizmor --rule <audit> --reason \"<why>\"`."
|
|
51
|
+
level = "recommended"
|
|
52
|
+
name = "zizmor"
|
|
73
53
|
output = { format = "regex", pattern = "^::(?:warning|error|notice) file=(?<file>[^,]+),line=(?<line>\\d+),title=(?<rule>[^:]+)::(?<message>.*)$" }
|
|
54
|
+
stage = "commit"
|
|
74
55
|
summary = "Audits GitHub Actions workflows and composite actions with zizmor for template injection, excessive permissions, and dangerous triggers."
|
|
75
56
|
why = "A workflow runs with the repository's credentials; an injectable expression can hand them to a stranger."
|
|
76
|
-
help = "Apply the fix zizmor names, or turn one audit off with gspot ignore github-actions/zizmor --rule `<audit>` --reason \"`<why>`\"."
|
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
# GitHub Actions
|
|
2
2
|
|
|
3
|
+
Read this rule when you change a GitHub Actions workflow or action.
|
|
4
|
+
|
|
3
5
|
## Workflow shape
|
|
4
6
|
|
|
5
|
-
- Every job has `timeout-minutes`.
|
|
6
|
-
|
|
7
|
+
- Every job has `timeout-minutes`.
|
|
8
|
+
- Every workflow that can run twice for one ref has a `concurrency` group. Cancel a run in progress only for a pull
|
|
9
|
+
request. Never cancel a run on the default branch or a tag; its result records that commit.
|
|
7
10
|
- Pin a runner image such as `ubuntu-24.04` for each job. Do not use `ubuntu-latest`.
|
|
8
|
-
- No `continue-on-error` without a reason comment. Required
|
|
9
|
-
- Upload diagnostics after failed checks with an explicit status condition. Deployments and
|
|
10
|
-
|
|
11
|
+
- No `continue-on-error` without a reason comment. Required steps that break must fail the job.
|
|
12
|
+
- Upload diagnostics after failed checks with an explicit status condition. Deployments and release publication
|
|
13
|
+
require successful prerequisites.
|
|
14
|
+
- Before a release job publishes a package or creates a release, it runs the tests or needs the job that does.
|
|
11
15
|
|
|
12
16
|
## Repository actions and secrets
|
|
13
17
|
|
|
@@ -17,19 +21,19 @@
|
|
|
17
21
|
|
|
18
22
|
## Scripts
|
|
19
23
|
|
|
20
|
-
- Declare the shell required by the script. The explicit Bash shell in GitHub Actions
|
|
21
|
-
`pipefail`, but
|
|
24
|
+
- Declare the shell required by the script. The explicit Bash shell in GitHub Actions turns on `-e` and
|
|
25
|
+
`pipefail`, but not `-u`. Enable required options and validate inputs explicitly.
|
|
22
26
|
- Key caches on the lockfile hash and the runtime version. Restore keys never match a
|
|
23
27
|
different lockfile.
|
|
24
28
|
|
|
25
29
|
## Outputs
|
|
26
30
|
|
|
27
31
|
- Artifacts and summaries name the job and the ref. Set retention explicitly.
|
|
28
|
-
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
32
|
+
- Each job leaves a result that a later one, a deployment, or a person uses. Do not upload an artifact that no job
|
|
33
|
+
downloads. Do not build the same output in two workflows.
|
|
34
|
+
- Give deploy credentials only to the job that deploys, as `env` on the step that needs them. Deploy only from the
|
|
35
|
+
default branch or a release tag. When the repository uses GitHub environments, run the job in a protected
|
|
36
|
+
one with a reviewer.
|
|
33
37
|
|
|
34
38
|
## Workflow organization
|
|
35
39
|
|