opsscript-gate 0.4.1__tar.gz → 0.5.1__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 (50) hide show
  1. {opsscript_gate-0.4.1 → opsscript_gate-0.5.1}/.github/workflows/test.yml +15 -2
  2. {opsscript_gate-0.4.1 → opsscript_gate-0.5.1}/CHANGELOG.md +33 -7
  3. {opsscript_gate-0.4.1 → opsscript_gate-0.5.1}/PKG-INFO +140 -39
  4. {opsscript_gate-0.4.1 → opsscript_gate-0.5.1}/README.md +138 -37
  5. opsscript_gate-0.5.1/README.zh-CN.md +67 -0
  6. opsscript_gate-0.5.1/action.yml +130 -0
  7. opsscript_gate-0.5.1/docs/configuration.md +115 -0
  8. opsscript_gate-0.5.1/docs/troubleshooting.md +67 -0
  9. {opsscript_gate-0.4.1 → opsscript_gate-0.5.1}/examples/alpine-incompatibility/README.md +2 -1
  10. {opsscript_gate-0.4.1 → opsscript_gate-0.5.1}/examples/github-actions/README.md +2 -2
  11. {opsscript_gate-0.4.1 → opsscript_gate-0.5.1}/examples/github-actions/workflow.yml +3 -1
  12. {opsscript_gate-0.4.1 → opsscript_gate-0.5.1}/pyproject.toml +2 -2
  13. {opsscript_gate-0.4.1 → opsscript_gate-0.5.1}/src/opsscript_gate/__init__.py +1 -1
  14. {opsscript_gate-0.4.1 → opsscript_gate-0.5.1}/src/opsscript_gate/cli.py +89 -4
  15. opsscript_gate-0.5.1/src/opsscript_gate/config.py +78 -0
  16. {opsscript_gate-0.4.1 → opsscript_gate-0.5.1}/src/opsscript_gate/discovery.py +16 -3
  17. opsscript_gate-0.5.1/tests/test_action_contract.py +22 -0
  18. opsscript_gate-0.5.1/tests/test_onboarding.py +133 -0
  19. {opsscript_gate-0.4.1 → opsscript_gate-0.5.1}/tests/test_runner.py +2 -1
  20. opsscript_gate-0.4.1/action.yml +0 -90
  21. opsscript_gate-0.4.1/docs/promotion/awesome-lists-pr.md +0 -59
  22. opsscript_gate-0.4.1/docs/promotion/juejin-zhihu-article.md +0 -144
  23. opsscript_gate-0.4.1/docs/promotion/reddit-devops.md +0 -56
  24. opsscript_gate-0.4.1/docs/promotion/show-hn.md +0 -67
  25. opsscript_gate-0.4.1/docs/promotion/v2ex-post.md +0 -68
  26. {opsscript_gate-0.4.1 → opsscript_gate-0.5.1}/.gitattributes +0 -0
  27. {opsscript_gate-0.4.1 → opsscript_gate-0.5.1}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  28. {opsscript_gate-0.4.1 → opsscript_gate-0.5.1}/.github/ISSUE_TEMPLATE/distro_request.yml +0 -0
  29. {opsscript_gate-0.4.1 → opsscript_gate-0.5.1}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  30. {opsscript_gate-0.4.1 → opsscript_gate-0.5.1}/.github/assets/social-preview.png +0 -0
  31. {opsscript_gate-0.4.1 → opsscript_gate-0.5.1}/.github/pull_request_template.md +0 -0
  32. {opsscript_gate-0.4.1 → opsscript_gate-0.5.1}/.github/workflows/demo.yml +0 -0
  33. {opsscript_gate-0.4.1 → opsscript_gate-0.5.1}/.github/workflows/release.yml +0 -0
  34. {opsscript_gate-0.4.1 → opsscript_gate-0.5.1}/.gitignore +0 -0
  35. {opsscript_gate-0.4.1 → opsscript_gate-0.5.1}/CONTRIBUTING.md +0 -0
  36. {opsscript_gate-0.4.1 → opsscript_gate-0.5.1}/LICENSE +0 -0
  37. {opsscript_gate-0.4.1 → opsscript_gate-0.5.1}/ROADMAP.md +0 -0
  38. {opsscript_gate-0.4.1 → opsscript_gate-0.5.1}/SECURITY.md +0 -0
  39. {opsscript_gate-0.4.1 → opsscript_gate-0.5.1}/examples/alpine-incompatibility/apt_dependency.sh +0 -0
  40. {opsscript_gate-0.4.1 → opsscript_gate-0.5.1}/examples/basic/README.md +0 -0
  41. {opsscript_gate-0.4.1 → opsscript_gate-0.5.1}/examples/basic/clean_setup.sh +0 -0
  42. {opsscript_gate-0.4.1 → opsscript_gate-0.5.1}/examples/interactive-hang/README.md +0 -0
  43. {opsscript_gate-0.4.1 → opsscript_gate-0.5.1}/examples/interactive-hang/prompt_confirm.sh +0 -0
  44. {opsscript_gate-0.4.1 → opsscript_gate-0.5.1}/src/opsscript_gate/models.py +0 -0
  45. {opsscript_gate-0.4.1 → opsscript_gate-0.5.1}/src/opsscript_gate/remediation.py +0 -0
  46. {opsscript_gate-0.4.1 → opsscript_gate-0.5.1}/src/opsscript_gate/reporter.py +0 -0
  47. {opsscript_gate-0.4.1 → opsscript_gate-0.5.1}/src/opsscript_gate/runner.py +0 -0
  48. {opsscript_gate-0.4.1 → opsscript_gate-0.5.1}/tests/fixtures/fail_deps.sh +0 -0
  49. {opsscript_gate-0.4.1 → opsscript_gate-0.5.1}/tests/fixtures/fail_hang.sh +0 -0
  50. {opsscript_gate-0.4.1 → opsscript_gate-0.5.1}/tests/fixtures/pass_basic.sh +0 -0
