lsdsk 1.0.0__tar.gz

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.
Files changed (178) hide show
  1. lsdsk-1.0.0/.claude-plugin/marketplace.json +16 -0
  2. lsdsk-1.0.0/.claude-plugin/plugin.json +11 -0
  3. lsdsk-1.0.0/.devcontainer/devcontainer.json +22 -0
  4. lsdsk-1.0.0/.devcontainer/settings.json +6 -0
  5. lsdsk-1.0.0/.env.example +366 -0
  6. lsdsk-1.0.0/.gitattributes +15 -0
  7. lsdsk-1.0.0/.github/actions/extract-metadata/action.yml +108 -0
  8. lsdsk-1.0.0/.github/dependabot.yml +22 -0
  9. lsdsk-1.0.0/.github/workflows/codeql.yml +39 -0
  10. lsdsk-1.0.0/.github/workflows/default_cicd_public.yml +436 -0
  11. lsdsk-1.0.0/.github/workflows/default_release_public.yml +95 -0
  12. lsdsk-1.0.0/.gitignore +208 -0
  13. lsdsk-1.0.0/.qlty/qlty.toml +2 -0
  14. lsdsk-1.0.0/.snyk +5 -0
  15. lsdsk-1.0.0/CHANGELOG.md +102 -0
  16. lsdsk-1.0.0/CONFIG.md +544 -0
  17. lsdsk-1.0.0/CONTRIBUTING.md +48 -0
  18. lsdsk-1.0.0/DEVELOPMENT.md +148 -0
  19. lsdsk-1.0.0/INSTALL.md +93 -0
  20. lsdsk-1.0.0/LICENSE +22 -0
  21. lsdsk-1.0.0/Makefile +453 -0
  22. lsdsk-1.0.0/PKG-INFO +466 -0
  23. lsdsk-1.0.0/README.md +413 -0
  24. lsdsk-1.0.0/SECURITY.md +40 -0
  25. lsdsk-1.0.0/ai-stance.md +90 -0
  26. lsdsk-1.0.0/ai-transparency.md +83 -0
  27. lsdsk-1.0.0/codecov.yml +27 -0
  28. lsdsk-1.0.0/docs/adr/0001-memory-adapters-in-src.md +29 -0
  29. lsdsk-1.0.0/docs/systemdesign/module_reference.md +192 -0
  30. lsdsk-1.0.0/notebooks/Quickstart.ipynb +257 -0
  31. lsdsk-1.0.0/pyproject.toml +326 -0
  32. lsdsk-1.0.0/skills/lsdsk/.skillwriter/checklist-2026-08-04.md +73 -0
  33. lsdsk-1.0.0/skills/lsdsk/.skillwriter/checklist-2026-08-05-default-report.md +48 -0
  34. lsdsk-1.0.0/skills/lsdsk/.skillwriter/checklist-2026-08-05-online-lookup.md +57 -0
  35. lsdsk-1.0.0/skills/lsdsk/.skillwriter/checklist-2026-08-05.md +57 -0
  36. lsdsk-1.0.0/skills/lsdsk/.skillwriter/checklist-2026-08-06-history-refusal-and-record.md +85 -0
  37. lsdsk-1.0.0/skills/lsdsk/.skillwriter/checklist-2026-08-06-isolated-review.md +109 -0
  38. lsdsk-1.0.0/skills/lsdsk/.skillwriter/checklist-2026-08-06-privileges-and-exit-codes.md +87 -0
  39. lsdsk-1.0.0/skills/lsdsk/SKILL.md +526 -0
  40. lsdsk-1.0.0/src/lsdsk/__init__.py +19 -0
  41. lsdsk-1.0.0/src/lsdsk/__init__conf__.py +90 -0
  42. lsdsk-1.0.0/src/lsdsk/__main__.py +9 -0
  43. lsdsk-1.0.0/src/lsdsk/adapters/__init__.py +14 -0
  44. lsdsk-1.0.0/src/lsdsk/adapters/cli/__init__.py +80 -0
  45. lsdsk-1.0.0/src/lsdsk/adapters/cli/commands/__init__.py +49 -0
  46. lsdsk-1.0.0/src/lsdsk/adapters/cli/commands/config.py +452 -0
  47. lsdsk-1.0.0/src/lsdsk/adapters/cli/commands/history.py +311 -0
  48. lsdsk-1.0.0/src/lsdsk/adapters/cli/commands/info.py +72 -0
  49. lsdsk-1.0.0/src/lsdsk/adapters/cli/commands/logging.py +34 -0
  50. lsdsk-1.0.0/src/lsdsk/adapters/cli/commands/scan.py +632 -0
  51. lsdsk-1.0.0/src/lsdsk/adapters/cli/constants.py +22 -0
  52. lsdsk-1.0.0/src/lsdsk/adapters/cli/context.py +162 -0
  53. lsdsk-1.0.0/src/lsdsk/adapters/cli/envelope.py +58 -0
  54. lsdsk-1.0.0/src/lsdsk/adapters/cli/exit_codes.py +61 -0
  55. lsdsk-1.0.0/src/lsdsk/adapters/cli/main.py +146 -0
  56. lsdsk-1.0.0/src/lsdsk/adapters/cli/py.typed +0 -0
  57. lsdsk-1.0.0/src/lsdsk/adapters/cli/root.py +235 -0
  58. lsdsk-1.0.0/src/lsdsk/adapters/cli/safe_console.py +213 -0
  59. lsdsk-1.0.0/src/lsdsk/adapters/cli/typed_click.py +51 -0
  60. lsdsk-1.0.0/src/lsdsk/adapters/config/__init__.py +25 -0
  61. lsdsk-1.0.0/src/lsdsk/adapters/config/defaultconfig.d/40-layered-config.toml +71 -0
  62. lsdsk-1.0.0/src/lsdsk/adapters/config/defaultconfig.d/50-history.toml +65 -0
  63. lsdsk-1.0.0/src/lsdsk/adapters/config/defaultconfig.d/60-thresholds.toml +108 -0
  64. lsdsk-1.0.0/src/lsdsk/adapters/config/defaultconfig.d/70-display.toml +56 -0
  65. lsdsk-1.0.0/src/lsdsk/adapters/config/defaultconfig.d/90-logging.toml +432 -0
  66. lsdsk-1.0.0/src/lsdsk/adapters/config/defaultconfig.toml +46 -0
  67. lsdsk-1.0.0/src/lsdsk/adapters/config/deploy.py +122 -0
  68. lsdsk-1.0.0/src/lsdsk/adapters/config/display.py +72 -0
  69. lsdsk-1.0.0/src/lsdsk/adapters/config/history.py +99 -0
  70. lsdsk-1.0.0/src/lsdsk/adapters/config/loader.py +196 -0
  71. lsdsk-1.0.0/src/lsdsk/adapters/config/overrides.py +191 -0
  72. lsdsk-1.0.0/src/lsdsk/adapters/config/permissions.py +222 -0
  73. lsdsk-1.0.0/src/lsdsk/adapters/config/py.typed +0 -0
  74. lsdsk-1.0.0/src/lsdsk/adapters/config/secrets.py +124 -0
  75. lsdsk-1.0.0/src/lsdsk/adapters/config/tunables.py +173 -0
  76. lsdsk-1.0.0/src/lsdsk/adapters/history/__init__.py +27 -0
  77. lsdsk-1.0.0/src/lsdsk/adapters/history/store.py +306 -0
  78. lsdsk-1.0.0/src/lsdsk/adapters/hw/__init__.py +19 -0
  79. lsdsk-1.0.0/src/lsdsk/adapters/hw/decode/__init__.py +26 -0
  80. lsdsk-1.0.0/src/lsdsk/adapters/hw/decode/ahci.py +130 -0
  81. lsdsk-1.0.0/src/lsdsk/adapters/hw/decode/ata_identify.py +263 -0
  82. lsdsk-1.0.0/src/lsdsk/adapters/hw/decode/ata_smart.py +276 -0
  83. lsdsk-1.0.0/src/lsdsk/adapters/hw/decode/nvme.py +145 -0
  84. lsdsk-1.0.0/src/lsdsk/adapters/hw/decode/pciids.py +225 -0
  85. lsdsk-1.0.0/src/lsdsk/adapters/hw/decode/text.py +48 -0
  86. lsdsk-1.0.0/src/lsdsk/adapters/hw/decode/virtualization.py +300 -0
  87. lsdsk-1.0.0/src/lsdsk/adapters/hw/linux/__init__.py +12 -0
  88. lsdsk-1.0.0/src/lsdsk/adapters/hw/linux/builder.py +647 -0
  89. lsdsk-1.0.0/src/lsdsk/adapters/hw/linux/reader.py +759 -0
  90. lsdsk-1.0.0/src/lsdsk/adapters/hw/snapshot.py +283 -0
  91. lsdsk-1.0.0/src/lsdsk/adapters/hw/windows/__init__.py +15 -0
  92. lsdsk-1.0.0/src/lsdsk/adapters/hw/windows/builder.py +346 -0
  93. lsdsk-1.0.0/src/lsdsk/adapters/hw/windows/reader.py +658 -0
  94. lsdsk-1.0.0/src/lsdsk/adapters/hw/windows/winapi.py +613 -0
  95. lsdsk-1.0.0/src/lsdsk/adapters/logging/__init__.py +13 -0
  96. lsdsk-1.0.0/src/lsdsk/adapters/logging/py.typed +0 -0
  97. lsdsk-1.0.0/src/lsdsk/adapters/logging/setup.py +134 -0
  98. lsdsk-1.0.0/src/lsdsk/adapters/memory/__init__.py +57 -0
  99. lsdsk-1.0.0/src/lsdsk/adapters/memory/config.py +65 -0
  100. lsdsk-1.0.0/src/lsdsk/adapters/memory/history.py +74 -0
  101. lsdsk-1.0.0/src/lsdsk/adapters/memory/info.py +41 -0
  102. lsdsk-1.0.0/src/lsdsk/adapters/memory/logging.py +18 -0
  103. lsdsk-1.0.0/src/lsdsk/adapters/py.typed +0 -0
  104. lsdsk-1.0.0/src/lsdsk/adapters/render/__init__.py +11 -0
  105. lsdsk-1.0.0/src/lsdsk/adapters/render/full.py +114 -0
  106. lsdsk-1.0.0/src/lsdsk/adapters/render/layout.py +184 -0
  107. lsdsk-1.0.0/src/lsdsk/adapters/render/report.py +813 -0
  108. lsdsk-1.0.0/src/lsdsk/adapters/render/rows.py +17 -0
  109. lsdsk-1.0.0/src/lsdsk/adapters/render/tables.py +367 -0
  110. lsdsk-1.0.0/src/lsdsk/adapters/render/theme.py +385 -0
  111. lsdsk-1.0.0/src/lsdsk/adapters/render/trend.py +265 -0
  112. lsdsk-1.0.0/src/lsdsk/adapters/textfile.py +86 -0
  113. lsdsk-1.0.0/src/lsdsk/adapters/tui/__init__.py +10 -0
  114. lsdsk-1.0.0/src/lsdsk/adapters/tui/app.py +340 -0
  115. lsdsk-1.0.0/src/lsdsk/adapters/tui/typed_table.py +65 -0
  116. lsdsk-1.0.0/src/lsdsk/application/__init__.py +26 -0
  117. lsdsk-1.0.0/src/lsdsk/application/ports.py +101 -0
  118. lsdsk-1.0.0/src/lsdsk/application/py.typed +0 -0
  119. lsdsk-1.0.0/src/lsdsk/composition/__init__.py +113 -0
  120. lsdsk-1.0.0/src/lsdsk/composition/py.typed +0 -0
  121. lsdsk-1.0.0/src/lsdsk/domain/__init__.py +39 -0
  122. lsdsk-1.0.0/src/lsdsk/domain/diagnostics.py +1070 -0
  123. lsdsk-1.0.0/src/lsdsk/domain/enums.py +242 -0
  124. lsdsk-1.0.0/src/lsdsk/domain/errors.py +44 -0
  125. lsdsk-1.0.0/src/lsdsk/domain/history.py +663 -0
  126. lsdsk-1.0.0/src/lsdsk/domain/models.py +865 -0
  127. lsdsk-1.0.0/src/lsdsk/domain/py.typed +0 -0
  128. lsdsk-1.0.0/src/lsdsk/domain/thresholds.py +61 -0
  129. lsdsk-1.0.0/src/lsdsk/entry.py +26 -0
  130. lsdsk-1.0.0/src/lsdsk/py.typed +0 -0
  131. lsdsk-1.0.0/tests/conftest.py +638 -0
  132. lsdsk-1.0.0/tests/e2e/hostprobe.py +256 -0
  133. lsdsk-1.0.0/tests/e2e/test_hostprobe_logic.py +141 -0
  134. lsdsk-1.0.0/tests/e2e/test_real_hardware.py +241 -0
  135. lsdsk-1.0.0/tests/fixtures/hw/linux-minimal.json +1550 -0
  136. lsdsk-1.0.0/tests/fixtures/hw/linux-nvme-board.json +1384 -0
  137. lsdsk-1.0.0/tests/fixtures/hw/linux-sas-hba-later.json +2693 -0
  138. lsdsk-1.0.0/tests/fixtures/hw/linux-sas-hba.json +2680 -0
  139. lsdsk-1.0.0/tests/fixtures/hw/windows-ahci.json +328 -0
  140. lsdsk-1.0.0/tests/test_cache_effectiveness.py +147 -0
  141. lsdsk-1.0.0/tests/test_cli_config.py +722 -0
  142. lsdsk-1.0.0/tests/test_cli_core.py +231 -0
  143. lsdsk-1.0.0/tests/test_cli_env_file.py +170 -0
  144. lsdsk-1.0.0/tests/test_cli_exit_codes.py +155 -0
  145. lsdsk-1.0.0/tests/test_cli_overrides.py +167 -0
  146. lsdsk-1.0.0/tests/test_cli_scan.py +214 -0
  147. lsdsk-1.0.0/tests/test_cli_validation.py +138 -0
  148. lsdsk-1.0.0/tests/test_config_keys_are_live.py +270 -0
  149. lsdsk-1.0.0/tests/test_config_overrides.py +375 -0
  150. lsdsk-1.0.0/tests/test_data_architecture.py +222 -0
  151. lsdsk-1.0.0/tests/test_deploy_permissions.py +477 -0
  152. lsdsk-1.0.0/tests/test_diagnostics.py +696 -0
  153. lsdsk-1.0.0/tests/test_display.py +187 -0
  154. lsdsk-1.0.0/tests/test_enums.py +66 -0
  155. lsdsk-1.0.0/tests/test_environment.py +292 -0
  156. lsdsk-1.0.0/tests/test_errors.py +93 -0
  157. lsdsk-1.0.0/tests/test_history.py +360 -0
  158. lsdsk-1.0.0/tests/test_history_cli.py +606 -0
  159. lsdsk-1.0.0/tests/test_history_config.py +351 -0
  160. lsdsk-1.0.0/tests/test_history_diagnostics.py +198 -0
  161. lsdsk-1.0.0/tests/test_history_store.py +435 -0
  162. lsdsk-1.0.0/tests/test_hw_builder.py +302 -0
  163. lsdsk-1.0.0/tests/test_hw_decode.py +363 -0
  164. lsdsk-1.0.0/tests/test_input_bounds.py +279 -0
  165. lsdsk-1.0.0/tests/test_logging.py +31 -0
  166. lsdsk-1.0.0/tests/test_machine_drivable.py +202 -0
  167. lsdsk-1.0.0/tests/test_metadata.py +84 -0
  168. lsdsk-1.0.0/tests/test_metadata_sync.py +80 -0
  169. lsdsk-1.0.0/tests/test_module_entry.py +197 -0
  170. lsdsk-1.0.0/tests/test_module_reference.py +82 -0
  171. lsdsk-1.0.0/tests/test_no_subprocess_or_network.py +107 -0
  172. lsdsk-1.0.0/tests/test_platform_markers.py +62 -0
  173. lsdsk-1.0.0/tests/test_ports.py +74 -0
  174. lsdsk-1.0.0/tests/test_property_overrides.py +165 -0
  175. lsdsk-1.0.0/tests/test_safe_console.py +135 -0
  176. lsdsk-1.0.0/tests/test_slots.py +355 -0
  177. lsdsk-1.0.0/tests/test_terminal_width.py +135 -0
  178. lsdsk-1.0.0/tests/test_tui.py +431 -0
