opsscript-gate 0.5.0__tar.gz → 0.6.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.5.0 → opsscript_gate-0.6.0}/CHANGELOG.md +27 -18
- {opsscript_gate-0.5.0 → opsscript_gate-0.6.0}/PKG-INFO +67 -42
- {opsscript_gate-0.5.0 → opsscript_gate-0.6.0}/README.md +65 -40
- {opsscript_gate-0.5.0 → opsscript_gate-0.6.0}/README.zh-CN.md +23 -4
- {opsscript_gate-0.5.0 → opsscript_gate-0.6.0}/action.yml +7 -1
- {opsscript_gate-0.5.0 → opsscript_gate-0.6.0}/docs/configuration.md +17 -2
- opsscript_gate-0.6.0/docs/gpt-oss.md +80 -0
- {opsscript_gate-0.5.0 → opsscript_gate-0.6.0}/examples/alpine-incompatibility/README.md +2 -1
- {opsscript_gate-0.5.0 → opsscript_gate-0.6.0}/examples/github-actions/README.md +2 -2
- {opsscript_gate-0.5.0 → opsscript_gate-0.6.0}/examples/github-actions/workflow.yml +3 -1
- {opsscript_gate-0.5.0 → opsscript_gate-0.6.0}/pyproject.toml +2 -2
- {opsscript_gate-0.5.0 → opsscript_gate-0.6.0}/src/opsscript_gate/__init__.py +1 -1
- {opsscript_gate-0.5.0 → opsscript_gate-0.6.0}/src/opsscript_gate/cli.py +26 -2
- {opsscript_gate-0.5.0 → opsscript_gate-0.6.0}/src/opsscript_gate/config.py +1 -1
- {opsscript_gate-0.5.0 → opsscript_gate-0.6.0}/src/opsscript_gate/discovery.py +64 -0
- {opsscript_gate-0.5.0 → opsscript_gate-0.6.0}/tests/test_action_contract.py +2 -1
- {opsscript_gate-0.5.0 → opsscript_gate-0.6.0}/tests/test_onboarding.py +35 -1
- opsscript_gate-0.5.0/docs/promotion/awesome-lists-pr.md +0 -59
- opsscript_gate-0.5.0/docs/promotion/juejin-zhihu-article.md +0 -144
- opsscript_gate-0.5.0/docs/promotion/reddit-devops.md +0 -56
- opsscript_gate-0.5.0/docs/promotion/show-hn.md +0 -67
- opsscript_gate-0.5.0/docs/promotion/v2ex-post.md +0 -68
- {opsscript_gate-0.5.0 → opsscript_gate-0.6.0}/.gitattributes +0 -0
- {opsscript_gate-0.5.0 → opsscript_gate-0.6.0}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {opsscript_gate-0.5.0 → opsscript_gate-0.6.0}/.github/ISSUE_TEMPLATE/distro_request.yml +0 -0
- {opsscript_gate-0.5.0 → opsscript_gate-0.6.0}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {opsscript_gate-0.5.0 → opsscript_gate-0.6.0}/.github/assets/social-preview.png +0 -0
- {opsscript_gate-0.5.0 → opsscript_gate-0.6.0}/.github/pull_request_template.md +0 -0
- {opsscript_gate-0.5.0 → opsscript_gate-0.6.0}/.github/workflows/demo.yml +0 -0
- {opsscript_gate-0.5.0 → opsscript_gate-0.6.0}/.github/workflows/release.yml +0 -0
- {opsscript_gate-0.5.0 → opsscript_gate-0.6.0}/.github/workflows/test.yml +0 -0
- {opsscript_gate-0.5.0 → opsscript_gate-0.6.0}/.gitignore +0 -0
- {opsscript_gate-0.5.0 → opsscript_gate-0.6.0}/CONTRIBUTING.md +0 -0
- {opsscript_gate-0.5.0 → opsscript_gate-0.6.0}/LICENSE +0 -0
- {opsscript_gate-0.5.0 → opsscript_gate-0.6.0}/ROADMAP.md +0 -0
- {opsscript_gate-0.5.0 → opsscript_gate-0.6.0}/SECURITY.md +0 -0
- {opsscript_gate-0.5.0 → opsscript_gate-0.6.0}/docs/troubleshooting.md +0 -0
- {opsscript_gate-0.5.0 → opsscript_gate-0.6.0}/examples/alpine-incompatibility/apt_dependency.sh +0 -0
- {opsscript_gate-0.5.0 → opsscript_gate-0.6.0}/examples/basic/README.md +0 -0
- {opsscript_gate-0.5.0 → opsscript_gate-0.6.0}/examples/basic/clean_setup.sh +0 -0
- {opsscript_gate-0.5.0 → opsscript_gate-0.6.0}/examples/interactive-hang/README.md +0 -0
- {opsscript_gate-0.5.0 → opsscript_gate-0.6.0}/examples/interactive-hang/prompt_confirm.sh +0 -0
- {opsscript_gate-0.5.0 → opsscript_gate-0.6.0}/src/opsscript_gate/models.py +0 -0
- {opsscript_gate-0.5.0 → opsscript_gate-0.6.0}/src/opsscript_gate/remediation.py +0 -0
- {opsscript_gate-0.5.0 → opsscript_gate-0.6.0}/src/opsscript_gate/reporter.py +0 -0
- {opsscript_gate-0.5.0 → opsscript_gate-0.6.0}/src/opsscript_gate/runner.py +0 -0
- {opsscript_gate-0.5.0 → opsscript_gate-0.6.0}/tests/fixtures/fail_deps.sh +0 -0
- {opsscript_gate-0.5.0 → opsscript_gate-0.6.0}/tests/fixtures/fail_hang.sh +0 -0
- {opsscript_gate-0.5.0 → opsscript_gate-0.6.0}/tests/fixtures/pass_basic.sh +0 -0
- {opsscript_gate-0.5.0 → opsscript_gate-0.6.0}/tests/test_runner.py +0 -0
|
@@ -1,21 +1,30 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.6.0] - 2026-09-30
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
- Added `--changed-since` and the matching Action input to test only shell scripts changed since a Git revision.
|
|
7
|
+
- Changed-script selection uses the existing discovery safety checks and passes when a change contains no shell scripts.
|
|
8
|
+
|
|
9
|
+
## [0.5.1] - 2026-09-30
|
|
10
|
+
|
|
11
|
+
### Changed
|
|
12
|
+
- Published the current README and examples with the v0.5.1 Action tag.
|
|
13
|
+
- Updated package and Action metadata to describe the supported container matrix and runtime compatibility check.
|
|
14
|
+
|
|
3
15
|
## [0.5.0] - 2026-09-24
|
|
4
16
|
|
|
5
17
|
### Added
|
|
6
|
-
- `init
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
-
|
|
10
|
-
- `--output` report artifacts, including failure reports; source/config overwrite protection.
|
|
11
|
-
- Action inputs for configuration, presets, exclusions, preview and saved reports.
|
|
12
|
-
- Chinese quickstart, configuration guide and Ubuntu/Alpine troubleshooting guide.
|
|
18
|
+
- Added `opsscript-gate init` to create a config file and GitHub workflow without replacing existing files.
|
|
19
|
+
- Added `.opsscript-gate.json` with CLI and Action overrides.
|
|
20
|
+
- Added `--dry-run`, `minimal` and `ubuntu` presets, exclusion globs, and `--output` reports.
|
|
21
|
+
- Added configuration, Chinese quickstart, and Ubuntu/Alpine troubleshooting documentation.
|
|
13
22
|
|
|
14
23
|
### Fixed
|
|
15
|
-
- Discovery
|
|
16
|
-
- Discovery skips symlinks and non-files and
|
|
17
|
-
- CLI
|
|
18
|
-
-
|
|
24
|
+
- Discovery stops at the first candidate beyond the configured limit instead of silently ignoring files.
|
|
25
|
+
- Discovery skips symlinks and non-files and checks shebangs without prefix matches.
|
|
26
|
+
- CLI validates limits and network modes before execution.
|
|
27
|
+
- Empty Action inputs no longer override project configuration.
|
|
19
28
|
|
|
20
29
|
### Migration
|
|
21
30
|
- Repositories with more than 20 discovered scripts must exclude unwanted scripts or raise `max_scripts`.
|
|
@@ -31,8 +40,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
31
40
|
## [0.4.1] - 2026-09-19
|
|
32
41
|
|
|
33
42
|
### Fixed & Hardened
|
|
34
|
-
-
|
|
35
|
-
-
|
|
43
|
+
- Bounded container log capture with a 256 KiB rolling buffer and 500-line tail.
|
|
44
|
+
- Neutralized untrusted container logs beginning with `::` before they reach GitHub Actions.
|
|
36
45
|
- **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.
|
|
37
46
|
- **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.
|
|
38
47
|
- **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`).
|
|
@@ -45,15 +54,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
45
54
|
## [0.4.0] - 2026-09-19
|
|
46
55
|
|
|
47
56
|
### Added
|
|
48
|
-
-
|
|
57
|
+
- Line-level GitHub Actions annotations with script paths and line numbers.
|
|
49
58
|
- **Workflow command injection defense**: Strictly escapes parameters (`%`, `\r`, `\n`, `:`, `,`) and message bodies (`%`, `\r`, `\n`) to eliminate command injection from unclassified container logs.
|
|
50
|
-
-
|
|
59
|
+
- Distro-aware remediation hints for common mismatches, including:
|
|
51
60
|
- Alpine package manager mismatches (`apt`/`apt-get` -> `apk`)
|
|
52
61
|
- Debian/Ubuntu package manager mismatches (`apk` -> `apt-get`)
|
|
53
62
|
- Alpine minimal missing Bash (`bash` -> consider POSIX sh or installing bash)
|
|
54
63
|
- Missing network prerequisites (`curl`, `wget`)
|
|
55
64
|
- Missing shebang interpreter paths.
|
|
56
|
-
-
|
|
65
|
+
- Updated the GitHub Actions Step Summary with a compatibility table and a Markdown result block.
|
|
57
66
|
- **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.
|
|
58
67
|
- **Hardened container resource limits**: Added `--mem-limit` (default: 256m) and `--pids-limit` (default: 128) flags and Action inputs to prevent runaway resource exhaustion.
|
|
59
68
|
- **Configurable network isolation (`--network`)**: Supports `--network bridge` (default) and `--network none` for offline script execution.
|
|
@@ -70,7 +79,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
70
79
|
|
|
71
80
|
### Added
|
|
72
81
|
- Structured runtime failure diagnostics: detect common "command not found" failures across Linux distributions (Alpine/BusyBox ash, Debian/Ubuntu dash, Bash, and missing interpreter paths).
|
|
73
|
-
-
|
|
82
|
+
- Missing-command classification requires exit code 127 and matching shell output.
|
|
74
83
|
- Additive `diagnostic` field in JSON report format (`SingleResult.to_dict()`) providing structured diagnostic information (backward-compatible for consumers tolerating additional fields).
|
|
75
84
|
- Enhanced terminal table formatting and GitHub Actions Step Summary showing clear failure causes in the summary overview.
|
|
76
85
|
|
|
@@ -104,7 +113,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
104
113
|
### Added
|
|
105
114
|
- Configured PyPI Trusted Publishing via GitHub Actions OIDC (`pypa/gh-action-pypi-publish`).
|
|
106
115
|
- Added full PyPI package metadata, classifiers, and project URLs to `pyproject.toml`.
|
|
107
|
-
- Ensured
|
|
116
|
+
- Ensured asset URLs in `README.md` render correctly on PyPI.
|
|
108
117
|
|
|
109
118
|
---
|
|
110
119
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: opsscript-gate
|
|
3
|
-
Version: 0.
|
|
4
|
-
Summary: Run Linux shell scripts
|
|
3
|
+
Version: 0.6.0
|
|
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
|
|
@@ -28,9 +28,9 @@ Description-Content-Type: text/markdown
|
|
|
28
28
|
|
|
29
29
|
# OpsScript Gate — shell script compatibility testing
|
|
30
30
|
|
|
31
|
-
[简体中文](README.zh-CN.md) · [Configuration](docs/configuration.md) · [Troubleshooting](docs/troubleshooting.md)
|
|
31
|
+
[简体中文](README.zh-CN.md) · [Configuration](docs/configuration.md) · [Troubleshooting](docs/troubleshooting.md) · [Self-hosted model installer guide](docs/gpt-oss.md)
|
|
32
32
|
|
|
33
|
-
>
|
|
33
|
+
> ShellCheck analyzes shell syntax. OpsScript Gate executes scripts in Linux containers.
|
|
34
34
|
|
|
35
35
|
[](https://github.com/Mresyzz/opsscript-gate/actions/workflows/test.yml)
|
|
36
36
|
[](https://github.com/Mresyzz/opsscript-gate/actions/workflows/demo.yml)
|
|
@@ -41,17 +41,17 @@ Description-Content-Type: text/markdown
|
|
|
41
41
|
[](https://opensource.org/licenses/MIT)
|
|
42
42
|
[](#default-test-matrix)
|
|
43
43
|
|
|
44
|
-
**OpsScript Gate** is a
|
|
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
45
|
|
|
46
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.
|
|
47
47
|
|
|
48
48
|
---
|
|
49
49
|
|
|
50
|
-
##
|
|
50
|
+
## Current release: v0.6.0
|
|
51
51
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
v0.4.1 and earlier do not include them.
|
|
52
|
+
The current release includes a project config file, a dry-run plan, presets, exclusions,
|
|
53
|
+
saved reports, and changed-script selection for pull requests. The project controls
|
|
54
|
+
were introduced in v0.5.0; projects on v0.4.1 and earlier do not include them.
|
|
55
55
|
|
|
56
56
|
```bash
|
|
57
57
|
opsscript-gate init
|
|
@@ -69,11 +69,14 @@ repository files, sibling scripts and project dependencies are **not** mounted.
|
|
|
69
69
|
See [configuration and migration](docs/configuration.md) and
|
|
70
70
|
[why a shell script works on Ubuntu but fails on Alpine](docs/troubleshooting.md).
|
|
71
71
|
|
|
72
|
-
##
|
|
72
|
+
## Quickstart
|
|
73
73
|
|
|
74
|
-
### In GitHub Actions
|
|
74
|
+
### In GitHub Actions
|
|
75
75
|
|
|
76
|
-
|
|
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.
|
|
77
80
|
|
|
78
81
|
```yaml
|
|
79
82
|
name: Shell Compatibility Gate
|
|
@@ -84,15 +87,18 @@ jobs:
|
|
|
84
87
|
runs-on: ubuntu-latest
|
|
85
88
|
steps:
|
|
86
89
|
- uses: actions/checkout@v7
|
|
87
|
-
- uses: Mresyzz/opsscript-gate@v0.
|
|
90
|
+
- uses: Mresyzz/opsscript-gate@v0.6.0
|
|
88
91
|
```
|
|
89
92
|
|
|
90
|
-
|
|
93
|
+
This zero-configuration form discovers shell scripts in the repository. Use
|
|
94
|
+
`opsscript-gate run --dry-run` to inspect the selection, or set `script-path` when the
|
|
95
|
+
repository has a single installer. For self-hosted model installers, see the
|
|
96
|
+
[installer guide](docs/gpt-oss.md).
|
|
91
97
|
|
|
92
98
|
Or test a specific script with custom execution modes:
|
|
93
99
|
|
|
94
100
|
```yaml
|
|
95
|
-
- uses: Mresyzz/opsscript-gate@v0.
|
|
101
|
+
- uses: Mresyzz/opsscript-gate@v0.6.0
|
|
96
102
|
with:
|
|
97
103
|
script-path: scripts/install.sh
|
|
98
104
|
shell: auto
|
|
@@ -114,7 +120,26 @@ opsscript-gate run ./scripts/install.sh
|
|
|
114
120
|
opsscript-gate run
|
|
115
121
|
```
|
|
116
122
|
|
|
117
|
-
###
|
|
123
|
+
### Test only scripts changed in a pull request
|
|
124
|
+
|
|
125
|
+
Fetch the comparison revision and pass the pull request base SHA to avoid running
|
|
126
|
+
unrelated scripts:
|
|
127
|
+
|
|
128
|
+
```yaml
|
|
129
|
+
- uses: actions/checkout@v7
|
|
130
|
+
with:
|
|
131
|
+
fetch-depth: 0
|
|
132
|
+
- uses: Mresyzz/opsscript-gate@v0.6.0
|
|
133
|
+
with:
|
|
134
|
+
changed-since: ${{ github.event.pull_request.base.sha }}
|
|
135
|
+
preset: minimal
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
If the change does not include a shell script, the check passes without starting a
|
|
139
|
+
container. The same selection can be previewed locally with
|
|
140
|
+
`opsscript-gate run --changed-since origin/main --dry-run`.
|
|
141
|
+
|
|
142
|
+
### Example: package-manager mismatch
|
|
118
143
|
|
|
119
144
|
Create `install.sh`:
|
|
120
145
|
|
|
@@ -141,23 +166,23 @@ Alpine 3.20 FAIL
|
|
|
141
166
|
apt-get: not found
|
|
142
167
|
```
|
|
143
168
|
|
|
144
|
-
The script is valid shell, but
|
|
169
|
+
The script is valid shell, but it assumes a command that is not present in Alpine.
|
|
145
170
|
|
|
146
171
|
---
|
|
147
172
|
|
|
148
|
-
##
|
|
173
|
+
## CI output
|
|
149
174
|
|
|
150
|
-
|
|
175
|
+
The action reports failures in two places:
|
|
151
176
|
|
|
152
|
-
###
|
|
153
|
-
|
|
177
|
+
### GitHub annotations
|
|
178
|
+
Failures include the script path, line number, distribution, and a short diagnostic:
|
|
154
179
|
|
|
155
180
|
```text
|
|
156
181
|
::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.
|
|
157
182
|
```
|
|
158
183
|
|
|
159
|
-
###
|
|
160
|
-
|
|
184
|
+
### Step summary
|
|
185
|
+
The action also writes a markdown matrix to `$GITHUB_STEP_SUMMARY`:
|
|
161
186
|
|
|
162
187
|
```markdown
|
|
163
188
|
## 🛡️ OpsScript Gate Compatibility Report
|
|
@@ -176,14 +201,14 @@ A beautifully formatted markdown summary is automatically posted to `$GITHUB_STE
|
|
|
176
201
|
| `alpine:3.20` | ❌ FAIL | `127` | `0.19s` | ⚠️ Missing command: `apt-get` (line 4)<br>💡 *Alpine normally uses apk instead of apt-get.* |
|
|
177
202
|
|
|
178
203
|
<details>
|
|
179
|
-
<summary
|
|
204
|
+
<summary><b>Markdown result</b></summary>
|
|
180
205
|
...
|
|
181
206
|
</details>
|
|
182
207
|
```
|
|
183
208
|
|
|
184
209
|
---
|
|
185
210
|
|
|
186
|
-
##
|
|
211
|
+
## Example: runtime behavior that static analysis misses
|
|
187
212
|
|
|
188
213
|
Consider this clean deployment script:
|
|
189
214
|
|
|
@@ -220,37 +245,38 @@ Failed Distributions - Output Snippets (last 15 lines):
|
|
|
220
245
|
sh: line 4: apt-get: not found
|
|
221
246
|
```
|
|
222
247
|
|
|
223
|
-
**Why it failed:** Alpine
|
|
248
|
+
**Why it failed:** Alpine uses `apk`, not `apt-get`. The report includes the missing command and its line number.
|
|
224
249
|
|
|
225
250
|
---
|
|
226
251
|
|
|
227
|
-
##
|
|
252
|
+
## Scope compared with other checks
|
|
228
253
|
|
|
229
|
-
### OpsScript Gate
|
|
254
|
+
### OpsScript Gate compared with ShellCheck and a custom CI matrix
|
|
230
255
|
|
|
231
256
|
| Capability | OpsScript Gate | ShellCheck | Handwritten CI Matrix |
|
|
232
257
|
| :--- | :---: | :---: | :---: |
|
|
233
258
|
| **Runtime execution** | **Yes** | No (Static AST only) | Yes |
|
|
234
259
|
| **Real distro environments** | **Yes (Debian, Ubuntu, Alpine)** | No | Yes |
|
|
235
260
|
| **Preconfigured defaults** | **Yes** | Yes | Requires custom workflow configuration |
|
|
236
|
-
| **
|
|
261
|
+
| **Restricted container defaults** | **Built-in (`ro`, `cap_drop`, resource limits)** | N/A | User-defined |
|
|
237
262
|
| **Anti-hang stdin protection** | **Built-in (`</dev/null`, noninteractive)** | No | User-defined |
|
|
238
|
-
| **Line-Level Annotations & Hints** | **Built-in
|
|
263
|
+
| **Line-Level Annotations & Hints** | **Built-in** | Static warnings | User-defined |
|
|
239
264
|
| **Parallel Matrix Execution** | **Built-in (`--jobs`)** | N/A | Manual matrix config |
|
|
240
265
|
|
|
241
|
-
|
|
242
|
-
|
|
266
|
+
ShellCheck checks shell syntax and common mistakes. OpsScript Gate runs the script in
|
|
267
|
+
real distributions. A custom CI matrix can do the same job, but each repository must
|
|
268
|
+
maintain its own images, mounts, timeouts, and report handling.
|
|
243
269
|
|
|
244
270
|
---
|
|
245
271
|
|
|
246
|
-
##
|
|
272
|
+
## Security boundaries and container isolation
|
|
247
273
|
|
|
248
274
|
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.
|
|
249
275
|
|
|
250
276
|
<details>
|
|
251
277
|
<summary><strong>View security boundaries and runtime hardening details</strong></summary>
|
|
252
278
|
|
|
253
|
-
|
|
279
|
+
The runner uses restricted container defaults:
|
|
254
280
|
|
|
255
281
|
1. **Restricted Container Defaults**:
|
|
256
282
|
- Containers run with `privileged=False`.
|
|
@@ -300,7 +326,7 @@ Use it when you want to know whether a shell script actually runs across the sup
|
|
|
300
326
|
|
|
301
327
|
---
|
|
302
328
|
|
|
303
|
-
##
|
|
329
|
+
## Default test matrix
|
|
304
330
|
|
|
305
331
|
| Image | Distribution | Focus |
|
|
306
332
|
| :--- | :--- | :--- |
|
|
@@ -313,7 +339,7 @@ Customize the matrix at any time via `--matrix` or Action input `matrix`.
|
|
|
313
339
|
|
|
314
340
|
---
|
|
315
341
|
|
|
316
|
-
##
|
|
342
|
+
## CLI reference
|
|
317
343
|
|
|
318
344
|
```text
|
|
319
345
|
usage: opsscript-gate run [-h] [--matrix MATRIX] [-j JOBS] [--timeout TIMEOUT]
|
|
@@ -335,6 +361,7 @@ usage: opsscript-gate run [-h] [--matrix MATRIX] [-j JOBS] [--timeout TIMEOUT]
|
|
|
335
361
|
| `--mem-limit` | String | `256m` | Memory limit per container (e.g. `256m`, `512m`) |
|
|
336
362
|
| `--pids-limit`| Integer | `128` | Maximum number of processes per container |
|
|
337
363
|
| `--network` | Choice | `bridge` | Container network mode: `bridge` or `none` |
|
|
364
|
+
| `--changed-since` | Git revision | - | Test shell scripts changed between this revision and `HEAD` |
|
|
338
365
|
| `--version` | Flag | - | Show version number |
|
|
339
366
|
| `-h, --help` | Flag | - | Show argument help |
|
|
340
367
|
|
|
@@ -366,9 +393,9 @@ usage: opsscript-gate run [-h] [--matrix MATRIX] [-j JOBS] [--timeout TIMEOUT]
|
|
|
366
393
|
Explicit CLI options override project settings. Explicit script paths bypass discovery
|
|
367
394
|
and its exclusions. See [complete configuration semantics](docs/configuration.md).
|
|
368
395
|
|
|
369
|
-
##
|
|
396
|
+
## Downstream example
|
|
370
397
|
|
|
371
|
-
|
|
398
|
+
[`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.
|
|
372
399
|
|
|
373
400
|
See the downstream workflow: [`.github/workflows/test.yml`](https://github.com/Mresyzz/linux-dev-bootstrap/blob/main/.github/workflows/test.yml).
|
|
374
401
|
|
|
@@ -393,11 +420,9 @@ pytest -v
|
|
|
393
420
|
|
|
394
421
|
---
|
|
395
422
|
|
|
396
|
-
##
|
|
397
|
-
|
|
398
|
-
If OpsScript Gate catches a compatibility problem in one of your scripts, consider starring the repository so other shell and DevOps maintainers can find it too.
|
|
423
|
+
## Feedback
|
|
399
424
|
|
|
400
|
-
|
|
425
|
+
Please report compatibility cases, bugs, and pull requests in the issue tracker.
|
|
401
426
|
|
|
402
427
|
---
|
|
403
428
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# OpsScript Gate — shell script compatibility testing
|
|
2
2
|
|
|
3
|
-
[简体中文](README.zh-CN.md) · [Configuration](docs/configuration.md) · [Troubleshooting](docs/troubleshooting.md)
|
|
3
|
+
[简体中文](README.zh-CN.md) · [Configuration](docs/configuration.md) · [Troubleshooting](docs/troubleshooting.md) · [Self-hosted model installer guide](docs/gpt-oss.md)
|
|
4
4
|
|
|
5
|
-
>
|
|
5
|
+
> ShellCheck analyzes shell syntax. OpsScript Gate executes scripts in Linux containers.
|
|
6
6
|
|
|
7
7
|
[](https://github.com/Mresyzz/opsscript-gate/actions/workflows/test.yml)
|
|
8
8
|
[](https://github.com/Mresyzz/opsscript-gate/actions/workflows/demo.yml)
|
|
@@ -13,17 +13,17 @@
|
|
|
13
13
|
[](https://opensource.org/licenses/MIT)
|
|
14
14
|
[](#default-test-matrix)
|
|
15
15
|
|
|
16
|
-
**OpsScript Gate** is a
|
|
16
|
+
**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.
|
|
17
17
|
|
|
18
18
|
It is designed for shell testing, portable shell validation, Bash/POSIX compatibility checks, and cross-distro CI where syntax-only tooling is not enough.
|
|
19
19
|
|
|
20
20
|
---
|
|
21
21
|
|
|
22
|
-
##
|
|
22
|
+
## Current release: v0.6.0
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
v0.4.1 and earlier do not include them.
|
|
24
|
+
The current release includes a project config file, a dry-run plan, presets, exclusions,
|
|
25
|
+
saved reports, and changed-script selection for pull requests. The project controls
|
|
26
|
+
were introduced in v0.5.0; projects on v0.4.1 and earlier do not include them.
|
|
27
27
|
|
|
28
28
|
```bash
|
|
29
29
|
opsscript-gate init
|
|
@@ -41,11 +41,14 @@ repository files, sibling scripts and project dependencies are **not** mounted.
|
|
|
41
41
|
See [configuration and migration](docs/configuration.md) and
|
|
42
42
|
[why a shell script works on Ubuntu but fails on Alpine](docs/troubleshooting.md).
|
|
43
43
|
|
|
44
|
-
##
|
|
44
|
+
## Quickstart
|
|
45
45
|
|
|
46
|
-
### In GitHub Actions
|
|
46
|
+
### In GitHub Actions
|
|
47
47
|
|
|
48
|
-
|
|
48
|
+
Add this workflow to `.github/workflows/shell-compat.yml`:
|
|
49
|
+
|
|
50
|
+
You can copy the maintained example from [`examples/github-actions/workflow.yml`](examples/github-actions/workflow.yml)
|
|
51
|
+
and change the `script-path`, or use the minimal workflow below.
|
|
49
52
|
|
|
50
53
|
```yaml
|
|
51
54
|
name: Shell Compatibility Gate
|
|
@@ -56,15 +59,18 @@ jobs:
|
|
|
56
59
|
runs-on: ubuntu-latest
|
|
57
60
|
steps:
|
|
58
61
|
- uses: actions/checkout@v7
|
|
59
|
-
- uses: Mresyzz/opsscript-gate@v0.
|
|
62
|
+
- uses: Mresyzz/opsscript-gate@v0.6.0
|
|
60
63
|
```
|
|
61
64
|
|
|
62
|
-
|
|
65
|
+
This zero-configuration form discovers shell scripts in the repository. Use
|
|
66
|
+
`opsscript-gate run --dry-run` to inspect the selection, or set `script-path` when the
|
|
67
|
+
repository has a single installer. For self-hosted model installers, see the
|
|
68
|
+
[installer guide](docs/gpt-oss.md).
|
|
63
69
|
|
|
64
70
|
Or test a specific script with custom execution modes:
|
|
65
71
|
|
|
66
72
|
```yaml
|
|
67
|
-
- uses: Mresyzz/opsscript-gate@v0.
|
|
73
|
+
- uses: Mresyzz/opsscript-gate@v0.6.0
|
|
68
74
|
with:
|
|
69
75
|
script-path: scripts/install.sh
|
|
70
76
|
shell: auto
|
|
@@ -86,7 +92,26 @@ opsscript-gate run ./scripts/install.sh
|
|
|
86
92
|
opsscript-gate run
|
|
87
93
|
```
|
|
88
94
|
|
|
89
|
-
###
|
|
95
|
+
### Test only scripts changed in a pull request
|
|
96
|
+
|
|
97
|
+
Fetch the comparison revision and pass the pull request base SHA to avoid running
|
|
98
|
+
unrelated scripts:
|
|
99
|
+
|
|
100
|
+
```yaml
|
|
101
|
+
- uses: actions/checkout@v7
|
|
102
|
+
with:
|
|
103
|
+
fetch-depth: 0
|
|
104
|
+
- uses: Mresyzz/opsscript-gate@v0.6.0
|
|
105
|
+
with:
|
|
106
|
+
changed-since: ${{ github.event.pull_request.base.sha }}
|
|
107
|
+
preset: minimal
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
If the change does not include a shell script, the check passes without starting a
|
|
111
|
+
container. The same selection can be previewed locally with
|
|
112
|
+
`opsscript-gate run --changed-since origin/main --dry-run`.
|
|
113
|
+
|
|
114
|
+
### Example: package-manager mismatch
|
|
90
115
|
|
|
91
116
|
Create `install.sh`:
|
|
92
117
|
|
|
@@ -113,23 +138,23 @@ Alpine 3.20 FAIL
|
|
|
113
138
|
apt-get: not found
|
|
114
139
|
```
|
|
115
140
|
|
|
116
|
-
The script is valid shell, but
|
|
141
|
+
The script is valid shell, but it assumes a command that is not present in Alpine.
|
|
117
142
|
|
|
118
143
|
---
|
|
119
144
|
|
|
120
|
-
##
|
|
145
|
+
## CI output
|
|
121
146
|
|
|
122
|
-
|
|
147
|
+
The action reports failures in two places:
|
|
123
148
|
|
|
124
|
-
###
|
|
125
|
-
|
|
149
|
+
### GitHub annotations
|
|
150
|
+
Failures include the script path, line number, distribution, and a short diagnostic:
|
|
126
151
|
|
|
127
152
|
```text
|
|
128
153
|
::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.
|
|
129
154
|
```
|
|
130
155
|
|
|
131
|
-
###
|
|
132
|
-
|
|
156
|
+
### Step summary
|
|
157
|
+
The action also writes a markdown matrix to `$GITHUB_STEP_SUMMARY`:
|
|
133
158
|
|
|
134
159
|
```markdown
|
|
135
160
|
## 🛡️ OpsScript Gate Compatibility Report
|
|
@@ -148,14 +173,14 @@ A beautifully formatted markdown summary is automatically posted to `$GITHUB_STE
|
|
|
148
173
|
| `alpine:3.20` | ❌ FAIL | `127` | `0.19s` | ⚠️ Missing command: `apt-get` (line 4)<br>💡 *Alpine normally uses apk instead of apt-get.* |
|
|
149
174
|
|
|
150
175
|
<details>
|
|
151
|
-
<summary
|
|
176
|
+
<summary><b>Markdown result</b></summary>
|
|
152
177
|
...
|
|
153
178
|
</details>
|
|
154
179
|
```
|
|
155
180
|
|
|
156
181
|
---
|
|
157
182
|
|
|
158
|
-
##
|
|
183
|
+
## Example: runtime behavior that static analysis misses
|
|
159
184
|
|
|
160
185
|
Consider this clean deployment script:
|
|
161
186
|
|
|
@@ -192,37 +217,38 @@ Failed Distributions - Output Snippets (last 15 lines):
|
|
|
192
217
|
sh: line 4: apt-get: not found
|
|
193
218
|
```
|
|
194
219
|
|
|
195
|
-
**Why it failed:** Alpine
|
|
220
|
+
**Why it failed:** Alpine uses `apk`, not `apt-get`. The report includes the missing command and its line number.
|
|
196
221
|
|
|
197
222
|
---
|
|
198
223
|
|
|
199
|
-
##
|
|
224
|
+
## Scope compared with other checks
|
|
200
225
|
|
|
201
|
-
### OpsScript Gate
|
|
226
|
+
### OpsScript Gate compared with ShellCheck and a custom CI matrix
|
|
202
227
|
|
|
203
228
|
| Capability | OpsScript Gate | ShellCheck | Handwritten CI Matrix |
|
|
204
229
|
| :--- | :---: | :---: | :---: |
|
|
205
230
|
| **Runtime execution** | **Yes** | No (Static AST only) | Yes |
|
|
206
231
|
| **Real distro environments** | **Yes (Debian, Ubuntu, Alpine)** | No | Yes |
|
|
207
232
|
| **Preconfigured defaults** | **Yes** | Yes | Requires custom workflow configuration |
|
|
208
|
-
| **
|
|
233
|
+
| **Restricted container defaults** | **Built-in (`ro`, `cap_drop`, resource limits)** | N/A | User-defined |
|
|
209
234
|
| **Anti-hang stdin protection** | **Built-in (`</dev/null`, noninteractive)** | No | User-defined |
|
|
210
|
-
| **Line-Level Annotations & Hints** | **Built-in
|
|
235
|
+
| **Line-Level Annotations & Hints** | **Built-in** | Static warnings | User-defined |
|
|
211
236
|
| **Parallel Matrix Execution** | **Built-in (`--jobs`)** | N/A | Manual matrix config |
|
|
212
237
|
|
|
213
|
-
|
|
214
|
-
|
|
238
|
+
ShellCheck checks shell syntax and common mistakes. OpsScript Gate runs the script in
|
|
239
|
+
real distributions. A custom CI matrix can do the same job, but each repository must
|
|
240
|
+
maintain its own images, mounts, timeouts, and report handling.
|
|
215
241
|
|
|
216
242
|
---
|
|
217
243
|
|
|
218
|
-
##
|
|
244
|
+
## Security boundaries and container isolation
|
|
219
245
|
|
|
220
246
|
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.
|
|
221
247
|
|
|
222
248
|
<details>
|
|
223
249
|
<summary><strong>View security boundaries and runtime hardening details</strong></summary>
|
|
224
250
|
|
|
225
|
-
|
|
251
|
+
The runner uses restricted container defaults:
|
|
226
252
|
|
|
227
253
|
1. **Restricted Container Defaults**:
|
|
228
254
|
- Containers run with `privileged=False`.
|
|
@@ -272,7 +298,7 @@ Use it when you want to know whether a shell script actually runs across the sup
|
|
|
272
298
|
|
|
273
299
|
---
|
|
274
300
|
|
|
275
|
-
##
|
|
301
|
+
## Default test matrix
|
|
276
302
|
|
|
277
303
|
| Image | Distribution | Focus |
|
|
278
304
|
| :--- | :--- | :--- |
|
|
@@ -285,7 +311,7 @@ Customize the matrix at any time via `--matrix` or Action input `matrix`.
|
|
|
285
311
|
|
|
286
312
|
---
|
|
287
313
|
|
|
288
|
-
##
|
|
314
|
+
## CLI reference
|
|
289
315
|
|
|
290
316
|
```text
|
|
291
317
|
usage: opsscript-gate run [-h] [--matrix MATRIX] [-j JOBS] [--timeout TIMEOUT]
|
|
@@ -307,6 +333,7 @@ usage: opsscript-gate run [-h] [--matrix MATRIX] [-j JOBS] [--timeout TIMEOUT]
|
|
|
307
333
|
| `--mem-limit` | String | `256m` | Memory limit per container (e.g. `256m`, `512m`) |
|
|
308
334
|
| `--pids-limit`| Integer | `128` | Maximum number of processes per container |
|
|
309
335
|
| `--network` | Choice | `bridge` | Container network mode: `bridge` or `none` |
|
|
336
|
+
| `--changed-since` | Git revision | - | Test shell scripts changed between this revision and `HEAD` |
|
|
310
337
|
| `--version` | Flag | - | Show version number |
|
|
311
338
|
| `-h, --help` | Flag | - | Show argument help |
|
|
312
339
|
|
|
@@ -338,9 +365,9 @@ usage: opsscript-gate run [-h] [--matrix MATRIX] [-j JOBS] [--timeout TIMEOUT]
|
|
|
338
365
|
Explicit CLI options override project settings. Explicit script paths bypass discovery
|
|
339
366
|
and its exclusions. See [complete configuration semantics](docs/configuration.md).
|
|
340
367
|
|
|
341
|
-
##
|
|
368
|
+
## Downstream example
|
|
342
369
|
|
|
343
|
-
|
|
370
|
+
[`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.
|
|
344
371
|
|
|
345
372
|
See the downstream workflow: [`.github/workflows/test.yml`](https://github.com/Mresyzz/linux-dev-bootstrap/blob/main/.github/workflows/test.yml).
|
|
346
373
|
|
|
@@ -365,11 +392,9 @@ pytest -v
|
|
|
365
392
|
|
|
366
393
|
---
|
|
367
394
|
|
|
368
|
-
##
|
|
369
|
-
|
|
370
|
-
If OpsScript Gate catches a compatibility problem in one of your scripts, consider starring the repository so other shell and DevOps maintainers can find it too.
|
|
395
|
+
## Feedback
|
|
371
396
|
|
|
372
|
-
|
|
397
|
+
Please report compatibility cases, bugs, and pull requests in the issue tracker.
|
|
373
398
|
|
|
374
399
|
---
|
|
375
400
|
|