@@ -8,7 +8,11 @@ on:
8
8
 
9
9
  jobs:
10
10
  test:
11
- runs-on: ubuntu-latest
11
+ strategy:
12
+ matrix:
13
+ os: [ubuntu-latest, windows-latest]
14
+ python: ['3.10', '3.12']
15
+ runs-on: ${{ matrix.os }}
12
16
  steps:
13
17
  - name: Checkout Code
14
18
  uses: actions/checkout@v7
@@ -16,7 +20,7 @@ jobs:
16
20
  - name: Set up Python
17
21
  uses: actions/setup-python@v7
18
22
  with:
19
- python-version: '3.12'
23
+ python-version: ${{ matrix.python }}
20
24
 
21
25
  - name: Install Dependencies
22
26
  run: |
@@ -50,3 +54,12 @@ jobs:
50
54
  - name: Run Docker Integration Tests
51
55
  run: |
52
56
  pytest -v -m integration
57
+
58
+ - name: Exercise the local composite Action
59
+ uses: ./
60
+ with:
61
+ script-path: tests/fixtures/pass_basic.sh
62
+ preset: minimal
63
+ network: none
64
+ output: action-report.json
65
+ format: json
@@ -1,5 +1,31 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.5.1] - 2026-09-30
4
+
5
+ ### Changed
6
+ - Published the current README and examples with the v0.5.1 Action tag.
7
+ - Updated package and Action metadata to describe the supported container matrix and runtime compatibility check.
8
+
9
+ ## [0.5.0] - 2026-09-24
10
+
11
+ ### Added
12
+ - Added `opsscript-gate init` to create a config file and GitHub workflow without replacing existing files.
13
+ - Added `.opsscript-gate.json` with CLI and Action overrides.
14
+ - Added `--dry-run`, `minimal` and `ubuntu` presets, exclusion globs, and `--output` reports.
15
+ - Added configuration, Chinese quickstart, and Ubuntu/Alpine troubleshooting documentation.
16
+
17
+ ### Fixed
18
+ - Discovery stops at the first candidate beyond the configured limit instead of silently ignoring files.
19
+ - Discovery skips symlinks and non-files and checks shebangs without prefix matches.
20
+ - CLI validates limits and network modes before execution.
21
+ - Empty Action inputs no longer override project configuration.
22
+
23
+ ### Migration
24
+ - Repositories with more than 20 discovered scripts must exclude unwanted scripts or raise `max_scripts`.
25
+ - Auto-discovery no longer follows file symlinks; explicit script paths remain supported.
26
+ - Default settings without a configuration file remain compatible with v0.4.1 and earlier.
27
+ - Generated workflows use the v0.5.0 release tag.
28
+
3
29
  All notable changes to this project will be documented in this file.
