opsscript-gate 0.3.0__tar.gz → 0.4.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.
- {opsscript_gate-0.3.0 → opsscript_gate-0.4.0}/.github/workflows/demo.yml +2 -0
- {opsscript_gate-0.3.0 → opsscript_gate-0.4.0}/CHANGELOG.md +24 -0
- opsscript_gate-0.4.0/PKG-INFO +301 -0
- opsscript_gate-0.4.0/README.md +273 -0
- opsscript_gate-0.4.0/ROADMAP.md +44 -0
- {opsscript_gate-0.3.0 → opsscript_gate-0.4.0}/SECURITY.md +6 -4
- {opsscript_gate-0.3.0 → opsscript_gate-0.4.0}/action.yml +34 -6
- opsscript_gate-0.4.0/docs/promotion/awesome-lists-pr.md +59 -0
- opsscript_gate-0.4.0/docs/promotion/juejin-zhihu-article.md +144 -0
- opsscript_gate-0.4.0/docs/promotion/reddit-devops.md +56 -0
- opsscript_gate-0.4.0/docs/promotion/show-hn.md +67 -0
- opsscript_gate-0.4.0/docs/promotion/v2ex-post.md +68 -0
- {opsscript_gate-0.3.0 → opsscript_gate-0.4.0}/pyproject.toml +1 -1
- {opsscript_gate-0.3.0 → opsscript_gate-0.4.0}/src/opsscript_gate/__init__.py +1 -1
- opsscript_gate-0.4.0/src/opsscript_gate/cli.py +233 -0
- opsscript_gate-0.4.0/src/opsscript_gate/discovery.py +106 -0
- {opsscript_gate-0.3.0 → opsscript_gate-0.4.0}/src/opsscript_gate/models.py +30 -0
- opsscript_gate-0.4.0/src/opsscript_gate/remediation.py +104 -0
- opsscript_gate-0.4.0/src/opsscript_gate/reporter.py +368 -0
- {opsscript_gate-0.3.0 → opsscript_gate-0.4.0}/src/opsscript_gate/runner.py +72 -14
- {opsscript_gate-0.3.0 → opsscript_gate-0.4.0}/tests/test_runner.py +369 -2
- opsscript_gate-0.3.0/PKG-INFO +0 -286
- opsscript_gate-0.3.0/README.md +0 -258
- opsscript_gate-0.3.0/ROADMAP.md +0 -33
- opsscript_gate-0.3.0/src/opsscript_gate/cli.py +0 -136
- opsscript_gate-0.3.0/src/opsscript_gate/reporter.py +0 -170
- {opsscript_gate-0.3.0 → opsscript_gate-0.4.0}/.gitattributes +0 -0
- {opsscript_gate-0.3.0 → opsscript_gate-0.4.0}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {opsscript_gate-0.3.0 → opsscript_gate-0.4.0}/.github/ISSUE_TEMPLATE/distro_request.yml +0 -0
- {opsscript_gate-0.3.0 → opsscript_gate-0.4.0}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {opsscript_gate-0.3.0 → opsscript_gate-0.4.0}/.github/assets/social-preview.png +0 -0
- {opsscript_gate-0.3.0 → opsscript_gate-0.4.0}/.github/pull_request_template.md +0 -0
- {opsscript_gate-0.3.0 → opsscript_gate-0.4.0}/.github/workflows/release.yml +0 -0
- {opsscript_gate-0.3.0 → opsscript_gate-0.4.0}/.github/workflows/test.yml +0 -0
- {opsscript_gate-0.3.0 → opsscript_gate-0.4.0}/.gitignore +0 -0
- {opsscript_gate-0.3.0 → opsscript_gate-0.4.0}/CONTRIBUTING.md +0 -0
- {opsscript_gate-0.3.0 → opsscript_gate-0.4.0}/LICENSE +0 -0
- {opsscript_gate-0.3.0 → opsscript_gate-0.4.0}/examples/alpine-incompatibility/README.md +0 -0
- {opsscript_gate-0.3.0 → opsscript_gate-0.4.0}/examples/alpine-incompatibility/apt_dependency.sh +0 -0
- {opsscript_gate-0.3.0 → opsscript_gate-0.4.0}/examples/basic/README.md +0 -0
- {opsscript_gate-0.3.0 → opsscript_gate-0.4.0}/examples/basic/clean_setup.sh +0 -0
- {opsscript_gate-0.3.0 → opsscript_gate-0.4.0}/examples/github-actions/README.md +0 -0
- {opsscript_gate-0.3.0 → opsscript_gate-0.4.0}/examples/github-actions/workflow.yml +0 -0
- {opsscript_gate-0.3.0 → opsscript_gate-0.4.0}/examples/interactive-hang/README.md +0 -0
- {opsscript_gate-0.3.0 → opsscript_gate-0.4.0}/examples/interactive-hang/prompt_confirm.sh +0 -0
- {opsscript_gate-0.3.0 → opsscript_gate-0.4.0}/tests/fixtures/fail_deps.sh +0 -0
- {opsscript_gate-0.3.0 → opsscript_gate-0.4.0}/tests/fixtures/fail_hang.sh +0 -0
- {opsscript_gate-0.3.0 → opsscript_gate-0.4.0}/tests/fixtures/pass_basic.sh +0 -0
|
@@ -5,6 +5,30 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.4.0] - 2026-09-19
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- **High-confidence line-level GitHub Actions annotations**: Emits inline `::error` annotations with exact script line numbers directly on pull request file diffs.
|
|
12
|
+
- **Workflow command injection defense**: Strictly escapes parameters (`%`, `\r`, `\n`, `:`, `,`) and message bodies (`%`, `\r`, `\n`) to eliminate command injection from unclassified container logs.
|
|
13
|
+
- **Conservative distro-aware remediation hints**: Suggests testable, high-confidence remediation recommendations (`RemediationRule`) with conservative phrasing (`normally`, `may`, `consider`), covering:
|
|
14
|
+
- Alpine package manager mismatches (`apt`/`apt-get` -> `apk`)
|
|
15
|
+
- Debian/Ubuntu package manager mismatches (`apk` -> `apt-get`)
|
|
16
|
+
- Alpine minimal missing Bash (`bash` -> consider POSIX sh or installing bash)
|
|
17
|
+
- Missing network prerequisites (`curl`, `wget`)
|
|
18
|
+
- Missing shebang interpreter paths.
|
|
19
|
+
- **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.
|
|
20
|
+
- **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.
|
|
21
|
+
- **Hardened container resource limits**: Added `--mem-limit` (default: 256m) and `--pids-limit` (default: 128) flags and Action inputs to prevent runaway resource exhaustion.
|
|
22
|
+
- **Configurable network isolation (`--network`)**: Supports `--network bridge` (default) and `--network none` for offline script execution.
|
|
23
|
+
- **Zero-config repository script auto-discovery**: Running `opsscript-gate run` without arguments automatically discovers and validates shell scripts in the repository, ignoring directories like `.git`, `node_modules`, and `.venv`, capped at 20 scripts and 1 MB per file.
|
|
24
|
+
- **Multi-script test consolidation (`MultiScriptReport`)**: Supports aggregate reporting and Step Summary cards when multiple scripts are evaluated in a single run.
|
|
25
|
+
|
|
26
|
+
### Changed
|
|
27
|
+
- **Action initialization performance**: Removed redundant `pip install --upgrade pip` step in composite `action.yml` to minimize Action startup latency.
|
|
28
|
+
- **Flexible Action inputs**: Made `script-path` optional in `action.yml` (triggers auto-discovery if omitted); added inputs `jobs`, `mem-limit`, `pids-limit`, and `network`.
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
8
32
|
## [0.3.0] - 2026-09-19
|
|
9
33
|
|
|
10
34
|
### Added
|
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: opsscript-gate
|
|
3
|
+
Version: 0.4.0
|
|
4
|
+
Summary: Run Linux shell scripts across Debian, Ubuntu and Alpine before release to catch runtime compatibility failures
|
|
5
|
+
Project-URL: Homepage, https://github.com/Mresyzz/opsscript-gate
|
|
6
|
+
Project-URL: Repository, https://github.com/Mresyzz/opsscript-gate
|
|
7
|
+
Project-URL: Issues, https://github.com/Mresyzz/opsscript-gate/issues
|
|
8
|
+
Project-URL: Changelog, https://github.com/Mresyzz/opsscript-gate/blob/main/CHANGELOG.md
|
|
9
|
+
Author: Mresyzz
|
|
10
|
+
License: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: ci,compatibility,cross-distro,devops,docker,github-actions,linux,posix,shell,testing
|
|
13
|
+
Classifier: Development Status :: 3 - Alpha
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Intended Audience :: System Administrators
|
|
16
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Topic :: Software Development :: Testing
|
|
22
|
+
Classifier: Topic :: System :: Systems Administration
|
|
23
|
+
Requires-Python: >=3.10
|
|
24
|
+
Requires-Dist: docker>=7.0.0
|
|
25
|
+
Provides-Extra: test
|
|
26
|
+
Requires-Dist: pytest>=8.0.0; extra == 'test'
|
|
27
|
+
Description-Content-Type: text/markdown
|
|
28
|
+
|
|
29
|
+
# OpsScript Gate
|
|
30
|
+
|
|
31
|
+
> **ShellCheck tells you if your script looks portable. OpsScript Gate checks if it actually runs there.**
|
|
32
|
+
|
|
33
|
+
[](https://github.com/Mresyzz/opsscript-gate/actions/workflows/test.yml)
|
|
34
|
+
[](https://github.com/Mresyzz/opsscript-gate/actions/workflows/demo.yml)
|
|
35
|
+
[](https://pypi.org/project/opsscript-gate/)
|
|
36
|
+
[](https://pypi.org/project/opsscript-gate/)
|
|
37
|
+
[](https://github.com/marketplace/actions/opsscript-gate)
|
|
38
|
+
[](https://github.com/Mresyzz/opsscript-gate/releases)
|
|
39
|
+
[](https://opensource.org/licenses/MIT)
|
|
40
|
+
[](#default-test-matrix)
|
|
41
|
+
|
|
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.
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## ⚡ 30-Second Quickstart
|
|
47
|
+
|
|
48
|
+
### In GitHub Actions (Zero Config)
|
|
49
|
+
|
|
50
|
+
Drop this minimal workflow into `.github/workflows/shell-compat.yml`:
|
|
51
|
+
|
|
52
|
+
```yaml
|
|
53
|
+
name: Shell Compatibility Gate
|
|
54
|
+
on: [pull_request, push]
|
|
55
|
+
|
|
56
|
+
jobs:
|
|
57
|
+
compat:
|
|
58
|
+
runs-on: ubuntu-latest
|
|
59
|
+
steps:
|
|
60
|
+
- uses: actions/checkout@v7
|
|
61
|
+
- uses: Mresyzz/opsscript-gate@v0.4.0
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
> **Zero Config**: If `script-path` is omitted, OpsScript Gate automatically discovers shell scripts in your repository and tests them concurrently!
|
|
65
|
+
|
|
66
|
+
Or test a specific script with custom execution modes:
|
|
67
|
+
|
|
68
|
+
```yaml
|
|
69
|
+
- uses: Mresyzz/opsscript-gate@v0.4.0
|
|
70
|
+
with:
|
|
71
|
+
script-path: scripts/install.sh
|
|
72
|
+
shell: auto
|
|
73
|
+
jobs: 4
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### In Local Terminal (CLI)
|
|
77
|
+
|
|
78
|
+
Requires Python 3.10+ and a running local Docker engine:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
# Install from PyPI
|
|
82
|
+
pip install opsscript-gate
|
|
83
|
+
|
|
84
|
+
# Run against a specific script
|
|
85
|
+
opsscript-gate run ./scripts/install.sh
|
|
86
|
+
|
|
87
|
+
# Or auto-discover scripts across your repository
|
|
88
|
+
opsscript-gate run
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## 🎯 Reviewer-First Experience: What It Produces
|
|
94
|
+
|
|
95
|
+
Every run of OpsScript Gate generates clean, actionable feedback right where developers and reviewers need it:
|
|
96
|
+
|
|
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:
|
|
99
|
+
|
|
100
|
+
```text
|
|
101
|
+
::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
|
+
```
|
|
103
|
+
|
|
104
|
+
### 2. GitHub Step Summary Compatibility Card
|
|
105
|
+
A beautifully formatted markdown summary is automatically posted to `$GITHUB_STEP_SUMMARY`:
|
|
106
|
+
|
|
107
|
+
```markdown
|
|
108
|
+
## 🛡️ OpsScript Gate Compatibility Report
|
|
109
|
+
|
|
110
|
+
**Target Script**: `scripts/setup.sh`
|
|
111
|
+
**Status**: ❌ **CHECKS FAILED (3/4 Passed)**
|
|
112
|
+
**Total Duration**: `1.24s`
|
|
113
|
+
|
|
114
|
+
### 📊 Compatibility Matrix
|
|
115
|
+
|
|
116
|
+
| Distribution | Status | Exit Code | Time | Diagnostic & Recommendation |
|
|
117
|
+
| :--- | :---: | :---: | :---: | :--- |
|
|
118
|
+
| `debian:12-slim` | ✅ PASS | `0` | `0.42s` | OK |
|
|
119
|
+
| `ubuntu:22.04` | ✅ PASS | `0` | `0.38s` | OK |
|
|
120
|
+
| `ubuntu:24.04` | ✅ PASS | `0` | `0.35s` | OK |
|
|
121
|
+
| `alpine:3.20` | ❌ FAIL | `127` | `0.19s` | ⚠️ Missing command: `apt-get` (line 4)<br>💡 *Alpine normally uses apk instead of apt-get.* |
|
|
122
|
+
|
|
123
|
+
<details>
|
|
124
|
+
<summary>📋 <b>Copyable Markdown (Click to expand & copy to PR / Issue)</b></summary>
|
|
125
|
+
...
|
|
126
|
+
</details>
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
## 🔍 Example: What Static Analysis Misses
|
|
132
|
+
|
|
133
|
+
Consider this clean deployment script:
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
#!/bin/sh
|
|
137
|
+
set -e
|
|
138
|
+
echo "Fetching package information..."
|
|
139
|
+
apt-get --version
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Running `shellcheck` reports **0 errors, 0 warnings** because the syntax is syntactically valid POSIX shell.
|
|
143
|
+
|
|
144
|
+
However, when verified with **OpsScript Gate**:
|
|
145
|
+
|
|
146
|
+
```text
|
|
147
|
+
+----------------+----------+-----------+----------+------------------------------------+
|
|
148
|
+
| Distro | Status | Exit Code | Duration | Details |
|
|
149
|
+
+----------------+----------+-----------+----------+------------------------------------+
|
|
150
|
+
| debian:12-slim | PASS | 0 | 0.42s | OK |
|
|
151
|
+
| ubuntu:22.04 | PASS | 0 | 0.38s | OK |
|
|
152
|
+
| ubuntu:24.04 | PASS | 0 | 0.35s | OK |
|
|
153
|
+
| alpine:3.20 | FAIL | 127 | 0.19s | command not found: apt-get (line 4)|
|
|
154
|
+
+----------------+----------+-----------+----------+------------------------------------+
|
|
155
|
+
Total duration: 0.58s | Result: FAILED
|
|
156
|
+
|
|
157
|
+
Remediation Recommendations:
|
|
158
|
+
* [alpine:3.20] Alpine normally uses apk instead of apt-get.
|
|
159
|
+
|
|
160
|
+
============================================================
|
|
161
|
+
Failed Distributions - Output Snippets (last 15 lines):
|
|
162
|
+
============================================================
|
|
163
|
+
|
|
164
|
+
--- [alpine:3.20] (FAIL) ---
|
|
165
|
+
sh: line 4: apt-get: not found
|
|
166
|
+
```
|
|
167
|
+
|
|
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.
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
## 🛡️ Why OpsScript Gate?
|
|
173
|
+
|
|
174
|
+
### OpsScript Gate vs ShellCheck vs Custom CI Matrix
|
|
175
|
+
|
|
176
|
+
| Capability | OpsScript Gate | ShellCheck | Handwritten CI Matrix |
|
|
177
|
+
| :--- | :---: | :---: | :---: |
|
|
178
|
+
| **Runtime execution** | **Yes** | No (Static AST only) | Yes |
|
|
179
|
+
| **Real distro environments** | **Yes (Debian, Ubuntu, Alpine)** | No | Yes |
|
|
180
|
+
| **Preconfigured defaults** | **Yes** | Yes | Requires custom workflow configuration |
|
|
181
|
+
| **Hardened container defaults** | **Built-in (`ro`, `cap_drop`, resource limits)** | N/A | User-defined |
|
|
182
|
+
| **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 |
|
|
184
|
+
| **Parallel Matrix Execution** | **Built-in (`--jobs`)** | N/A | Manual matrix config |
|
|
185
|
+
|
|
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.
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
## 🔒 Security Boundaries & Hardened Isolation
|
|
192
|
+
|
|
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.
|
|
194
|
+
|
|
195
|
+
OpsScript Gate applies conservative, restricted container defaults when running scripts:
|
|
196
|
+
|
|
197
|
+
1. **Restricted Container Defaults**:
|
|
198
|
+
- Containers run with `privileged=False`.
|
|
199
|
+
- All Linux capabilities are dropped: `cap_drop=["ALL"]`.
|
|
200
|
+
- Privilege escalation is disabled: `security_opt=["no-new-privileges:true"]`.
|
|
201
|
+
2. **Resource Constraints**:
|
|
202
|
+
- Memory limits enforced per container (`--mem-limit`, default: `256m`).
|
|
203
|
+
- Process caps enforced to prevent fork bombs (`--pids-limit`, default: `128`).
|
|
204
|
+
- Network isolation configurable (`--network bridge` or `--network none`).
|
|
205
|
+
3. **Read-Only Target Mount**:
|
|
206
|
+
- The tested script is mounted read-only (`:ro`) at `/tmp/target_script.sh`.
|
|
207
|
+
- No host directories or sensitive sockets are mounted into test containers.
|
|
208
|
+
4. **Anti-Hang Deadlock Defense**:
|
|
209
|
+
- Disables TTY and stdin (`stdin_open=False`, `tty=False`).
|
|
210
|
+
- 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.
|
|
212
|
+
5. **Hard Timeout & Container Cleanup**:
|
|
213
|
+
- Enforces configurable timeout (default: 60s). Timed-out containers are sent `SIGKILL` and marked `TIMED_OUT`.
|
|
214
|
+
- Container removal is attempted from a `finally` block in normal, failure, and timeout execution paths.
|
|
215
|
+
6. **Command Injection Defense**:
|
|
216
|
+
- Workflow commands (`::error`) apply strict percent-encoding for all properties and message bodies, preventing unclassified container logs from injecting GitHub Actions workflow commands.
|
|
217
|
+
7. **Windows CRLF Defense**:
|
|
218
|
+
- Automatically detects and normalizes carriage returns (`\r\n` -> `\n`) before container execution, preventing false `\r: command not found` errors.
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
## 📦 Default Test Matrix
|
|
223
|
+
|
|
224
|
+
| Image | Distribution | Focus |
|
|
225
|
+
| :--- | :--- | :--- |
|
|
226
|
+
| `debian:12-slim` | Debian 12 (Bookworm) | Minimal glibc + APT base |
|
|
227
|
+
| `ubuntu:22.04` | Ubuntu 22.04 LTS (Jammy) | Enterprise long-term support baseline |
|
|
228
|
+
| `ubuntu:24.04` | Ubuntu 24.04 LTS (Noble) | Modern glibc, updated coreutils & defaults |
|
|
229
|
+
| `alpine:3.20` | Alpine Linux 3.20 | Minimal musl libc + BusyBox /bin/sh environment |
|
|
230
|
+
|
|
231
|
+
Customize the matrix at any time via `--matrix` or Action input `matrix`.
|
|
232
|
+
|
|
233
|
+
---
|
|
234
|
+
|
|
235
|
+
## 🛠️ CLI Reference
|
|
236
|
+
|
|
237
|
+
```text
|
|
238
|
+
usage: opsscript-gate run [-h] [--matrix MATRIX] [-j JOBS] [--timeout TIMEOUT]
|
|
239
|
+
[--format {table,markdown,json}]
|
|
240
|
+
[--shell {posix,shebang,auto}]
|
|
241
|
+
[--mem-limit MEM_LIMIT] [--pids-limit PIDS_LIMIT]
|
|
242
|
+
[--network NETWORK]
|
|
243
|
+
[script_path]
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
| Parameter | Type | Default | Description |
|
|
247
|
+
| :--- | :--- | :--- | :--- |
|
|
248
|
+
| `script_path` | Positional | *Optional* | Path to target shell script (auto-discovers if omitted) |
|
|
249
|
+
| `-j, --jobs` | Integer | `min(2, size)` | Number of concurrent container jobs |
|
|
250
|
+
| `--matrix` | String | `debian:12-slim,ubuntu:22.04,ubuntu:24.04,alpine:3.20` | Comma-separated list of Docker images |
|
|
251
|
+
| `--timeout` | Integer | `60` | Hard timeout per container in seconds |
|
|
252
|
+
| `--format` | Choice | `table` | Output format: `table`, `markdown`, or `json` |
|
|
253
|
+
| `--shell` | Choice | `posix` | Execution mode: `posix` (default), `shebang`, or `auto` |
|
|
254
|
+
| `--mem-limit` | String | `256m` | Memory limit per container (e.g. `256m`, `512m`) |
|
|
255
|
+
| `--pids-limit`| Integer | `128` | Maximum number of processes per container |
|
|
256
|
+
| `--network` | Choice | `bridge` | Container network mode: `bridge` or `none` |
|
|
257
|
+
| `--version` | Flag | - | Show version number |
|
|
258
|
+
| `-h, --help` | Flag | - | Show argument help |
|
|
259
|
+
|
|
260
|
+
### Shell Execution Modes (`--shell`)
|
|
261
|
+
|
|
262
|
+
- **`posix`** (default): Strictly executes with `/bin/sh`, ignoring any script shebang to verify portability against minimal POSIX environments (including Alpine BusyBox).
|
|
263
|
+
- **`shebang`**: Strictly honors the interpreter specified in the script's shebang (`#!/bin/sh`, `#!/bin/bash`, `#!/usr/bin/sh`, `#!/usr/bin/bash`, `#!/usr/bin/env sh`, `#!/usr/bin/env bash`). Fails immediately if shebang is missing, malformed, or unsupported.
|
|
264
|
+
- **`auto`**: Honors recognized shebangs if present; safely falls back to `/bin/sh` if no shebang is present.
|
|
265
|
+
|
|
266
|
+
### Exit Code Convention
|
|
267
|
+
- **`0`**: All tested scripts and distributions passed (`PASS`).
|
|
268
|
+
- **`1`**: At least one distribution failed (`FAIL`), timed out (`TIMED_OUT`), or errored (`ERROR`).
|
|
269
|
+
|
|
270
|
+
---
|
|
271
|
+
|
|
272
|
+
## 🐶 Dogfooding
|
|
273
|
+
|
|
274
|
+
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.
|
|
275
|
+
|
|
276
|
+
See the downstream workflow: [`.github/workflows/test.yml`](https://github.com/Mresyzz/linux-dev-bootstrap/blob/main/.github/workflows/test.yml).
|
|
277
|
+
|
|
278
|
+
---
|
|
279
|
+
|
|
280
|
+
## 🧪 Development & Testing
|
|
281
|
+
|
|
282
|
+
```bash
|
|
283
|
+
# Clone repository
|
|
284
|
+
git clone https://github.com/Mresyzz/opsscript-gate.git
|
|
285
|
+
cd opsscript-gate
|
|
286
|
+
|
|
287
|
+
# Install in editable mode with test dependencies
|
|
288
|
+
pip install -e .[test]
|
|
289
|
+
|
|
290
|
+
# Run unit tests (Mocked, no Docker daemon required)
|
|
291
|
+
pytest -v -m "not integration"
|
|
292
|
+
|
|
293
|
+
# Run integration tests (Requires local Docker daemon)
|
|
294
|
+
pytest -v
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
---
|
|
298
|
+
|
|
299
|
+
## 📄 License
|
|
300
|
+
|
|
301
|
+
OpsScript Gate is licensed under the [MIT License](LICENSE).
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
# OpsScript Gate
|
|
2
|
+
|
|
3
|
+
> **ShellCheck tells you if your script looks portable. OpsScript Gate checks if it actually runs there.**
|
|
4
|
+
|
|
5
|
+
[](https://github.com/Mresyzz/opsscript-gate/actions/workflows/test.yml)
|
|
6
|
+
[](https://github.com/Mresyzz/opsscript-gate/actions/workflows/demo.yml)
|
|
7
|
+
[](https://pypi.org/project/opsscript-gate/)
|
|
8
|
+
[](https://pypi.org/project/opsscript-gate/)
|
|
9
|
+
[](https://github.com/marketplace/actions/opsscript-gate)
|
|
10
|
+
[](https://github.com/Mresyzz/opsscript-gate/releases)
|
|
11
|
+
[](https://opensource.org/licenses/MIT)
|
|
12
|
+
[](#default-test-matrix)
|
|
13
|
+
|
|
14
|
+
**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.
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## ⚡ 30-Second Quickstart
|
|
19
|
+
|
|
20
|
+
### In GitHub Actions (Zero Config)
|
|
21
|
+
|
|
22
|
+
Drop this minimal workflow into `.github/workflows/shell-compat.yml`:
|
|
23
|
+
|
|
24
|
+
```yaml
|
|
25
|
+
name: Shell Compatibility Gate
|
|
26
|
+
on: [pull_request, push]
|
|
27
|
+
|
|
28
|
+
jobs:
|
|
29
|
+
compat:
|
|
30
|
+
runs-on: ubuntu-latest
|
|
31
|
+
steps:
|
|
32
|
+
- uses: actions/checkout@v7
|
|
33
|
+
- uses: Mresyzz/opsscript-gate@v0.4.0
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
> **Zero Config**: If `script-path` is omitted, OpsScript Gate automatically discovers shell scripts in your repository and tests them concurrently!
|
|
37
|
+
|
|
38
|
+
Or test a specific script with custom execution modes:
|
|
39
|
+
|
|
40
|
+
```yaml
|
|
41
|
+
- uses: Mresyzz/opsscript-gate@v0.4.0
|
|
42
|
+
with:
|
|
43
|
+
script-path: scripts/install.sh
|
|
44
|
+
shell: auto
|
|
45
|
+
jobs: 4
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### In Local Terminal (CLI)
|
|
49
|
+
|
|
50
|
+
Requires Python 3.10+ and a running local Docker engine:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
# Install from PyPI
|
|
54
|
+
pip install opsscript-gate
|
|
55
|
+
|
|
56
|
+
# Run against a specific script
|
|
57
|
+
opsscript-gate run ./scripts/install.sh
|
|
58
|
+
|
|
59
|
+
# Or auto-discover scripts across your repository
|
|
60
|
+
opsscript-gate run
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## 🎯 Reviewer-First Experience: What It Produces
|
|
66
|
+
|
|
67
|
+
Every run of OpsScript Gate generates clean, actionable feedback right where developers and reviewers need it:
|
|
68
|
+
|
|
69
|
+
### 1. Line-Level GitHub Annotations
|
|
70
|
+
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:
|
|
71
|
+
|
|
72
|
+
```text
|
|
73
|
+
::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.
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### 2. GitHub Step Summary Compatibility Card
|
|
77
|
+
A beautifully formatted markdown summary is automatically posted to `$GITHUB_STEP_SUMMARY`:
|
|
78
|
+
|
|
79
|
+
```markdown
|
|
80
|
+
## 🛡️ OpsScript Gate Compatibility Report
|
|
81
|
+
|
|
82
|
+
**Target Script**: `scripts/setup.sh`
|
|
83
|
+
**Status**: ❌ **CHECKS FAILED (3/4 Passed)**
|
|
84
|
+
**Total Duration**: `1.24s`
|
|
85
|
+
|
|
86
|
+
### 📊 Compatibility Matrix
|
|
87
|
+
|
|
88
|
+
| Distribution | Status | Exit Code | Time | Diagnostic & Recommendation |
|
|
89
|
+
| :--- | :---: | :---: | :---: | :--- |
|
|
90
|
+
| `debian:12-slim` | ✅ PASS | `0` | `0.42s` | OK |
|
|
91
|
+
| `ubuntu:22.04` | ✅ PASS | `0` | `0.38s` | OK |
|
|
92
|
+
| `ubuntu:24.04` | ✅ PASS | `0` | `0.35s` | OK |
|
|
93
|
+
| `alpine:3.20` | ❌ FAIL | `127` | `0.19s` | ⚠️ Missing command: `apt-get` (line 4)<br>💡 *Alpine normally uses apk instead of apt-get.* |
|
|
94
|
+
|
|
95
|
+
<details>
|
|
96
|
+
<summary>📋 <b>Copyable Markdown (Click to expand & copy to PR / Issue)</b></summary>
|
|
97
|
+
...
|
|
98
|
+
</details>
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## 🔍 Example: What Static Analysis Misses
|
|
104
|
+
|
|
105
|
+
Consider this clean deployment script:
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
#!/bin/sh
|
|
109
|
+
set -e
|
|
110
|
+
echo "Fetching package information..."
|
|
111
|
+
apt-get --version
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Running `shellcheck` reports **0 errors, 0 warnings** because the syntax is syntactically valid POSIX shell.
|
|
115
|
+
|
|
116
|
+
However, when verified with **OpsScript Gate**:
|
|
117
|
+
|
|
118
|
+
```text
|
|
119
|
+
+----------------+----------+-----------+----------+------------------------------------+
|
|
120
|
+
| Distro | Status | Exit Code | Duration | Details |
|
|
121
|
+
+----------------+----------+-----------+----------+------------------------------------+
|
|
122
|
+
| debian:12-slim | PASS | 0 | 0.42s | OK |
|
|
123
|
+
| ubuntu:22.04 | PASS | 0 | 0.38s | OK |
|
|
124
|
+
| ubuntu:24.04 | PASS | 0 | 0.35s | OK |
|
|
125
|
+
| alpine:3.20 | FAIL | 127 | 0.19s | command not found: apt-get (line 4)|
|
|
126
|
+
+----------------+----------+-----------+----------+------------------------------------+
|
|
127
|
+
Total duration: 0.58s | Result: FAILED
|
|
128
|
+
|
|
129
|
+
Remediation Recommendations:
|
|
130
|
+
* [alpine:3.20] Alpine normally uses apk instead of apt-get.
|
|
131
|
+
|
|
132
|
+
============================================================
|
|
133
|
+
Failed Distributions - Output Snippets (last 15 lines):
|
|
134
|
+
============================================================
|
|
135
|
+
|
|
136
|
+
--- [alpine:3.20] (FAIL) ---
|
|
137
|
+
sh: line 4: apt-get: not found
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
**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.
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
## 🛡️ Why OpsScript Gate?
|
|
145
|
+
|
|
146
|
+
### OpsScript Gate vs ShellCheck vs Custom CI Matrix
|
|
147
|
+
|
|
148
|
+
| Capability | OpsScript Gate | ShellCheck | Handwritten CI Matrix |
|
|
149
|
+
| :--- | :---: | :---: | :---: |
|
|
150
|
+
| **Runtime execution** | **Yes** | No (Static AST only) | Yes |
|
|
151
|
+
| **Real distro environments** | **Yes (Debian, Ubuntu, Alpine)** | No | Yes |
|
|
152
|
+
| **Preconfigured defaults** | **Yes** | Yes | Requires custom workflow configuration |
|
|
153
|
+
| **Hardened container defaults** | **Built-in (`ro`, `cap_drop`, resource limits)** | N/A | User-defined |
|
|
154
|
+
| **Anti-hang stdin protection** | **Built-in (`</dev/null`, noninteractive)** | No | User-defined |
|
|
155
|
+
| **Line-Level Annotations & Hints** | **Built-in (Zero config)** | Static warnings | User-defined |
|
|
156
|
+
| **Parallel Matrix Execution** | **Built-in (`--jobs`)** | N/A | Manual matrix config |
|
|
157
|
+
|
|
158
|
+
- **ShellCheck** is indispensable for static analysis (syntax, quoting, SC warnings). OpsScript Gate complements it by testing actual execution behavior in real distributions.
|
|
159
|
+
- **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.
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
## 🔒 Security Boundaries & Hardened Isolation
|
|
164
|
+
|
|
165
|
+
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.
|
|
166
|
+
|
|
167
|
+
OpsScript Gate applies conservative, restricted container defaults when running scripts:
|
|
168
|
+
|
|
169
|
+
1. **Restricted Container Defaults**:
|
|
170
|
+
- Containers run with `privileged=False`.
|
|
171
|
+
- All Linux capabilities are dropped: `cap_drop=["ALL"]`.
|
|
172
|
+
- Privilege escalation is disabled: `security_opt=["no-new-privileges:true"]`.
|
|
173
|
+
2. **Resource Constraints**:
|
|
174
|
+
- Memory limits enforced per container (`--mem-limit`, default: `256m`).
|
|
175
|
+
- Process caps enforced to prevent fork bombs (`--pids-limit`, default: `128`).
|
|
176
|
+
- Network isolation configurable (`--network bridge` or `--network none`).
|
|
177
|
+
3. **Read-Only Target Mount**:
|
|
178
|
+
- The tested script is mounted read-only (`:ro`) at `/tmp/target_script.sh`.
|
|
179
|
+
- No host directories or sensitive sockets are mounted into test containers.
|
|
180
|
+
4. **Anti-Hang Deadlock Defense**:
|
|
181
|
+
- Disables TTY and stdin (`stdin_open=False`, `tty=False`).
|
|
182
|
+
- Disconnects standard input: `/bin/sh -c "... /tmp/target_script.sh </dev/null"`.
|
|
183
|
+
- Injects `DEBIAN_FRONTEND=noninteractive` and `CI=true`. Interactive prompts (`read -p`) fail immediately instead of hanging CI runners.
|
|
184
|
+
5. **Hard Timeout & Container Cleanup**:
|
|
185
|
+
- Enforces configurable timeout (default: 60s). Timed-out containers are sent `SIGKILL` and marked `TIMED_OUT`.
|
|
186
|
+
- Container removal is attempted from a `finally` block in normal, failure, and timeout execution paths.
|
|
187
|
+
6. **Command Injection Defense**:
|
|
188
|
+
- Workflow commands (`::error`) apply strict percent-encoding for all properties and message bodies, preventing unclassified container logs from injecting GitHub Actions workflow commands.
|
|
189
|
+
7. **Windows CRLF Defense**:
|
|
190
|
+
- Automatically detects and normalizes carriage returns (`\r\n` -> `\n`) before container execution, preventing false `\r: command not found` errors.
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
## 📦 Default Test Matrix
|
|
195
|
+
|
|
196
|
+
| Image | Distribution | Focus |
|
|
197
|
+
| :--- | :--- | :--- |
|
|
198
|
+
| `debian:12-slim` | Debian 12 (Bookworm) | Minimal glibc + APT base |
|
|
199
|
+
| `ubuntu:22.04` | Ubuntu 22.04 LTS (Jammy) | Enterprise long-term support baseline |
|
|
200
|
+
| `ubuntu:24.04` | Ubuntu 24.04 LTS (Noble) | Modern glibc, updated coreutils & defaults |
|
|
201
|
+
| `alpine:3.20` | Alpine Linux 3.20 | Minimal musl libc + BusyBox /bin/sh environment |
|
|
202
|
+
|
|
203
|
+
Customize the matrix at any time via `--matrix` or Action input `matrix`.
|
|
204
|
+
|
|
205
|
+
---
|
|
206
|
+
|
|
207
|
+
## 🛠️ CLI Reference
|
|
208
|
+
|
|
209
|
+
```text
|
|
210
|
+
usage: opsscript-gate run [-h] [--matrix MATRIX] [-j JOBS] [--timeout TIMEOUT]
|
|
211
|
+
[--format {table,markdown,json}]
|
|
212
|
+
[--shell {posix,shebang,auto}]
|
|
213
|
+
[--mem-limit MEM_LIMIT] [--pids-limit PIDS_LIMIT]
|
|
214
|
+
[--network NETWORK]
|
|
215
|
+
[script_path]
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
| Parameter | Type | Default | Description |
|
|
219
|
+
| :--- | :--- | :--- | :--- |
|
|
220
|
+
| `script_path` | Positional | *Optional* | Path to target shell script (auto-discovers if omitted) |
|
|
221
|
+
| `-j, --jobs` | Integer | `min(2, size)` | Number of concurrent container jobs |
|
|
222
|
+
| `--matrix` | String | `debian:12-slim,ubuntu:22.04,ubuntu:24.04,alpine:3.20` | Comma-separated list of Docker images |
|
|
223
|
+
| `--timeout` | Integer | `60` | Hard timeout per container in seconds |
|
|
224
|
+
| `--format` | Choice | `table` | Output format: `table`, `markdown`, or `json` |
|
|
225
|
+
| `--shell` | Choice | `posix` | Execution mode: `posix` (default), `shebang`, or `auto` |
|
|
226
|
+
| `--mem-limit` | String | `256m` | Memory limit per container (e.g. `256m`, `512m`) |
|
|
227
|
+
| `--pids-limit`| Integer | `128` | Maximum number of processes per container |
|
|
228
|
+
| `--network` | Choice | `bridge` | Container network mode: `bridge` or `none` |
|
|
229
|
+
| `--version` | Flag | - | Show version number |
|
|
230
|
+
| `-h, --help` | Flag | - | Show argument help |
|
|
231
|
+
|
|
232
|
+
### Shell Execution Modes (`--shell`)
|
|
233
|
+
|
|
234
|
+
- **`posix`** (default): Strictly executes with `/bin/sh`, ignoring any script shebang to verify portability against minimal POSIX environments (including Alpine BusyBox).
|
|
235
|
+
- **`shebang`**: Strictly honors the interpreter specified in the script's shebang (`#!/bin/sh`, `#!/bin/bash`, `#!/usr/bin/sh`, `#!/usr/bin/bash`, `#!/usr/bin/env sh`, `#!/usr/bin/env bash`). Fails immediately if shebang is missing, malformed, or unsupported.
|
|
236
|
+
- **`auto`**: Honors recognized shebangs if present; safely falls back to `/bin/sh` if no shebang is present.
|
|
237
|
+
|
|
238
|
+
### Exit Code Convention
|
|
239
|
+
- **`0`**: All tested scripts and distributions passed (`PASS`).
|
|
240
|
+
- **`1`**: At least one distribution failed (`FAIL`), timed out (`TIMED_OUT`), or errored (`ERROR`).
|
|
241
|
+
|
|
242
|
+
---
|
|
243
|
+
|
|
244
|
+
## 🐶 Dogfooding
|
|
245
|
+
|
|
246
|
+
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.
|
|
247
|
+
|
|
248
|
+
See the downstream workflow: [`.github/workflows/test.yml`](https://github.com/Mresyzz/linux-dev-bootstrap/blob/main/.github/workflows/test.yml).
|
|
249
|
+
|
|
250
|
+
---
|
|
251
|
+
|
|
252
|
+
## 🧪 Development & Testing
|
|
253
|
+
|
|
254
|
+
```bash
|
|
255
|
+
# Clone repository
|
|
256
|
+
git clone https://github.com/Mresyzz/opsscript-gate.git
|
|
257
|
+
cd opsscript-gate
|
|
258
|
+
|
|
259
|
+
# Install in editable mode with test dependencies
|
|
260
|
+
pip install -e .[test]
|
|
261
|
+
|
|
262
|
+
# Run unit tests (Mocked, no Docker daemon required)
|
|
263
|
+
pytest -v -m "not integration"
|
|
264
|
+
|
|
265
|
+
# Run integration tests (Requires local Docker daemon)
|
|
266
|
+
pytest -v
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
---
|
|
270
|
+
|
|
271
|
+
## 📄 License
|
|
272
|
+
|
|
273
|
+
OpsScript Gate is licensed under the [MIT License](LICENSE).
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# OpsScript Gate Roadmap
|
|
2
|
+
|
|
3
|
+
This roadmap tracks features delivered in recent releases and areas under consideration for future versions.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Delivered in v0.4.0
|
|
8
|
+
|
|
9
|
+
- [x] **High-confidence Line-level GitHub Actions Annotations**: Emits safe `::error` annotations linking failure lines directly on pull request file diffs.
|
|
10
|
+
- [x] **Distro-aware Remediation Hints**: Conservative, testable hints for Alpine vs Debian package managers, missing bash interpreters, and core utilities.
|
|
11
|
+
- [x] **Interactive Compatibility Card & Copyable Summary**: Rich GitHub Actions Step Summary table with copy-pasteable Markdown snippets for PR/Issue triage.
|
|
12
|
+
- [x] **Parallel Matrix Execution (`--jobs` / `jobs`)**: Concurrent multi-container testing via `ThreadPoolExecutor` with strict matrix order preservation.
|
|
13
|
+
- [x] **Hardened Resource Limits**: Added `--mem-limit` (default: 256m) and `--pids-limit` (default: 128) container controls.
|
|
14
|
+
- [x] **Configurable Network Isolation (`--network none|bridge`)**: Run scripts offline when network access is not required.
|
|
15
|
+
- [x] **Zero-Config Script Auto-Discovery**: Automatically discovers candidate shell scripts in repository root when `script_path` is omitted.
|
|
16
|
+
- [x] **Composite Action Initialization Optimization**: Stripped redundant pip upgrade steps for rapid Action startup.
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Delivered in v0.2.0 - v0.3.0
|
|
21
|
+
|
|
22
|
+
- [x] **Structured Runtime Failure Diagnostics**: Detects "command not found" errors with exit code 127 validation (v0.3.0).
|
|
23
|
+
- [x] **Shebang-aware execution (`--shell shebang | auto`)**: Parses and honors recognized shebang forms (`sh`, `bash`) across distributions using fixed trusted container commands (v0.2.0).
|
|
24
|
+
- [x] **Explicit POSIX mode (`--shell posix`)**: Retains `/bin/sh` baseline across all containers to verify strict POSIX portability (v0.2.0).
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## Planned for Future Releases (v0.5.0+)
|
|
29
|
+
|
|
30
|
+
### 1. Matrix & Distribution Presets
|
|
31
|
+
- [ ] **RPM-based distributions**: Evaluate support for Enterprise Linux baselines (e.g. Rocky Linux 9, AlmaLinux, Fedora).
|
|
32
|
+
- [ ] **Matrix presets**: Predefined profiles (e.g. `--preset minimal`, `--preset enterprise`, `--preset all`).
|
|
33
|
+
|
|
34
|
+
### 2. Performance & Caching
|
|
35
|
+
- [ ] **Docker image pre-pull & caching action**: Optional helper step to leverage GitHub Actions cache for test container base images.
|
|
36
|
+
|
|
37
|
+
### 3. Pre-run Setup Hooks
|
|
38
|
+
- [ ] **Script prerequisites hook**: Declarative environment setup (e.g. install custom apt packages before testing the target script).
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## Suggestions & Feedback
|
|
43
|
+
|
|
44
|
+
To propose an addition or share feedback on priorities, open a [Feature Request](https://github.com/Mresyzz/opsscript-gate/issues/new?template=feature_request.yml) on GitHub.
|