@@ -0,0 +1,16 @@
1
+ {
2
+ "name": "lsdsk",
3
+ "owner": {
4
+ "name": "bitranox"
5
+ },
6
+ "metadata": {
7
+ "description": "lsdsk delivered as a single Claude Code plugin: a skill to inspect and diagnose storage topology, link speeds and disk health on Linux and Windows."
8
+ },
9
+ "plugins": [
10
+ {
11
+ "name": "lsdsk",
12
+ "source": ".",
13
+ "description": "Install and use lsdsk: group disks by controller, compare every link against what both ends could do, read SMART wear and error counters, and decide whether a slow link is a fault, a better slot, or a mainboard limit."
14
+ }
15
+ ]
16
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "name": "lsdsk",
3
+ "description": "See which disks hang off which controller, whether each one runs at the speed it could, and how worn it is. Ships the lsdsk skill: install via uvx, read the topology tree and the problem summary, interpret every finding class, and tell an actionable fault from a mainboard ceiling that only a different board would lift.",
4
+ "version": "1.0.0",
5
+ "author": {
6
+ "name": "bitranox"
7
+ },
8
+ "homepage": "https://github.com/bitranox/lsdsk",
9
+ "repository": "https://github.com/bitranox/lsdsk",
10
+ "license": "MIT"
11
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "image": "mcr.microsoft.com/devcontainers/python:3.13",
3
+
4
+ "postCreateCommand": "bash -lc '\nPY=/usr/local/bin/python;\n$PY -m pip install -U pip && \\\n$PY -m pip install ipykernel && \\\n$PY -m pip install -e . && \\\n# register kernel using this exact interpreter\n$PY -m ipykernel install --name=python3 --display-name=\"Python 3 (3.13)\" --user && \\\n# patch the notebook to point to the python3 kernelspec (VS Code will bind to /usr/local/bin/python)\n$PY - <<\"PY\"\nimport json, pathlib\np = pathlib.Path(\"notebooks/Quickstart.ipynb\")\nif p.exists():\n nb = json.loads(p.read_text(encoding=\"utf-8\"))\n md = nb.setdefault(\"metadata\", {})\n md[\"kernelspec\"] = {\n \"name\": \"python3\",\n \"display_name\": \"Python 3 (3.13)\",\n \"language\": \"python\"\n }\n md[\"language_info\"] = {\"name\": \"python\"}\n p.write_text(json.dumps(nb, ensure_ascii=False, indent=1), encoding=\"utf-8\")\n print(\"Pinned kernelspec to python3 in\", p)\nelse:\n print(\"Notebook not found:\", p)\nPY'\n",
5
+
6
+ "customizations": {
7
+ "vscode": {
8
+ "extensions": ["ms-toolsai.jupyter", "ms-python.python"],
9
+ "settings": {
10
+ "workbench.startupEditor": "none",
11
+ "jupyter.alwaysTrustNotebooks": true,
12
+ "jupyter.kernelPickerType": "OnlyRecommended",
13
+ "python.defaultInterpreterPath": "/usr/local/bin/python"
14
+ }
15
+ },
16
+ "codespaces": {
17
+ "openFiles": ["README.md"]
18
+ }
19
+ },
20
+
21
+ "postAttachCommand": "bash -lc 'if [ -f notebooks/Quickstart.ipynb ]; then code -r notebooks/Quickstart.ipynb; fi'"
22
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "python.defaultInterpreterPath": "/usr/local/bin/python3.13",
3
+ "jupyter.alwaysTrustNotebooks": true,
4
+ "jupyter.kernelPickerType": "OnlyRecommended",
5
+ "jupyter.askForKernelRestart": false
6
+ }
@@ -0,0 +1,366 @@
1
+ # Copy to .env and fill values as needed.
2
+
3
+ # Codecov upload token (required for private repos; optional for public repos)
4
+ CODECOV_TOKEN=
5
+
6
+ # PyPI API token for release workflow (.github/workflows/release.yml)
7
+ # Format: pypi-AgENdGVzdC5weXBpLm9yZwIk...
8
+ PYPI_API_TOKEN=
9
+
10
+ # Optional: GitHub token for API-limited tasks
11
+ GITHUB_TOKEN=
12
+
13
+ # ==============================================================================
14
+ # ==============================================================================
15
+ #
16
+ # Naming Convention
17
+ # -----------------
18
+ # Format: <SECTION>__<KEY>=value (double underscore separates section from key)
19
+ # Lists use comma-separated values, booleans use true/false, floats use decimal notation.
20
+ #
21
+ # Full environment variable (outside .env):
22
+ # (triple underscore separates the application slug from the section)
23
+
24
+ # Type: comma-separated strings in "host[:port]" format
25
+ # Default: (empty, must be configured to send email)
26
+
27
+ # Purpose: Default sender address for outgoing emails
28
+ # Type: string (valid email address)
29
+ # Default: (empty, must be configured or passed via --from)
30
+
31
+ # Type: comma-separated strings (valid email addresses)
32
+ # Default: (empty, must be configured or passed via --to)
33
+
34
+ # Type: string
35
+ # Default: (empty, no authentication)
36
+
37
+ # Type: string
38
+ # Default: (empty, no authentication)
39
+
40
+ # Purpose: Enable STARTTLS negotiation before authentication
41
+ # Type: boolean (true/false)
42
+ # Default: true
43
+
44
+ # Type: float
45
+ # Default: 30.0
46
+
47
+ # Type: boolean (true/false)
48
+ # Default: true
49
+
50
+ # Type: boolean (true/false)
51
+ # Default: true
52
+
53
+ # ==============================================================================
54
+ # Logging Configuration (lib_log_rich)
55
+ # ==============================================================================
56
+ #
57
+ # Naming Convention
58
+ # -----------------
59
+ # Format: <SECTION>__<KEY>=value (double underscore separates section from key)
60
+ # Strings need no quotes. Booleans: true/false. Floats: 1.0. Lists: comma-separated.
61
+ #
62
+ # Full environment variable (outside .env):
63
+ # LSDSK___LIB_LOG_RICH__<KEY>=value
64
+ #
65
+ # For nested subsections (e.g. payload_limits):
66
+ # LSDSK___LIB_LOG_RICH__PAYLOAD_LIMITS__<KEY>=value
67
+ # .env: LIB_LOG_RICH__PAYLOAD_LIMITS__<KEY>=value
68
+
69
+ # --- Core Identity ---
70
+
71
+ # Purpose: Logical service name recorded in each log event
72
+ # Type: string (non-empty)
73
+ # Default: "lsdsk"
74
+ # Environment Variable: LSDSK___LIB_LOG_RICH__SERVICE=my-application
75
+ # .env: LIB_LOG_RICH__SERVICE=my-application
76
+ # LIB_LOG_RICH__SERVICE=my-application
77
+
78
+ # Purpose: Deployment environment label
79
+ # Type: string (non-empty)
80
+ # Default: "prod"
81
+ # Environment Variable: LSDSK___LIB_LOG_RICH__ENVIRONMENT=dev
82
+ # .env: LIB_LOG_RICH__ENVIRONMENT=dev
83
+ # LIB_LOG_RICH__ENVIRONMENT=dev
84
+
85
+ # --- Console Output ---
86
+
87
+ # Purpose: Minimum severity level emitted to Rich console
88
+ # Type: string (case-insensitive): "DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"
89
+ # Default: "INFO"
90
+ # Environment Variable: LSDSK___LIB_LOG_RICH__CONSOLE_LEVEL=DEBUG
91
+ # .env: LIB_LOG_RICH__CONSOLE_LEVEL=DEBUG
92
+ # LIB_LOG_RICH__CONSOLE_LEVEL=DEBUG
93
+
94
+ # Purpose: Where to send console output
95
+ # Type: string: "stdout", "stderr", "both", "custom", "none"
96
+ # Default: "stderr"
97
+ # Environment Variable: LSDSK___LIB_LOG_RICH__CONSOLE_STREAM=stderr
98
+ # .env: LIB_LOG_RICH__CONSOLE_STREAM=stderr
99
+ # LIB_LOG_RICH__CONSOLE_STREAM=stderr
100
+
101
+ # Purpose: Console line layout preset
102
+ # Type: string (case-insensitive): "full", "short", "full_loc", "short_loc"
103
+ # Default: "short_loc"
104
+ # Environment Variable: LSDSK___LIB_LOG_RICH__CONSOLE_FORMAT_PRESET=short_loc
105
+ # .env: LIB_LOG_RICH__CONSOLE_FORMAT_PRESET=short_loc
106
+ # LIB_LOG_RICH__CONSOLE_FORMAT_PRESET=short_loc
107
+
108
+ # Purpose: Custom console output template (overrides preset)
109
+ # Type: string (Python str.format template); empty = uses preset
110
+ # Default: (empty, uses preset)
111
+ # Environment Variable: LSDSK___LIB_LOG_RICH__CONSOLE_FORMAT_TEMPLATE={timestamp_trimmed_naive_loc} {level_code} {message}
112
+ # .env: LIB_LOG_RICH__CONSOLE_FORMAT_TEMPLATE={timestamp_trimmed_naive_loc} {level_code} {message}
113
+ # LIB_LOG_RICH__CONSOLE_FORMAT_TEMPLATE={timestamp_trimmed_naive_loc} {level_code} {message}
114
+
115
+ # Purpose: Rich color palette for console output
116
+ # Type: string: "classic", "dark", "neon", "pastel"
117
+ # Default: "dark"
118
+ # Environment Variable: LSDSK___LIB_LOG_RICH__CONSOLE_THEME=dark
119
+ # .env: LIB_LOG_RICH__CONSOLE_THEME=dark
120
+ # LIB_LOG_RICH__CONSOLE_THEME=dark
121
+
122
+ # Purpose: Override Rich styles per severity level (comma-separated LEVEL=style pairs)
123
+ # Type: comma-separated LEVEL=style pairs
124
+ # Default: (empty, uses theme defaults)
125
+ # Environment Variable: LSDSK___LIB_LOG_RICH__CONSOLE_STYLES=DEBUG=dim,ERROR=bold red
126
+ # .env: LIB_LOG_RICH__CONSOLE_STYLES=DEBUG=dim,ERROR=bold red
127
+ # LIB_LOG_RICH__CONSOLE_STYLES=DEBUG=dim,ERROR=bold red
128
+
129
+ # Purpose: Force ANSI color output even when stderr is not a TTY
130
+ # Type: boolean (true/false)
131
+ # Default: false
132
+ # Environment Variable: LSDSK___LIB_LOG_RICH__FORCE_COLOR=true
133
+ # .env: LIB_LOG_RICH__FORCE_COLOR=true
134
+ # LIB_LOG_RICH__FORCE_COLOR=true
135
+
136
+ # Purpose: Disable color output entirely (overrides force_color)
137
+ # Type: boolean (true/false)
138
+ # Default: false
139
+ # Environment Variable: LSDSK___LIB_LOG_RICH__NO_COLOR=false
140
+ # .env: LIB_LOG_RICH__NO_COLOR=false
141
+ # LIB_LOG_RICH__NO_COLOR=false
142
+
143
+ # --- Backend Adapters ---
144
+
145
+ # Purpose: Minimum severity threshold for journald and Windows Event Log
146
+ # Type: string (case-insensitive): "DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"
147
+ # Default: "WARNING"
148
+ # Environment Variable: LSDSK___LIB_LOG_RICH__BACKEND_LEVEL=WARNING
149
+ # .env: LIB_LOG_RICH__BACKEND_LEVEL=WARNING
150
+ # LIB_LOG_RICH__BACKEND_LEVEL=WARNING
151
+
152
+ # Purpose: Enable systemd journald adapter (Linux only; requires python3-systemd)
153
+ # Type: boolean (true/false)
154
+ # Default: false
155
+ # Environment Variable: LSDSK___LIB_LOG_RICH__ENABLE_JOURNALD=true
156
+ # .env: LIB_LOG_RICH__ENABLE_JOURNALD=true
157
+ # LIB_LOG_RICH__ENABLE_JOURNALD=true
158
+
159
+ # Purpose: Enable Windows Event Log adapter (Windows only)
160
+ # Type: boolean (true/false)
161
+ # Default: false
162
+ # Environment Variable: LSDSK___LIB_LOG_RICH__ENABLE_EVENTLOG=false
163
+ # .env: LIB_LOG_RICH__ENABLE_EVENTLOG=false
164
+ # LIB_LOG_RICH__ENABLE_EVENTLOG=false
165
+
166
+ # --- Graylog / GELF ---
167
+
168
+ # Purpose: Enable Graylog adapter for centralized logging
169
+ # Type: boolean (true/false)
170
+ # Default: false
171
+ # Environment Variable: LSDSK___LIB_LOG_RICH__ENABLE_GRAYLOG=true
172
+ # .env: LIB_LOG_RICH__ENABLE_GRAYLOG=true
173
+ # LIB_LOG_RICH__ENABLE_GRAYLOG=true
174
+
175
+ # Purpose: Graylog server address (host:port)
176
+ # Type: string "host:port"
177
+ # Default: (none, must be configured to enable Graylog)
178
+ # Environment Variable: LSDSK___LIB_LOG_RICH__GRAYLOG_ENDPOINT=graylog.example.com:12201
179
+ # .env: LIB_LOG_RICH__GRAYLOG_ENDPOINT=graylog.example.com:12201
180
+ # LIB_LOG_RICH__GRAYLOG_ENDPOINT=graylog.example.com:12201
181
+
182
+ # Purpose: Transport protocol for Graylog (tcp, udp); TLS only supported with tcp
183
+ # Type: string: "tcp", "udp"
184
+ # Default: "tcp"
185
+ # Environment Variable: LSDSK___LIB_LOG_RICH__GRAYLOG_PROTOCOL=tcp
186
+ # .env: LIB_LOG_RICH__GRAYLOG_PROTOCOL=tcp
187
+ # LIB_LOG_RICH__GRAYLOG_PROTOCOL=tcp
188
+
189
+ # Purpose: Wrap Graylog TCP connection in TLS
190
+ # Type: boolean (true/false)
191
+ # Default: false
192
+ # Environment Variable: LSDSK___LIB_LOG_RICH__GRAYLOG_TLS=true
193
+ # .env: LIB_LOG_RICH__GRAYLOG_TLS=true
194
+ # LIB_LOG_RICH__GRAYLOG_TLS=true
195
+
196
+ # Purpose: Minimum severity level sent to Graylog
197
+ # Type: string (case-insensitive): "DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"
198
+ # Default: "WARNING"
199
+ # Environment Variable: LSDSK___LIB_LOG_RICH__GRAYLOG_LEVEL=WARNING
200
+ # .env: LIB_LOG_RICH__GRAYLOG_LEVEL=WARNING
201
+ # LIB_LOG_RICH__GRAYLOG_LEVEL=WARNING
202
+
203
+ # --- Queue Settings ---
204
+
205
+ # Purpose: Route log events through background queue worker (false = synchronous, blocks on I/O)
206
+ # Type: boolean (true/false)
207
+ # Default: true
208
+ # Environment Variable: LSDSK___LIB_LOG_RICH__QUEUE_ENABLED=true
209
+ # .env: LIB_LOG_RICH__QUEUE_ENABLED=true
210
+ # LIB_LOG_RICH__QUEUE_ENABLED=true
211
+
212
+ # Purpose: Maximum pending events before queue full policy applies
213
+ # Type: integer (> 0)
214
+ # Default: 2048
215
+ # Environment Variable: LSDSK___LIB_LOG_RICH__QUEUE_MAXSIZE=2048
216
+ # .env: LIB_LOG_RICH__QUEUE_MAXSIZE=2048
217
+ # LIB_LOG_RICH__QUEUE_MAXSIZE=2048
218
+
219
+ # Purpose: Behavior when queue is full
220
+ # Type: string: "block" (wait for space), "drop" (discard events)
221
+ # Default: "block"
222
+ # Environment Variable: LSDSK___LIB_LOG_RICH__QUEUE_FULL_POLICY=block
223
+ # .env: LIB_LOG_RICH__QUEUE_FULL_POLICY=block
224
+ # LIB_LOG_RICH__QUEUE_FULL_POLICY=block
225
+
226
+ # Purpose: Timeout in seconds for blocking queue puts (0 = infinite wait)
227
+ # Type: float (>= 0)
228
+ # Default: 1.0
229
+ # Environment Variable: LSDSK___LIB_LOG_RICH__QUEUE_PUT_TIMEOUT=1.0
230
+ # .env: LIB_LOG_RICH__QUEUE_PUT_TIMEOUT=1.0
231
+ # LIB_LOG_RICH__QUEUE_PUT_TIMEOUT=1.0
232
+
233
+ # Purpose: Maximum wait in seconds for queue drain during shutdown
234
+ # Type: float (> 0)
235
+ # Default: 5.0
236
+ # Environment Variable: LSDSK___LIB_LOG_RICH__QUEUE_STOP_TIMEOUT=5.0
237
+ # .env: LIB_LOG_RICH__QUEUE_STOP_TIMEOUT=5.0
238
+ # LIB_LOG_RICH__QUEUE_STOP_TIMEOUT=5.0
239
+
240
+ # --- Ring Buffer ---
241
+
242
+ # Purpose: Enable in-memory circular buffer for log history (enables log.dump())
243
+ # Type: boolean (true/false)
244
+ # Default: true
245
+ # Environment Variable: LSDSK___LIB_LOG_RICH__ENABLE_RING_BUFFER=true
246
+ # .env: LIB_LOG_RICH__ENABLE_RING_BUFFER=true
247
+ # LIB_LOG_RICH__ENABLE_RING_BUFFER=true
248
+
249
+ # Purpose: Maximum events retained in ring buffer
250
+ # Type: integer (> 0)
251
+ # Default: 25000
252
+ # Environment Variable: LSDSK___LIB_LOG_RICH__RING_BUFFER_SIZE=25000
253
+ # .env: LIB_LOG_RICH__RING_BUFFER_SIZE=25000
254
+ # LIB_LOG_RICH__RING_BUFFER_SIZE=25000
255
+
256
+ # --- Dump Format ---
257
+
258
+ # Purpose: Default layout for text dumps
259
+ # Type: string (case-insensitive): "full", "short", "full_loc", "short_loc"
260
+ # Default: "full"
261
+ # Environment Variable: LSDSK___LIB_LOG_RICH__DUMP_FORMAT_PRESET=full
262
+ # .env: LIB_LOG_RICH__DUMP_FORMAT_PRESET=full
263
+ # LIB_LOG_RICH__DUMP_FORMAT_PRESET=full
264
+
265
+ # Purpose: Custom template for text dumps (overrides preset)
266
+ # Type: string (Python str.format template); empty = uses preset
267
+ # Default: (empty, uses preset)
268
+ # Environment Variable: LSDSK___LIB_LOG_RICH__DUMP_FORMAT_TEMPLATE={timestamp_trimmed_naive_loc} {level_code} {message}
269
+ # .env: LIB_LOG_RICH__DUMP_FORMAT_TEMPLATE={timestamp_trimmed_naive_loc} {level_code} {message}
270
+ # LIB_LOG_RICH__DUMP_FORMAT_TEMPLATE={timestamp_trimmed_naive_loc} {level_code} {message}
271
+
272
+ # --- Security & Payload ---
273
+
274
+ # Purpose: Regex patterns to redact sensitive data (comma-separated field=regex pairs)
275
+ # Type: comma-separated field=regex pairs
276
+ # Default: password=.+,secret=.+,token=.+
277
+ # Environment Variable: LSDSK___LIB_LOG_RICH__SCRUB_PATTERNS=password=.+,secret=.+,token=.+,api_key=.+
278
+ # .env: LIB_LOG_RICH__SCRUB_PATTERNS=password=.+,secret=.+,token=.+,api_key=.+
279
+ # LIB_LOG_RICH__SCRUB_PATTERNS=password=.+,secret=.+,token=.+,api_key=.+
280
+
281
+ # Purpose: Throttle log emissions (MAX_EVENTS:WINDOW_SECONDS)
282
+ # Type: string "max_events:window_seconds"
283
+ # Default: (none, no rate limiting)
284
+ # Environment Variable: LSDSK___LIB_LOG_RICH__RATE_LIMIT=100:60
285
+ # .env: LIB_LOG_RICH__RATE_LIMIT=100:60
286
+ # LIB_LOG_RICH__RATE_LIMIT=100:60
287
+
288
+ # --- Payload Limits ---
289
+
290
+ # Purpose: Truncate vs reject oversized messages
291
+ # Type: boolean (true/false)
292
+ # Default: true
293
+ # Environment Variable: LSDSK___LIB_LOG_RICH__PAYLOAD_LIMITS__TRUNCATE_MESSAGE=true
294
+ # .env: LIB_LOG_RICH__PAYLOAD_LIMITS__TRUNCATE_MESSAGE=true
295
+ # LIB_LOG_RICH__PAYLOAD_LIMITS__TRUNCATE_MESSAGE=true
296
+
297
+ # Purpose: Maximum characters in primary log message
298
+ # Type: integer
299
+ # Default: 4096
300
+ # Environment Variable: LSDSK___LIB_LOG_RICH__PAYLOAD_LIMITS__MESSAGE_MAX_CHARS=4096
301
+ # .env: LIB_LOG_RICH__PAYLOAD_LIMITS__MESSAGE_MAX_CHARS=4096
302
+ # LIB_LOG_RICH__PAYLOAD_LIMITS__MESSAGE_MAX_CHARS=4096
303
+
304
+ # Purpose: Maximum keys in extra metadata dict
305
+ # Type: integer
306
+ # Default: 25
307
+ # Environment Variable: LSDSK___LIB_LOG_RICH__PAYLOAD_LIMITS__EXTRA_MAX_KEYS=25
308
+ # .env: LIB_LOG_RICH__PAYLOAD_LIMITS__EXTRA_MAX_KEYS=25
309
+ # LIB_LOG_RICH__PAYLOAD_LIMITS__EXTRA_MAX_KEYS=25
310
+
311
+ # Purpose: Maximum characters per extra value (after stringify)
312
+ # Type: integer
313
+ # Default: 512
314
+ # Environment Variable: LSDSK___LIB_LOG_RICH__PAYLOAD_LIMITS__EXTRA_MAX_VALUE_CHARS=512
315
+ # .env: LIB_LOG_RICH__PAYLOAD_LIMITS__EXTRA_MAX_VALUE_CHARS=512
316
+ # LIB_LOG_RICH__PAYLOAD_LIMITS__EXTRA_MAX_VALUE_CHARS=512
317
+
318
+ # Purpose: Maximum nesting depth for extra structures
319
+ # Type: integer
320
+ # Default: 3
321
+ # Environment Variable: LSDSK___LIB_LOG_RICH__PAYLOAD_LIMITS__EXTRA_MAX_DEPTH=3
322
+ # .env: LIB_LOG_RICH__PAYLOAD_LIMITS__EXTRA_MAX_DEPTH=3
323
+ # LIB_LOG_RICH__PAYLOAD_LIMITS__EXTRA_MAX_DEPTH=3
324
+
325
+ # Purpose: Total UTF-8 byte limit for sanitized extra payload
326
+ # Type: integer
327
+ # Default: 8192
328
+ # Environment Variable: LSDSK___LIB_LOG_RICH__PAYLOAD_LIMITS__EXTRA_MAX_TOTAL_BYTES=8192
329
+ # .env: LIB_LOG_RICH__PAYLOAD_LIMITS__EXTRA_MAX_TOTAL_BYTES=8192
330
+ # LIB_LOG_RICH__PAYLOAD_LIMITS__EXTRA_MAX_TOTAL_BYTES=8192
331
+
332
+ # Purpose: Maximum keys in LogContext.extra
333
+ # Type: integer
334
+ # Default: 20
335
+ # Environment Variable: LSDSK___LIB_LOG_RICH__PAYLOAD_LIMITS__CONTEXT_MAX_KEYS=20
336
+ # .env: LIB_LOG_RICH__PAYLOAD_LIMITS__CONTEXT_MAX_KEYS=20
337
+ # LIB_LOG_RICH__PAYLOAD_LIMITS__CONTEXT_MAX_KEYS=20
338
+
339
+ # Purpose: Maximum characters per context value
340
+ # Type: integer
341
+ # Default: 256
342
+ # Environment Variable: LSDSK___LIB_LOG_RICH__PAYLOAD_LIMITS__CONTEXT_MAX_VALUE_CHARS=256
343
+ # .env: LIB_LOG_RICH__PAYLOAD_LIMITS__CONTEXT_MAX_VALUE_CHARS=256
344
+ # LIB_LOG_RICH__PAYLOAD_LIMITS__CONTEXT_MAX_VALUE_CHARS=256
345
+
346
+ # Purpose: Number of frames preserved in exception tracebacks
347
+ # Type: integer
348
+ # Default: 10
349
+ # Environment Variable: LSDSK___LIB_LOG_RICH__PAYLOAD_LIMITS__STACKTRACE_MAX_FRAMES=10
350
+ # .env: LIB_LOG_RICH__PAYLOAD_LIMITS__STACKTRACE_MAX_FRAMES=10
351
+ # LIB_LOG_RICH__PAYLOAD_LIMITS__STACKTRACE_MAX_FRAMES=10
352
+
353
+ # ---------------------------------------------------------------------------
354
+ # Real-hardware end-to-end tests (make testintegration)
355
+ # ---------------------------------------------------------------------------
356
+ #
357
+ # Which machines `tests/e2e/test_real_hardware.py` ships the probe to. Left
358
+ # empty here and set in .env, which is never committed: a fleet's hostnames are
359
+ # infrastructure, and this repository is public.
360
+ #
361
+ # Format: comma-separated host:user:family, family being linux or windows.
362
+ # Example: LSDSK_E2E_HOSTS="server-a:root:linux,workstation-b:admin:windows"
363
+ #
364
+ # Unset, the hardware tests skip and say so. Authentication uses the ssh key at
365
+ # ~/.ssh/, never a password in this file.
366
+ LSDSK_E2E_HOSTS=
@@ -0,0 +1,15 @@
1
+ # Normalize every text file to LF in the repo AND the working tree, on every OS.
2
+ # `text=auto` auto-detects binary and leaves it untouched; `eol=lf` forces LF checkout
3
+ # so a Windows edit/save cannot reintroduce CRLF churn.
4
+ * text=auto eol=lf
5
+
6
+ # Runtime-critical: CRLF here breaks execution on Linux (^M in shebang / make recipes).
7
+ Makefile text eol=lf
8
+ *.sh text eol=lf
9
+ *.py text eol=lf
10
+ *.ps1 text eol=lf
11
+ *.toml text eol=lf
12
+ *.md text eol=lf
13
+ *.json text eol=lf
14
+ *.yml text eol=lf
15
+ *.yaml text eol=lf
@@ -0,0 +1,108 @@
1
+ name: Extract project metadata
2
+ description: >-
3
+ Parse pyproject.toml and expose project metadata as step outputs.
4
+ Requires Python to be available in the runner environment.
5
+ Auto-installs rtoml if not already present.
6
+
7
+ outputs:
8
+ PACKAGE_MODULE:
9
+ description: Python-importable module name (underscored)
10
+ value: ${{ steps.meta.outputs.PACKAGE_MODULE }}
11
+ PROJECT_NAME:
12
+ description: Project name from pyproject.toml
13
+ value: ${{ steps.meta.outputs.PROJECT_NAME }}
14
+ CLI_BIN:
15
+ description: CLI entry-point binary name
16
+ value: ${{ steps.meta.outputs.CLI_BIN }}
17
+ SRC_PATH:
18
+ description: Source directory path (e.g. "src")
19
+ value: ${{ steps.meta.outputs.SRC_PATH }}
20
+ COV_FAIL_UNDER:
21
+ description: Minimum coverage percentage from tool.coverage.report.fail_under
22
+ value: ${{ steps.meta.outputs.COV_FAIL_UNDER }}
23
+ COV_REPORT_FILE:
24
+ description: Coverage report filename (e.g. "coverage.xml")
25
+ value: ${{ steps.meta.outputs.COV_REPORT_FILE }}
26
+ PYTEST_VERBOSITY:
27
+ description: Pytest verbosity flag (e.g. "-vv")
28
+ value: ${{ steps.meta.outputs.PYTEST_VERBOSITY }}
29
+ BANDIT_SKIP_FLAG:
30
+ description: Bandit skip flag string (e.g. "-s B101,B601") or empty
31
+ value: ${{ steps.meta.outputs.BANDIT_SKIP_FLAG }}
32
+ PYTEST_MARKER_EXPR:
33
+ description: >-
34
+ Marker expression for the CI test run (e.g. "not local_only and not integration"),
35
+ built from tool.ci.pytest-exclude-markers
36
+ value: ${{ steps.meta.outputs.PYTEST_MARKER_EXPR }}
37
+
38
+ runs:
39
+ using: composite
40
+ steps:
41
+ - name: Extract project metadata from pyproject.toml
42
+ id: meta
43
+ shell: python
44
+ run: |
45
+ import os, subprocess, sys
46
+ try:
47
+ import rtoml
48
+ except ModuleNotFoundError:
49
+ subprocess.check_call([sys.executable, "-m", "pip", "install", "rtoml", "-q"])
50
+ import rtoml
51
+
52
+ from pathlib import Path
53
+ data = rtoml.load(Path('pyproject.toml'))
54
+
55
+ # --- [project] section ---
56
+ project = data['project']['name']
57
+ module = project.replace('-', '_')
58
+ dash = project.replace('_', '-')
59
+ scripts = list(data['project'].get('scripts', {}).keys())
60
+ cli_bin = scripts[0] if scripts else dash
61
+
62
+ # --- [tool.scripts.test] section ---
63
+ scripts_test = data.get('tool', {}).get('scripts', {}).get('test', {})
64
+ src_path = scripts_test.get('src-path', 'src')
65
+ pytest_verbosity = scripts_test.get('pytest-verbosity', '-vv')
66
+ cov_report_file = scripts_test.get('coverage-report-file', 'coverage.xml')
67
+
68
+ # --- [tool.coverage.report] section ---
69
+ cov_fail_under = (
70
+ data.get('tool', {}).get('coverage', {}).get('report', {}).get('fail_under', 90)
71
+ )
72
+
73
+ # --- [tool.bandit] section ---
74
+ bandit_skips = data.get('tool', {}).get('bandit', {}).get('skips', [])
75
+ bandit_skip_flag = f"-s {','.join(bandit_skips)}" if bandit_skips else ""
76
+
77
+ # --- [tool.ci] section ---
78
+ # CI always skips local_only (those tests need a dev box). A project whose
79
+ # suite also carries markers CI cannot satisfy - integration tests needing a
80
+ # container that a separate workflow starts - names them here, rather than
81
+ # every such repo forking this workflow to edit one -m expression.
82
+ ci_config = data.get('tool', {}).get('ci', {})
83
+ exclude_markers = ['local_only', *ci_config.get('pytest-exclude-markers', [])]
84
+ pytest_marker_expr = ' and '.join(f'not {m}' for m in exclude_markers)
85
+
86
+ # Write to GITHUB_OUTPUT for composite action outputs
87
+ with open(os.environ['GITHUB_OUTPUT'], 'a', encoding='utf-8') as out:
88
+ out.write(f"PROJECT_NAME={project}\n")
89
+ out.write(f"PACKAGE_MODULE={module}\n")
90
+ out.write(f"CLI_BIN={cli_bin}\n")
91
+ out.write(f"SRC_PATH={src_path}\n")
92
+ out.write(f"PYTEST_VERBOSITY={pytest_verbosity}\n")
93
+ out.write(f"COV_REPORT_FILE={cov_report_file}\n")
94
+ out.write(f"COV_FAIL_UNDER={cov_fail_under}\n")
95
+ out.write(f"BANDIT_SKIP_FLAG={bandit_skip_flag}\n")
96
+ out.write(f"PYTEST_MARKER_EXPR={pytest_marker_expr}\n")
97
+
98
+ # Also write to GITHUB_ENV so subsequent steps can use ${{ env.VAR }}
99
+ with open(os.environ['GITHUB_ENV'], 'a', encoding='utf-8') as env:
100
+ env.write(f"PROJECT_NAME={project}\n")
101
+ env.write(f"PACKAGE_MODULE={module}\n")
102
+ env.write(f"CLI_BIN={cli_bin}\n")
103
+ env.write(f"SRC_PATH={src_path}\n")
104
+ env.write(f"PYTEST_VERBOSITY={pytest_verbosity}\n")
105
+ env.write(f"COV_REPORT_FILE={cov_report_file}\n")
106
+ env.write(f"COV_FAIL_UNDER={cov_fail_under}\n")
107
+ env.write(f"BANDIT_SKIP_FLAG={bandit_skip_flag}\n")
108
+ env.write(f"PYTEST_MARKER_EXPR={pytest_marker_expr}\n")
@@ -0,0 +1,22 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: "pip"
4
+ directory: "/"
5
+ schedule:
6
+ interval: "weekly"
7
+ allow:
8
+ - dependency-type: "direct"
9
+ labels:
10
+ - "dependencies"
11
+ commit-message:
12
+ prefix: "deps"
13
+ include: "scope"
14
+ - package-ecosystem: "github-actions"
15
+ directory: "/"
16
+ schedule:
17
+ interval: "weekly"
18
+ labels:
19
+ - "dependencies"
20
+ commit-message:
21
+ prefix: "deps"
22
+ include: "scope"
@@ -0,0 +1,39 @@
1
+ name: CodeQL
2
+
3
+ on:
4
+ push:
5
+ branches: [ main, master ]
6
+ pull_request:
7
+ branches: [ main, master ]
8
+ schedule:
9
+ - cron: '0 8 * * 1'
10
+
11
+ jobs:
12
+ analyze:
13
+ name: CodeQL Analyze
14
+ runs-on: ubuntu-latest
15
+ permissions:
16
+ actions: read
17
+ contents: read
18
+ security-events: write
19
+ strategy:
20
+ fail-fast: false
21
+ matrix:
22
+ language: [ 'python' ]
23
+
24
+ steps:
25
+ - name: Checkout repository
26
+ uses: actions/checkout@v7
27
+
28
+ - name: Initialize CodeQL
29
+ uses: github/codeql-action/init@v4
30
+ with:
31
+ languages: ${{ matrix.language }}
32
+
33
+ - name: Autobuild
34
+ uses: github/codeql-action/autobuild@v4
35
+
36
+ - name: Perform CodeQL Analysis
37
+ uses: github/codeql-action/analyze@v4
38
+ with:
39
+ category: "/language:${{ matrix.language }}"