4
30
 
5
31
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
@@ -8,8 +34,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
8
34
  ## [0.4.1] - 2026-09-19
9
35
 
10
36
  ### Fixed & Hardened
11
- - **Bounded container log capture**: Stream-captures container logs using an immediate rolling byte buffer capped at 256 KiB (`MAX_CAPTURED_LOG_BYTES`) and tail limited to 500 lines (`MAX_LOG_TAIL_LINES`), bounding retained container log data to reduce memory-exhaustion risk from runaway output.
12
- - **Workflow command neutralization**: Neutralizes untrusted container logs starting with `::` into `[container] ::` to prevent malicious scripts from forging GitHub Actions workflow commands in Runner consoles, while keeping OpsScript Gate's own annotations intact.
37
+ - Bounded container log capture with a 256 KiB rolling buffer and 500-line tail.
38
+ - Neutralized untrusted container logs beginning with `::` before they reach GitHub Actions.
13
39
  - **Terminal ANSI and control character sanitization**: Strips ANSI escape sequences (CSI, OSC, 2-byte escapes), removes dangerous C0 control characters and DEL, and normalizes CRLF and standalone carriage returns (`\r`) to defeat terminal line overwrite and status spoofing, while preserving printable Unicode.
14
40
  - **Context-sensitive Markdown and HTML injection defense**: Implemented dedicated escaping (`escape_inline_code`, `escape_markdown_text`, `escape_markdown_table_cell`, `escape_html_text`, `format_safe_code_fence`) to prevent table cell tearing, HTML container breakout (`</details>`), premature code fence closure, and structural Markdown injection from runtime-derived values.
15
41
  - **Bounded streaming script preparation**: Stream-normalizes CRLF in bounded 64 KiB chunks (`SCRIPT_READ_CHUNK_SIZE`), properly handling boundary-split CRLF while preserving lone CR bytes without whole-file memory allocation. Bounded shebang parsing to 4096 bytes (`MAX_SHEBANG_BYTES`).
@@ -22,15 +48,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
22
48
  ## [0.4.0] - 2026-09-19
23
49
 
24
50
  ### Added
25
- - **High-confidence line-level GitHub Actions annotations**: Emits inline `::error` annotations with exact script line numbers directly on pull request file diffs.
51
+ - Line-level GitHub Actions annotations with script paths and line numbers.
26
52
  - **Workflow command injection defense**: Strictly escapes parameters (`%`, `\r`, `\n`, `:`, `,`) and message bodies (`%`, `\r`, `\n`) to eliminate command injection from unclassified container logs.
27
- - **Conservative distro-aware remediation hints**: Suggests testable, high-confidence remediation recommendations (`RemediationRule`) with conservative phrasing (`normally`, `may`, `consider`), covering:
53
+ - Distro-aware remediation hints for common mismatches, including:
28
54
  - Alpine package manager mismatches (`apt`/`apt-get` -> `apk`)
29
55
  - Debian/Ubuntu package manager mismatches (`apk` -> `apt-get`)
30
56
  - Alpine minimal missing Bash (`bash` -> consider POSIX sh or installing bash)
31
57
  - Missing network prerequisites (`curl`, `wget`)
32
58
  - Missing shebang interpreter paths.
33
- - **Re-engineered Compatibility Card**: Overhauled GitHub Actions Step Summary with an instant 5-second triage table and an expandable copy-pasteable Markdown snippet ready for PR descriptions and Issue comments.
59
+ - Updated the GitHub Actions Step Summary with a compatibility table and a Markdown result block.
34
60
  - **Parallel matrix execution (`--jobs` / `jobs`)**: Concurrently runs container checks using `ThreadPoolExecutor` (defaults to `min(2, matrix_size)`), strictly preserving matrix output order and ensuring reliable container cleanup.
35
61
  - **Hardened container resource limits**: Added `--mem-limit` (default: 256m) and `--pids-limit` (default: 128) flags and Action inputs to prevent runaway resource exhaustion.
36
62
  - **Configurable network isolation (`--network`)**: Supports `--network bridge` (default) and `--network none` for offline script execution.
@@ -47,7 +73,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
47
73
 
48
74
  ### Added
49
75
  - Structured runtime failure diagnostics: detect common "command not found" failures across Linux distributions (Alpine/BusyBox ash, Debian/Ubuntu dash, Bash, and missing interpreter paths).
50
- - High-confidence dual-signal classification: requires exit code 127 and matching shell output to produce a `missing_command` diagnostic.
76
+ - Missing-command classification requires exit code 127 and matching shell output.
51
77
  - Additive `diagnostic` field in JSON report format (`SingleResult.to_dict()`) providing structured diagnostic information (backward-compatible for consumers tolerating additional fields).
52
78
  - Enhanced terminal table formatting and GitHub Actions Step Summary showing clear failure causes in the summary overview.
53
79
 
@@ -81,7 +107,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
81
107
  ### Added
82
108
  - Configured PyPI Trusted Publishing via GitHub Actions OIDC (`pypa/gh-action-pypi-publish`).
83
109
  - Added full PyPI package metadata, classifiers, and project URLs to `pyproject.toml`.
84
- - Ensured absolute asset URLs in `README.md` for seamless PyPI rendering.
110
+ - Ensured asset URLs in `README.md` render correctly on PyPI.
85
111
 
86
112
  ---
87
113
 
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: opsscript-gate
3
- Version: 0.4.1
4
- Summary: Run Linux shell scripts across Debian, Ubuntu and Alpine before release to catch runtime compatibility failures
3
+ Version: 0.5.1
4
+ Summary: Run Linux shell scripts in Debian, Ubuntu and Alpine containers to catch runtime compatibility failures before merge
5
5
  Project-URL: Homepage, https://github.com/Mresyzz/opsscript-gate
6
6
  Project-URL: Repository, https://github.com/Mresyzz/opsscript-gate
7
7
  Project-URL: Issues, https://github.com/Mresyzz/opsscript-gate/issues
@@ -26,9 +26,11 @@ Provides-Extra: test
26
26
  Requires-Dist: pytest>=8.0.0; extra == 'test'
27
27
  Description-Content-Type: text/markdown
28
28
 
29
- # OpsScript Gate
29
+ # OpsScript Gate — shell script compatibility testing
30
30
 
31
- > **ShellCheck tells you if your script looks portable. OpsScript Gate checks if it actually runs there.**
31
+ [简体中文](README.zh-CN.md) · [Configuration](docs/configuration.md) · [Troubleshooting](docs/troubleshooting.md)
32
+
33
+ > ShellCheck analyzes shell syntax. OpsScript Gate executes scripts in Linux containers.
32
34
 
33
35
  [![CI](https://github.com/Mresyzz/opsscript-gate/actions/workflows/test.yml/badge.svg)](https://github.com/Mresyzz/opsscript-gate/actions/workflows/test.yml)
34
36
  [![Demo](https://github.com/Mresyzz/opsscript-gate/actions/workflows/demo.yml/badge.svg)](https://github.com/Mresyzz/opsscript-gate/actions/workflows/demo.yml)
@@ -39,15 +41,42 @@ Description-Content-Type: text/markdown
39
41
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
40
42
  [![Supported Distros](https://img.shields.io/badge/matrix-Debian%20%7C%20Ubuntu%20%7C%20Alpine-orange.svg)](#default-test-matrix)
41
43
 
42
- **OpsScript Gate** is a drop-in runtime compatibility gate for Linux shell scripts. It executes your scripts inside unprivileged Debian, Ubuntu, and Alpine containers before merge, catching environment-specific runtime failures, missing interpreters, and package-manager assumptions that static analysis cannot detect.
44
+ **OpsScript Gate** is a runtime compatibility checker for Linux shell scripts. It executes scripts inside unprivileged Debian, Ubuntu, and Alpine containers, catching environment-specific failures, missing interpreters, and package-manager assumptions that static analysis cannot detect.
45
+
46
+ It is designed for shell testing, portable shell validation, Bash/POSIX compatibility checks, and cross-distro CI where syntax-only tooling is not enough.
43
47
 
44
48
  ---
45
49
 
46
- ## ⚡ 30-Second Quickstart
50
+ ## Current release: v0.5.1
51
+
52
+ The current release includes a project config file, a dry-run plan, presets, exclusions,
53
+ and saved reports. These controls were introduced in v0.5.0; projects on v0.4.1 and
54
+ earlier do not include them.
55
+
56
+ ```bash
57
+ opsscript-gate init
58
+ opsscript-gate run --dry-run
59
+ opsscript-gate run --format json --output reports/compatibility.json
60
+ ```
47
61
 
48
- ### In GitHub Actions (Zero Config)
62
+ `init` creates `.opsscript-gate.json` and a GitHub Actions workflow without replacing
63
+ existing files. Review its exclusions (`tests/*`, `examples/*`) and offline network
64
+ default before running. No Docker is required for `init` or `--dry-run`.
49
65
 
50
- Drop this minimal workflow into `.github/workflows/shell-compat.yml`:
66
+ Useful for standalone installers, container entrypoints and release scripts that
67
+ must work on both GNU/Linux and Alpine/BusyBox. Each script runs independently;
68
+ repository files, sibling scripts and project dependencies are **not** mounted.
69
+ See [configuration and migration](docs/configuration.md) and
70
+ [why a shell script works on Ubuntu but fails on Alpine](docs/troubleshooting.md).
71
+
72
+ ## Quickstart
73
+
74
+ ### In GitHub Actions
75
+
76
+ Add this workflow to `.github/workflows/shell-compat.yml`:
77
+
78
+ You can copy the maintained example from [`examples/github-actions/workflow.yml`](examples/github-actions/workflow.yml)
79
+ and change the `script-path`, or use the minimal workflow below.
51
80
 
52
81
  ```yaml
53
82
  name: Shell Compatibility Gate
@@ -58,15 +87,16 @@ jobs:
58
87
  runs-on: ubuntu-latest
59
88
  steps:
60
89
  - uses: actions/checkout@v7
61
- - uses: Mresyzz/opsscript-gate@v0.4.1
90
+ - uses: Mresyzz/opsscript-gate@v0.5.1
62
91
  ```
63
92
 
64
- > **Zero Config**: If `script-path` is omitted, OpsScript Gate automatically discovers shell scripts in your repository and tests them concurrently!
93
+ If `script-path` is omitted, the action discovers shell scripts in the repository.
94
+ Use `opsscript-gate run --dry-run` to inspect the selection before running it.
65
95
 
66
96
  Or test a specific script with custom execution modes:
67
97
 
68
98
  ```yaml
69
- - uses: Mresyzz/opsscript-gate@v0.4.1
99
+ - uses: Mresyzz/opsscript-gate@v0.5.1
70
100
  with:
71
101
  script-path: scripts/install.sh
72
102
  shell: auto
@@ -88,21 +118,50 @@ opsscript-gate run ./scripts/install.sh
88
118
  opsscript-gate run
89
119
  ```
90
120
 
121
+ ### Example: package-manager mismatch
122
+
123
+ Create `install.sh`:
124
+
125
+ ```sh
126
+ #!/bin/sh
127
+ set -e
128
+ apt-get --version
129
+ ```
130
+
131
+ Then run:
132
+
133
+ ```bash
134
+ opsscript-gate run ./install.sh
135
+ ```
136
+
137
+ A typical result across the default matrix looks like this:
138
+
139
+ ```text
140
+ Debian 12 PASS
141
+ Ubuntu 22.04 PASS
142
+ Ubuntu 24.04 PASS
143
+ Alpine 3.20 FAIL
144
+
145
+ apt-get: not found
146
+ ```
147
+
148
+ The script is valid shell, but it assumes a command that is not present in Alpine.
149
+
91
150
  ---
92
151
 
93
- ## 🎯 Reviewer-First Experience: What It Produces
152
+ ## CI output
94
153
 
95
- Every run of OpsScript Gate generates clean, actionable feedback right where developers and reviewers need it:
154
+ The action reports failures in two places:
96
155
 
97
- ### 1. Line-Level GitHub Annotations
98
- When a failure occurs, OpsScript Gate flags the exact script line on your Pull Request's **Files Changed** view with high-confidence diagnostics and conservative remediation hints:
156
+ ### GitHub annotations
157
+ Failures include the script path, line number, distribution, and a short diagnostic:
99
158
 
100
159
  ```text
101
160
  ::error file=scripts/setup.sh,line=4,title=OpsScript Gate: [alpine:3.20] command not found: apt-get::command not found: apt-get — Alpine normally uses apk instead of apt-get.
102
161
  ```
103
162
 
104
- ### 2. GitHub Step Summary Compatibility Card
105
- A beautifully formatted markdown summary is automatically posted to `$GITHUB_STEP_SUMMARY`:
163
+ ### Step summary
164
+ The action also writes a markdown matrix to `$GITHUB_STEP_SUMMARY`:
106
165
 
107
166
  ```markdown
108
167
  ## 🛡️ OpsScript Gate Compatibility Report
@@ -121,14 +180,14 @@ A beautifully formatted markdown summary is automatically posted to `$GITHUB_STE
121
180
  | `alpine:3.20` | ❌ FAIL | `127` | `0.19s` | ⚠️ Missing command: `apt-get` (line 4)<br>💡 *Alpine normally uses apk instead of apt-get.* |
122
181
 
123
182
  <details>
124
- <summary>📋 <b>Copyable Markdown (Click to expand & copy to PR / Issue)</b></summary>
183
+ <summary><b>Markdown result</b></summary>
125
184
  ...
126
185
  </details>
127
186
  ```
128
187
 
129
188
  ---
130
189
 
131
- ## 🔍 Example: What Static Analysis Misses
190
+ ## Example: runtime behavior that static analysis misses
132
191
 
133
192
  Consider this clean deployment script:
134
193
 
@@ -165,34 +224,38 @@ Failed Distributions - Output Snippets (last 15 lines):
165
224
  sh: line 4: apt-get: not found
166
225
  ```
167
226
 
168
- **Why it failed:** Alpine Linux is musl/BusyBox-based and uses `apk`, not `apt-get`. OpsScript Gate catches the missing command (`exit code 127`) and gives you the exact line number and conservative remediation hint before deployment.
227
+ **Why it failed:** Alpine uses `apk`, not `apt-get`. The report includes the missing command and its line number.
169
228
 
170
229
  ---
171
230
 
172
- ## 🛡️ Why OpsScript Gate?
231
+ ## Scope compared with other checks
173
232
 
174
- ### OpsScript Gate vs ShellCheck vs Custom CI Matrix
233
+ ### OpsScript Gate compared with ShellCheck and a custom CI matrix
175
234
 
176
235
  | Capability | OpsScript Gate | ShellCheck | Handwritten CI Matrix |
177
236
  | :--- | :---: | :---: | :---: |
178
237
  | **Runtime execution** | **Yes** | No (Static AST only) | Yes |
179
238
  | **Real distro environments** | **Yes (Debian, Ubuntu, Alpine)** | No | Yes |
180
239
  | **Preconfigured defaults** | **Yes** | Yes | Requires custom workflow configuration |
181
- | **Hardened container defaults** | **Built-in (`ro`, `cap_drop`, resource limits)** | N/A | User-defined |
240
+ | **Restricted container defaults** | **Built-in (`ro`, `cap_drop`, resource limits)** | N/A | User-defined |
182
241
  | **Anti-hang stdin protection** | **Built-in (`</dev/null`, noninteractive)** | No | User-defined |
183
- | **Line-Level Annotations & Hints** | **Built-in (Zero config)** | Static warnings | User-defined |
242
+ | **Line-Level Annotations & Hints** | **Built-in** | Static warnings | User-defined |
184
243
  | **Parallel Matrix Execution** | **Built-in (`--jobs`)** | N/A | Manual matrix config |
185
244
 
186
- - **ShellCheck** is indispensable for static analysis (syntax, quoting, SC warnings). OpsScript Gate complements it by testing actual execution behavior in real distributions.
187
- - **Handwritten CI Matrix** requires maintaining complex Docker configurations, volume mounts, timeout guards, and log parsers across every project. OpsScript Gate packages this into a single check.
245
+ ShellCheck checks shell syntax and common mistakes. OpsScript Gate runs the script in
246
+ real distributions. A custom CI matrix can do the same job, but each repository must
247
+ maintain its own images, mounts, timeouts, and report handling.
188
248
 
189
249
  ---
190
250
 
191
- ## 🔒 Security Boundaries & Hardened Isolation
251
+ ## Security boundaries and container isolation
192
252
 
193
- OpsScript Gate is not a security sandbox for untrusted code. Containers may run as the image's default user, and Docker containers still share the host kernel.
253
+ OpsScript Gate is a runtime compatibility testing tool, **not a security sandbox for hostile or fully untrusted code**. Containers still share the host kernel, so target scripts should be treated accordingly.
194
254
 
195
- OpsScript Gate applies conservative, restricted container defaults when running scripts:
255
+ <details>
256
+ <summary><strong>View security boundaries and runtime hardening details</strong></summary>
257
+
258
+ The runner uses restricted container defaults:
196
259
 
197
260
  1. **Restricted Container Defaults**:
198
261
  - Containers run with `privileged=False`.
@@ -208,25 +271,41 @@ OpsScript Gate applies conservative, restricted container defaults when running
208
271
  4. **Anti-Hang Deadlock Defense**:
209
272
  - Disables TTY and stdin (`stdin_open=False`, `tty=False`).
210
273
  - Disconnects standard input: `/bin/sh -c "... /tmp/target_script.sh </dev/null"`.
211
- - Injects `DEBIAN_FRONTEND=noninteractive` and `CI=true`. Interactive prompts (`read -p`) fail immediately instead of hanging CI runners.
274
+ - Injects `DEBIAN_FRONTEND=noninteractive` and `CI=true`. Interactive prompts (`read -p`) fail instead of hanging CI runners.
212
275
  5. **Hard Timeout & Container Cleanup**:
213
276
  - Enforces configurable timeout (default: 60s). Timed-out containers are sent `SIGKILL` and marked `TIMED_OUT`.
214
277
  - Container removal is attempted from a `finally` block in normal, failure, and timeout execution paths.
215
278
  6. **Bounded Output & Memory Protection**:
216
- - Captures container logs using an immediate rolling byte buffer capped at 256 KiB (`MAX_CAPTURED_LOG_BYTES`) and tail limited to 500 lines (`MAX_LOG_TAIL_LINES`), which bounds retained container log data to reduce memory-exhaustion risk.
279
+ - Captures container logs using a rolling byte buffer capped at 256 KiB (`MAX_CAPTURED_LOG_BYTES`) and a 500-line tail limit (`MAX_LOG_TAIL_LINES`) to reduce memory-exhaustion risk from runaway output.
217
280
  7. **Untrusted Log Neutralization & Terminal Defense**:
218
281
  - Neutralizes line-leading workflow commands (`[container] ::`) to prevent forged GitHub Actions annotations in CI runners.
219
- - Strips ANSI escape sequences and dangerous C0 control characters, and normalizes carriage returns (`\r`) to defeat terminal line overwrite spoofing.
220
- - Employs context-sensitive escaping (`escape_inline_code`, `escape_markdown_text`, `escape_markdown_table_cell`, `escape_html_text`, `format_safe_code_fence`) to prevent Step Summary layout disruptions.
282
+ - Strips ANSI escape sequences and dangerous C0 control characters, and normalizes carriage returns (`\r`) to defeat terminal line-overwrite spoofing.
283
+ - Employs context-sensitive escaping (`escape_inline_code`, `escape_markdown_text`, `escape_markdown_table_cell`, `escape_html_text`, `format_safe_code_fence`) to protect Step Summary output contexts.
221
284
  8. **Command Injection Defense**:
222
- - OpsScript Gate's own annotations (`::error`) apply strict percent-encoding for all properties and message bodies, preventing workflow command injection.
285
+ - OpsScript Gate's own annotations (`::error`) apply strict percent-encoding for workflow-command fields and message bodies.
223
286
  9. **Bounded Streaming CRLF & Shebang Defense**:
224
- - Stream-normalizes carriage returns in 64 KiB chunks, preserving lone CR bytes and bounds shebang parsing to 4096 bytes without whole-file memory allocation.
287
+ - Stream-normalizes CRLF in 64 KiB chunks and bounds shebang parsing to 4096 bytes without whole-file memory allocation.
225
288
  - Pre-normalizes scripts once before parallel matrix runs, sharing a read-only prepared path across worker threads.
226
289
 
290
+ For the complete supported-version policy and vulnerability reporting guidance, see [SECURITY.md](SECURITY.md).
291
+
292
+ </details>
293
+
294
+ ### When NOT to use OpsScript Gate
295
+
296
+ OpsScript Gate is intentionally focused on Linux shell runtime compatibility. It is not designed for:
297
+
298
+ - executing hostile or fully untrusted third-party scripts
299
+ - kernel-level or privileged behavior testing
300
+ - replacing full integration or end-to-end test suites
301
+ - validating macOS or Windows behavior
302
+ - proving that a script is secure
303
+
304
+ Use it when you want to know whether a shell script actually runs across the supported Linux distributions.
305
+
227
306
  ---
228
307
 
229
- ## 📦 Default Test Matrix
308
+ ## Default test matrix
230
309
 
231
310
  | Image | Distribution | Focus |
232
311
  | :--- | :--- | :--- |
@@ -239,7 +318,7 @@ Customize the matrix at any time via `--matrix` or Action input `matrix`.
239
318
 
240
319
  ---
241
320
 
242
- ## 🛠️ CLI Reference
321
+ ## CLI reference
243
322
 
244
323
  ```text
245
324
  usage: opsscript-gate run [-h] [--matrix MATRIX] [-j JOBS] [--timeout TIMEOUT]
@@ -276,9 +355,25 @@ usage: opsscript-gate run [-h] [--matrix MATRIX] [-j JOBS] [--timeout TIMEOUT]
276
355
 
277
356
  ---
278
357
 
279
- ## 🐶 Dogfooding
358
+ ### v0.5.0 project controls
359
+
360
+ | Option | Purpose |
361
+ | :--- | :--- |
362
+ | `init` | Generate configuration and a GitHub workflow without overwriting files |
363
+ | `--dry-run` | Preview selected scripts, images and total executions without Docker |
364
+ | `--config PATH` | Load a specific JSON configuration file |
365
+ | `--preset minimal` | Debian + Alpine (two container runs per script) |
366
+ | `--preset ubuntu` | Ubuntu 22.04 + 24.04 |
367
+ | `--exclude 'tests/*'` | Exclude a repository-relative glob; repeatable |
368
+ | `--max-scripts 50` | Raise the default discovery limit of 20; overflow is an error |
369
+ | `--output report.json` | Save the selected output format, including failed test reports |
370
+
371
+ Explicit CLI options override project settings. Explicit script paths bypass discovery
372
+ and its exclusions. See [complete configuration semantics](docs/configuration.md).
280
373
 
281
- OpsScript Gate is actively used in [`Mresyzz/linux-dev-bootstrap`](https://github.com/Mresyzz/linux-dev-bootstrap) to validate `install.sh` across the default Debian, Ubuntu, and Alpine matrix in GitHub Actions.
374
+ ## Downstream example
375
+
376
+ [`Mresyzz/linux-dev-bootstrap`](https://github.com/Mresyzz/linux-dev-bootstrap) contains a workflow that validates `install.sh` across the default Debian, Ubuntu, and Alpine matrix.
282
377
 
283
378
  See the downstream workflow: [`.github/workflows/test.yml`](https://github.com/Mresyzz/linux-dev-bootstrap/blob/main/.github/workflows/test.yml).
284
379
 
@@ -303,6 +398,12 @@ pytest -v
303
398
 
304
399
  ---
305
400
 
401
+ ## Feedback
402
+
403
+ Please report compatibility cases, bugs, and pull requests in the issue tracker.
404
+
405
+ ---
406
+
306
407
  ## 📄 License
307
408
 
308
409
  OpsScript Gate is licensed under the [MIT License](LICENSE).