opsscript-gate 0.8.2__tar.gz → 0.9.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/.github/workflow-templates/opsscript-gate.properties.json +1 -1
  2. {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/.github/workflow-templates/opsscript-gate.yml +1 -1
  3. opsscript_gate-0.9.0/.github/workflows/deploy-pages.yml +34 -0
  4. {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/CHANGELOG.md +16 -0
  5. {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/CITATION.cff +1 -1
  6. opsscript_gate-0.8.2/README.md → opsscript_gate-0.9.0/PKG-INFO +94 -19
  7. opsscript_gate-0.8.2/PKG-INFO → opsscript_gate-0.9.0/README.md +63 -49
  8. {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/README.zh-CN.md +16 -7
  9. {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/ROADMAP.md +9 -0
  10. {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/action.yml +7 -1
  11. opsscript_gate-0.9.0/demo.html +980 -0
  12. opsscript_gate-0.9.0/docs/command-not-found.html +122 -0
  13. opsscript_gate-0.9.0/docs/command-not-found.md +119 -0
  14. {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/docs/configuration.md +8 -3
  15. {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/docs/gpt-oss.md +1 -1
  16. opsscript_gate-0.9.0/docs/index.html +988 -0
  17. opsscript_gate-0.9.0/docs/llms.txt +26 -0
  18. opsscript_gate-0.9.0/docs/sitemap.xml +5 -0
  19. {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/examples/github-actions/README.md +1 -1
  20. {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/examples/github-actions/workflow.yml +1 -1
  21. opsscript_gate-0.9.0/index.html +988 -0
  22. opsscript_gate-0.9.0/llms.txt +26 -0
  23. {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/pyproject.toml +12 -4
  24. {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/src/opsscript_gate/__init__.py +1 -1
  25. {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/src/opsscript_gate/cli.py +38 -37
  26. {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/src/opsscript_gate/config.py +9 -2
  27. {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/src/opsscript_gate/models.py +20 -1
  28. {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/src/opsscript_gate/reporter.py +12 -1
  29. {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/src/opsscript_gate/runner.py +75 -26
  30. {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/tests/test_action_contract.py +2 -2
  31. {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/tests/test_onboarding.py +14 -1
  32. {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/tests/test_runner.py +60 -1
  33. {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/.gitattributes +0 -0
  34. {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  35. {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/.github/ISSUE_TEMPLATE/distro_request.yml +0 -0
  36. {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  37. {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/.github/assets/social-preview.png +0 -0
  38. {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/.github/pull_request_template.md +0 -0
  39. {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/.github/workflows/demo.yml +0 -0
  40. {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/.github/workflows/release.yml +0 -0
  41. {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/.github/workflows/test.yml +0 -0
  42. {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/.gitignore +0 -0
  43. {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/CONTRIBUTING.md +0 -0
  44. {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/LICENSE +0 -0
  45. {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/SECURITY.md +0 -0
  46. {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/docs/troubleshooting.md +0 -0
  47. {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/examples/alpine-incompatibility/README.md +0 -0
  48. {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/examples/alpine-incompatibility/apt_dependency.sh +0 -0
  49. {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/examples/basic/README.md +0 -0
  50. {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/examples/basic/clean_setup.sh +0 -0
  51. {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/examples/interactive-hang/README.md +0 -0
  52. {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/examples/interactive-hang/prompt_confirm.sh +0 -0
  53. {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/src/opsscript_gate/discovery.py +0 -0
  54. {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/src/opsscript_gate/remediation.py +0 -0
  55. {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/tests/fixtures/fail_deps.sh +0 -0
  56. {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/tests/fixtures/fail_hang.sh +0 -0
  57. {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/tests/fixtures/pass_basic.sh +0 -0
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "OpsScript Gate shell compatibility",
3
- "description": "Run shell scripts in Debian, Ubuntu and Alpine containers on changes to shell files.",
3
+ "description": "Run shell scripts in Debian, Ubuntu and Alpine containers to catch command not found and runtime compatibility failures.",
4
4
  "iconName": "octicon-shield-check",
5
5
  "categories": ["Continuous integration", "Testing"],
6
6
  "filePatterns": [".*\\.sh$", ".*\\.bash$"]
@@ -25,7 +25,7 @@ jobs:
25
25
  persist-credentials: false
26
26
 
27
27
  - name: Run OpsScript Gate
28
- uses: Mresyzz/opsscript-gate@v0.8.0
28
+ uses: Mresyzz/opsscript-gate@v0.8.3
29
29
  with:
30
30
  shell: auto
31
31
  network: none
@@ -0,0 +1,34 @@
1
+ name: Deploy GitHub Pages
2
+
3
+ on:
4
+ push:
5
+ branches: ["main"]
6
+ workflow_dispatch:
7
+
8
+ permissions:
9
+ contents: read
10
+ pages: write
11
+ id-token: write
12
+
13
+ concurrency:
14
+ group: "pages"
15
+ cancel-in-progress: false
16
+
17
+ jobs:
18
+ deploy:
19
+ environment:
20
+ name: github-pages
21
+ url: ${{ steps.deployment.outputs.page_url }}
22
+ runs-on: ubuntu-latest
23
+ steps:
24
+ - name: Checkout
25
+ uses: actions/checkout@v4
26
+ - name: Setup Pages
27
+ uses: actions/configure-pages@v5
28
+ - name: Upload artifact
29
+ uses: actions/upload-pages-artifact@v3
30
+ with:
31
+ path: 'docs'
32
+ - name: Deploy to GitHub Pages
33
+ id: deployment
34
+ uses: actions/deploy-pages@v4
@@ -1,5 +1,21 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.9.0] - 2026-10-03
4
+
5
+ ### Added
6
+ - Added `--repeat` and Action/config `repeat` support to detect flaky runtime behavior per distribution.
7
+ - Added attempt counts and `FLAKY` status to JSON, Markdown, SARIF, terminal, and GitHub Step Summary reports.
8
+
9
+ ### Fixed
10
+ - Bounded project configuration reads to prevent oversized configuration files from consuming unbounded memory.
11
+ - Prefer Docker's blocking wait API over repeated synchronous container reloads, while retaining a bounded compatibility fallback.
12
+ - Removed duplicated CLI execution error handling and the unused `asdict` import.
13
+
14
+ ## [0.8.3] - 2026-10-02
15
+
16
+ - Corrected the PyPI homepage and demo links to point to the OpsScript Gate Pages site.
17
+ - Refreshed all generated examples and release metadata to v0.8.3.
18
+
3
19
  ## [0.8.2] - 2026-10-02
4
20
 
5
21
  ### Fixed
@@ -5,7 +5,7 @@ type: software
5
5
  authors:
6
6
  - family-names: Mresyzz
7
7
  given-names: Mresy
8
- version: 0.8.2
8
+ version: 0.9.0
9
9
  date-released: 2026-10-02
10
10
  repository-code: https://github.com/Mresyzz/opsscript-gate
11
11
  url: https://github.com/Mresyzz/opsscript-gate
@@ -1,8 +1,39 @@
1
- # OpsScript Gate — shell script compatibility testing
2
-
3
- [简体中文](README.zh-CN.md) · [Configuration](docs/configuration.md) · [Troubleshooting](docs/troubleshooting.md) · [Self-hosted model installer guide](docs/gpt-oss.md)
4
-
5
- > ShellCheck analyzes shell syntax. OpsScript Gate executes scripts in Linux containers.
1
+ Metadata-Version: 2.5
2
+ Name: opsscript-gate
3
+ Version: 0.9.0
4
+ Summary: Cross-distro shell script compatibility checker for runtime testing in Debian, Ubuntu and Alpine
5
+ Project-URL: Homepage, https://mresyzz.github.io/opsscript-gate/
6
+ Project-URL: Demo, https://mresyzz.github.io/opsscript-gate/
7
+ Project-URL: Repository, https://github.com/Mresyzz/opsscript-gate
8
+ Project-URL: Issues, https://github.com/Mresyzz/opsscript-gate/issues
9
+ Project-URL: Changelog, https://github.com/Mresyzz/opsscript-gate/blob/main/CHANGELOG.md
10
+ Project-URL: Documentation, https://github.com/Mresyzz/opsscript-gate/tree/main/docs
11
+ Project-URL: Troubleshooting, https://github.com/Mresyzz/opsscript-gate/blob/main/docs/command-not-found.md
12
+ Author: Mresyzz
13
+ License: MIT
14
+ License-File: LICENSE
15
+ Keywords: alpine,apk,apt-get,bashisms,bootstrap,busybox,ci,command-not-found,compatibility,cross-distro,debian,devops,docker,github-actions,installer,installer-testing,linux,portable-shell,posix,runtime-compatibility,shell,shell-portability,shell-script-testing,shellcheck,shellcheck-alternative,testing,ubuntu
16
+ Classifier: Development Status :: 4 - Beta
17
+ Classifier: Intended Audience :: Developers
18
+ Classifier: Intended Audience :: System Administrators
19
+ Classifier: License :: OSI Approved :: MIT License
20
+ Classifier: Programming Language :: Python :: 3
21
+ Classifier: Programming Language :: Python :: 3.10
22
+ Classifier: Programming Language :: Python :: 3.11
23
+ Classifier: Programming Language :: Python :: 3.12
24
+ Classifier: Topic :: Software Development :: Testing
25
+ Classifier: Topic :: System :: Systems Administration
26
+ Requires-Python: >=3.10
27
+ Requires-Dist: docker>=7.0.0
28
+ Provides-Extra: test
29
+ Requires-Dist: pytest>=8.0.0; extra == 'test'
30
+ Description-Content-Type: text/markdown
31
+
32
+ # OpsScript Gate — cross-distro shell script runtime compatibility checker
33
+
34
+ [Live demo](https://mresyzz.github.io/opsscript-gate/) · [简体中文](README.zh-CN.md) · [Configuration](docs/configuration.md) · [Troubleshooting](docs/troubleshooting.md) · [Self-hosted model installer guide](docs/gpt-oss.md)
35
+
36
+ > **OpsScript Gate is a cross-distro shell script runtime compatibility checker.** The GitHub Action and Python CLI test shell installers in real Debian, Ubuntu, and Alpine containers and diagnose failures such as `command not found`. Use it alongside ShellCheck to check both source code and runtime behavior.
6
37
 
7
38
  [![CI](https://github.com/Mresyzz/opsscript-gate/actions/workflows/test.yml/badge.svg)](https://github.com/Mresyzz/opsscript-gate/actions/workflows/test.yml)
8
39
  [![Demo](https://github.com/Mresyzz/opsscript-gate/actions/workflows/demo.yml/badge.svg)](https://github.com/Mresyzz/opsscript-gate/actions/workflows/demo.yml)
@@ -13,23 +44,55 @@
13
44
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
14
45
  [![Supported Distros](https://img.shields.io/badge/matrix-Debian%20%7C%20Ubuntu%20%7C%20Alpine-orange.svg)](#default-test-matrix)
15
46
 
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.
47
+ **OpsScript Gate** is a cross-distro shell script runtime compatibility checker for Linux. It executes scripts inside unprivileged Debian, Ubuntu, and Alpine containers, catching environment-specific failures, missing interpreters, package-manager assumptions, and exit code 127 errors that static analysis cannot detect.
17
48
 
18
49
  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
50
 
20
- If your repository contains an installer, bootstrap script, or shell entrypoint, the fastest path is to
21
- open the [InstallReady scanner](https://mresyzz.github.io/InstallReady/), enter `owner/repository`, and
22
- choose **Add workflow on GitHub**. It generates a reviewable workflow without an account, API key, or
23
- service signup. You can also copy the maintained [zero-configuration workflow](.github/workflow-templates/opsscript-gate.yml).
51
+ If you arrived here from an error or a search, these are the problems this project answers:
52
+
53
+ - `command not found` when a shell script runs in Docker or GitHub Actions
54
+ - `apt-get: not found` on Alpine, or `apk: not found` on Debian/Ubuntu
55
+ - a shell installer that passes ShellCheck but fails at runtime
56
+ - a shell script compatibility checker that tests runtime commands, not only syntax
57
+ - cross-distro shell testing for installers, bootstrap scripts, and entrypoints
58
+ - testing one shell script across real Debian, Ubuntu, and Alpine containers
59
+ - replacing a hand-written cross-distribution CI matrix with one reusable action
60
+
61
+ Start with the problem-first guide: [debug `command not found` across Debian, Ubuntu, and Alpine](docs/command-not-found.md). It includes a failing script, the diagnosis, a copyable workflow, and the local CLI equivalent.
62
+
63
+ If your repository contains an installer, bootstrap script, or shell entrypoint, start with the
64
+ [interactive demo](https://mresyzz.github.io/opsscript-gate/), then copy the maintained
65
+ [zero-configuration workflow](.github/workflow-templates/opsscript-gate.yml). The demo explains the
66
+ ShellCheck-versus-runtime gap and the workflow is ready to review in your own repository.
24
67
 
25
- Try the browser scanner: [InstallReady](https://mresyzz.github.io/InstallReady/?repo=Mresyzz%2Fopsscript-gate) checks this repository without executing code or requiring a login.
68
+ ### The 15-second proof
69
+
70
+ This script is valid POSIX shell and can pass a syntax linter, but it fails on Alpine because
71
+ `apt-get` is not installed there:
72
+
73
+ ```sh
74
+ #!/bin/sh
75
+ set -eu
76
+ apt-get --version
77
+ ```
78
+
79
+ Run it locally with `opsscript-gate run ./install.sh`, or add the following step to CI:
80
+
81
+ ```yaml
82
+ - uses: Mresyzz/opsscript-gate@v0.9.0
83
+ with:
84
+ script-path: install.sh
85
+ ```
86
+
87
+ The result identifies the failing distribution, exit code, line, missing command, and the usual remediation (`apk` on Alpine). See the [full `command not found` guide](docs/command-not-found.md) for Bash, `curl`, `jq`, and noninteractive prompt cases.
26
88
 
27
89
  ---
28
90
 
29
- ## Current release: v0.8.2
91
+ ## Current release: v0.9.0
30
92
 
31
93
  The current release includes a project config file, a dry-run plan, presets, exclusions,
32
- saved reports, and changed-script selection for pull requests. The project controls
94
+ saved reports, changed-script selection for pull requests, and repeat runs for detecting
95
+ flaky runtime behavior. The project controls
33
96
  were introduced in v0.5.0; projects on v0.4.1 and earlier do not include them.
34
97
 
35
98
  ```bash
@@ -37,6 +100,8 @@ opsscript-gate init
37
100
  opsscript-gate doctor
38
101
  opsscript-gate run --dry-run
39
102
  opsscript-gate run --format json --output reports/compatibility.json
103
+ # Repeat each distro three times when diagnosing intermittent failures
104
+ opsscript-gate run ./install.sh --repeat 3
40
105
  ```
41
106
 
42
107
  `init` creates `.opsscript-gate.json` and a GitHub Actions workflow without replacing
@@ -60,8 +125,8 @@ requires bridge networking. See [configuration and migration](docs/configuration
60
125
  Add this workflow to `.github/workflows/shell-compat.yml`:
61
126
 
62
127
  The repository includes a maintained [workflow template](.github/workflow-templates/opsscript-gate.yml).
63
- For a one-click setup in another public repository, use the InstallReady scanner above; it opens GitHub's
64
- workflow editor with the generated file ready to review.
128
+ Use the [interactive demo](https://mresyzz.github.io/opsscript-gate/) to understand the failure modes,
129
+ then copy the template into your repository and review the generated workflow.
65
130
 
66
131
  You can copy the maintained example from [`examples/github-actions/workflow.yml`](examples/github-actions/workflow.yml)
67
132
  and change the `script-path`, or use the minimal workflow below.
@@ -77,7 +142,7 @@ jobs:
77
142
  - uses: actions/checkout@v7
78
143
  with:
79
144
  persist-credentials: false
80
- - uses: Mresyzz/opsscript-gate@v0.8.2
145
+ - uses: Mresyzz/opsscript-gate@v0.9.0
81
146
  ```
82
147
 
83
148
  This zero-configuration form discovers shell scripts in the repository. Use
@@ -88,11 +153,13 @@ repository has a single installer. For self-hosted model installers, see the
88
153
  Or test a specific script with custom execution modes:
89
154
 
90
155
  ```yaml
91
- - uses: Mresyzz/opsscript-gate@v0.8.2
156
+ - uses: Mresyzz/opsscript-gate@v0.9.0
92
157
  with:
93
158
  script-path: scripts/install.sh
94
159
  shell: auto
95
160
  jobs: 4
161
+ # Optional: expose intermittent runtime failures
162
+ repeat: 3
96
163
  ```
97
164
 
98
165
  ### In Local Terminal (CLI)
@@ -120,7 +187,7 @@ unrelated scripts:
120
187
  with:
121
188
  persist-credentials: false
122
189
  fetch-depth: 0
123
- - uses: Mresyzz/opsscript-gate@v0.8.2
190
+ - uses: Mresyzz/opsscript-gate@v0.9.0
124
191
  with:
125
192
  changed-since: ${{ github.event.pull_request.base.sha }}
126
193
  preset: minimal
@@ -130,6 +197,14 @@ If the change does not include a shell script, the check passes without starting
130
197
  container. The same selection can be previewed locally with
131
198
  `opsscript-gate run --changed-since origin/main --dry-run`.
132
199
 
200
+ ### Detect intermittent runtime failures
201
+
202
+ Use `--repeat N` when a script sometimes passes and sometimes fails in CI. OpsScript
203
+ Gate runs each distribution N times and reports `FLAKY` when the same distribution has
204
+ both passing and failing attempts. The JSON, Markdown, SARIF, annotations, and step
205
+ summary include the attempt counts so a retry cannot silently turn an unstable script
206
+ green.
207
+
133
208
  ### Example: package-manager mismatch
134
209
 
135
210
  Create `install.sh`:
@@ -203,7 +278,7 @@ Use `sarif` when the result should appear in GitHub Code Scanning or another
203
278
  SARIF-compatible viewer. Upload it explicitly with the official upload action:
204
279
 
205
280
  ```yaml
206
- - uses: Mresyzz/opsscript-gate@v0.8.2
281
+ - uses: Mresyzz/opsscript-gate@v0.9.0
207
282
  with:
208
283
  script-path: scripts/install.sh
209
284
  format: sarif
@@ -1,38 +1,8 @@
1
- Metadata-Version: 2.5
2
- Name: opsscript-gate
3
- Version: 0.8.2
4
- Summary: Run Linux shell scripts in Debian, Ubuntu and Alpine containers to catch runtime compatibility failures before merge
5
- Project-URL: Homepage, https://mresyzz.github.io/InstallReady/
6
- Project-URL: Demo, https://mresyzz.github.io/InstallReady/?repo=Mresyzz%2Fopsscript-gate
7
- Project-URL: Repository, https://github.com/Mresyzz/opsscript-gate
8
- Project-URL: Issues, https://github.com/Mresyzz/opsscript-gate/issues
9
- Project-URL: Changelog, https://github.com/Mresyzz/opsscript-gate/blob/main/CHANGELOG.md
10
- Project-URL: Documentation, https://github.com/Mresyzz/opsscript-gate/tree/main/docs
11
- Author: Mresyzz
12
- License: MIT
13
- License-File: LICENSE
14
- Keywords: alpine,bootstrap,busybox,ci,compatibility,cross-distro,debian,devops,docker,github-actions,installer,installer-testing,linux,posix,shell,shell-portability,shellcheck,shellcheck-alternative,testing,ubuntu
15
- Classifier: Development Status :: 4 - Beta
16
- Classifier: Intended Audience :: Developers
17
- Classifier: Intended Audience :: System Administrators
18
- Classifier: License :: OSI Approved :: MIT License
19
- Classifier: Programming Language :: Python :: 3
20
- Classifier: Programming Language :: Python :: 3.10
21
- Classifier: Programming Language :: Python :: 3.11
22
- Classifier: Programming Language :: Python :: 3.12
23
- Classifier: Topic :: Software Development :: Testing
24
- Classifier: Topic :: System :: Systems Administration
25
- Requires-Python: >=3.10
26
- Requires-Dist: docker>=7.0.0
27
- Provides-Extra: test
28
- Requires-Dist: pytest>=8.0.0; extra == 'test'
29
- Description-Content-Type: text/markdown
30
-
31
- # OpsScript Gate — shell script compatibility testing
32
-
33
- [简体中文](README.zh-CN.md) · [Configuration](docs/configuration.md) · [Troubleshooting](docs/troubleshooting.md) · [Self-hosted model installer guide](docs/gpt-oss.md)
34
-
35
- > ShellCheck analyzes shell syntax. OpsScript Gate executes scripts in Linux containers.
1
+ # OpsScript Gate — cross-distro shell script runtime compatibility checker
2
+
3
+ [Live demo](https://mresyzz.github.io/opsscript-gate/) · [简体中文](README.zh-CN.md) · [Configuration](docs/configuration.md) · [Troubleshooting](docs/troubleshooting.md) · [Self-hosted model installer guide](docs/gpt-oss.md)
4
+
5
+ > **OpsScript Gate is a cross-distro shell script runtime compatibility checker.** The GitHub Action and Python CLI test shell installers in real Debian, Ubuntu, and Alpine containers and diagnose failures such as `command not found`. Use it alongside ShellCheck to check both source code and runtime behavior.
36
6
 
37
7
  [![CI](https://github.com/Mresyzz/opsscript-gate/actions/workflows/test.yml/badge.svg)](https://github.com/Mresyzz/opsscript-gate/actions/workflows/test.yml)
38
8
  [![Demo](https://github.com/Mresyzz/opsscript-gate/actions/workflows/demo.yml/badge.svg)](https://github.com/Mresyzz/opsscript-gate/actions/workflows/demo.yml)
@@ -43,23 +13,55 @@ Description-Content-Type: text/markdown
43
13
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
44
14
  [![Supported Distros](https://img.shields.io/badge/matrix-Debian%20%7C%20Ubuntu%20%7C%20Alpine-orange.svg)](#default-test-matrix)
45
15
 
46
- **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.
16
+ **OpsScript Gate** is a cross-distro shell script runtime compatibility checker for Linux. It executes scripts inside unprivileged Debian, Ubuntu, and Alpine containers, catching environment-specific failures, missing interpreters, package-manager assumptions, and exit code 127 errors that static analysis cannot detect.
47
17
 
48
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.
49
19
 
50
- If your repository contains an installer, bootstrap script, or shell entrypoint, the fastest path is to
51
- open the [InstallReady scanner](https://mresyzz.github.io/InstallReady/), enter `owner/repository`, and
52
- choose **Add workflow on GitHub**. It generates a reviewable workflow without an account, API key, or
53
- service signup. You can also copy the maintained [zero-configuration workflow](.github/workflow-templates/opsscript-gate.yml).
20
+ If you arrived here from an error or a search, these are the problems this project answers:
21
+
22
+ - `command not found` when a shell script runs in Docker or GitHub Actions
23
+ - `apt-get: not found` on Alpine, or `apk: not found` on Debian/Ubuntu
24
+ - a shell installer that passes ShellCheck but fails at runtime
25
+ - a shell script compatibility checker that tests runtime commands, not only syntax
26
+ - cross-distro shell testing for installers, bootstrap scripts, and entrypoints
27
+ - testing one shell script across real Debian, Ubuntu, and Alpine containers
28
+ - replacing a hand-written cross-distribution CI matrix with one reusable action
29
+
30
+ Start with the problem-first guide: [debug `command not found` across Debian, Ubuntu, and Alpine](docs/command-not-found.md). It includes a failing script, the diagnosis, a copyable workflow, and the local CLI equivalent.
31
+
32
+ If your repository contains an installer, bootstrap script, or shell entrypoint, start with the
33
+ [interactive demo](https://mresyzz.github.io/opsscript-gate/), then copy the maintained
34
+ [zero-configuration workflow](.github/workflow-templates/opsscript-gate.yml). The demo explains the
35
+ ShellCheck-versus-runtime gap and the workflow is ready to review in your own repository.
54
36
 
55
- Try the browser scanner: [InstallReady](https://mresyzz.github.io/InstallReady/?repo=Mresyzz%2Fopsscript-gate) checks this repository without executing code or requiring a login.
37
+ ### The 15-second proof
38
+
39
+ This script is valid POSIX shell and can pass a syntax linter, but it fails on Alpine because
40
+ `apt-get` is not installed there:
41
+
42
+ ```sh
43
+ #!/bin/sh
44
+ set -eu
45
+ apt-get --version
46
+ ```
47
+
48
+ Run it locally with `opsscript-gate run ./install.sh`, or add the following step to CI:
49
+
50
+ ```yaml
51
+ - uses: Mresyzz/opsscript-gate@v0.9.0
52
+ with:
53
+ script-path: install.sh
54
+ ```
55
+
56
+ The result identifies the failing distribution, exit code, line, missing command, and the usual remediation (`apk` on Alpine). See the [full `command not found` guide](docs/command-not-found.md) for Bash, `curl`, `jq`, and noninteractive prompt cases.
56
57
 
57
58
  ---
58
59
 
59
- ## Current release: v0.8.2
60
+ ## Current release: v0.9.0
60
61
 
61
62
  The current release includes a project config file, a dry-run plan, presets, exclusions,
62
- saved reports, and changed-script selection for pull requests. The project controls
63
+ saved reports, changed-script selection for pull requests, and repeat runs for detecting
64
+ flaky runtime behavior. The project controls
63
65
  were introduced in v0.5.0; projects on v0.4.1 and earlier do not include them.
64
66
 
65
67
  ```bash
@@ -67,6 +69,8 @@ opsscript-gate init
67
69
  opsscript-gate doctor
68
70
  opsscript-gate run --dry-run
69
71
  opsscript-gate run --format json --output reports/compatibility.json
72
+ # Repeat each distro three times when diagnosing intermittent failures
73
+ opsscript-gate run ./install.sh --repeat 3
70
74
  ```
71
75
 
72
76
  `init` creates `.opsscript-gate.json` and a GitHub Actions workflow without replacing
@@ -90,8 +94,8 @@ requires bridge networking. See [configuration and migration](docs/configuration
90
94
  Add this workflow to `.github/workflows/shell-compat.yml`:
91
95
 
92
96
  The repository includes a maintained [workflow template](.github/workflow-templates/opsscript-gate.yml).
93
- For a one-click setup in another public repository, use the InstallReady scanner above; it opens GitHub's
94
- workflow editor with the generated file ready to review.
97
+ Use the [interactive demo](https://mresyzz.github.io/opsscript-gate/) to understand the failure modes,
98
+ then copy the template into your repository and review the generated workflow.
95
99
 
96
100
  You can copy the maintained example from [`examples/github-actions/workflow.yml`](examples/github-actions/workflow.yml)
97
101
  and change the `script-path`, or use the minimal workflow below.
@@ -107,7 +111,7 @@ jobs:
107
111
  - uses: actions/checkout@v7
108
112
  with:
109
113
  persist-credentials: false
110
- - uses: Mresyzz/opsscript-gate@v0.8.2
114
+ - uses: Mresyzz/opsscript-gate@v0.9.0
111
115
  ```
112
116
 
113
117
  This zero-configuration form discovers shell scripts in the repository. Use
@@ -118,11 +122,13 @@ repository has a single installer. For self-hosted model installers, see the
118
122
  Or test a specific script with custom execution modes:
119
123
 
120
124
  ```yaml
121
- - uses: Mresyzz/opsscript-gate@v0.8.2
125
+ - uses: Mresyzz/opsscript-gate@v0.9.0
122
126
  with:
123
127
  script-path: scripts/install.sh
124
128
  shell: auto
125
129
  jobs: 4
130
+ # Optional: expose intermittent runtime failures
131
+ repeat: 3
126
132
  ```
127
133
 
128
134
  ### In Local Terminal (CLI)
@@ -150,7 +156,7 @@ unrelated scripts:
150
156
  with:
151
157
  persist-credentials: false
152
158
  fetch-depth: 0
153
- - uses: Mresyzz/opsscript-gate@v0.8.2
159
+ - uses: Mresyzz/opsscript-gate@v0.9.0
154
160
  with:
155
161
  changed-since: ${{ github.event.pull_request.base.sha }}
156
162
  preset: minimal
@@ -160,6 +166,14 @@ If the change does not include a shell script, the check passes without starting
160
166
  container. The same selection can be previewed locally with
161
167
  `opsscript-gate run --changed-since origin/main --dry-run`.
162
168
 
169
+ ### Detect intermittent runtime failures
170
+
171
+ Use `--repeat N` when a script sometimes passes and sometimes fails in CI. OpsScript
172
+ Gate runs each distribution N times and reports `FLAKY` when the same distribution has
173
+ both passing and failing attempts. The JSON, Markdown, SARIF, annotations, and step
174
+ summary include the attempt counts so a retry cannot silently turn an unstable script
175
+ green.
176
+
163
177
  ### Example: package-manager mismatch
164
178
 
165
179
  Create `install.sh`:
@@ -233,7 +247,7 @@ Use `sarif` when the result should appear in GitHub Code Scanning or another
233
247
  SARIF-compatible viewer. Upload it explicitly with the official upload action:
234
248
 
235
249
  ```yaml
236
- - uses: Mresyzz/opsscript-gate@v0.8.2
250
+ - uses: Mresyzz/opsscript-gate@v0.9.0
237
251
  with:
238
252
  script-path: scripts/install.sh
239
253
  format: sarif
@@ -1,18 +1,25 @@
1
- # OpsScript Gate:Shell 脚本跨发行版运行检查
1
+ # OpsScript Gate:cross-distro shell script runtime compatibility checker
2
2
 
3
- [English](README.md) · [配置说明](docs/configuration.md) · [常见问题](docs/troubleshooting.md) · [自托管模型安装脚本指南](docs/gpt-oss.md)
3
+ OpsScript Gate 是跨发行版 Shell 脚本运行时兼容性检查器(cross-distro shell script runtime compatibility checker)。
4
+ 它在 Debian、Ubuntu、Alpine 中真实运行脚本,诊断 `command not found`。
5
+
6
+ [English](README.md) · [按错误排查:`command not found` / `apt-get: not found`](docs/command-not-found.md) · [配置说明](docs/configuration.md) · [常见问题](docs/troubleshooting.md) · [自托管模型安装脚本指南](docs/gpt-oss.md)
4
7
 
5
8
  在 Debian、Ubuntu、Alpine 容器里实际运行 Shell 脚本,提前发现缺失命令、
6
9
  Bash 依赖、包管理器假设和交互式阻塞。它与 ShellCheck 互补。
7
10
 
11
+ 如果你搜索的是“在 Debian/Ubuntu/Alpine 真实运行 shell 脚本”“Alpine 上
12
+ `apt-get: not found`”“ShellCheck 通过但 CI 运行失败”,请直接看
13
+ [按错误排查的指南](docs/command-not-found.md)。
14
+
8
15
  适合独立安装脚本、容器入口脚本和发布脚本。每次只挂载目标脚本,
9
16
  不挂载整个仓库;依赖其他仓库文件的脚本需要现有项目测试配合。
10
17
 
11
- 也可以直接打开 [InstallReady 在线扫描器](https://mresyzz.github.io/InstallReady/?repo=Mresyzz%2Fopsscript-gate),无需登录即可检查公开仓库。
18
+ 也可以直接打开 [OpsScript Gate 在线演示](https://mresyzz.github.io/opsscript-gate/),先查看 ShellCheck 与运行时验证的差异,再复制 workflow 到自己的仓库。
12
19
 
13
- ## 当前版本 v0.8.2
20
+ ## 当前版本 v0.9.0
14
21
 
15
- v0.8.2 已作为正式版本发布;如果你要从源码验证当前分支,也可以执行:
22
+ v0.9.0 已作为正式版本发布;如果你要从源码验证当前分支,也可以执行:
16
23
 
17
24
  ```bash
18
25
  pip install -e .
@@ -28,7 +35,7 @@ opsscript-gate run --dry-run
28
35
  opsscript-gate run --format json --output reports/compatibility.json
29
36
  ```
30
37
 
31
- `init` 生成配置和 GitHub 工作流,不覆盖已有文件。工作流引用 `v0.8.2`。
38
+ `init` 生成配置和 GitHub 工作流,不覆盖已有文件。工作流引用 `v0.9.0`。
32
39
  预览不需要 Docker;真实运行需要 Python 3.10+
33
40
  和可访问的 Linux Docker 引擎。
34
41
  `opsscript-gate doctor` 可以在真实运行前检查 Python 和 Docker。
@@ -51,6 +58,8 @@ opsscript-gate run --format json --output reports/compatibility.json
51
58
  - 排除规则、发行版预设、扫描数量限制。
52
59
  - 超过扫描上限明确报错,避免只测前 20 个却误以为全部通过。
53
60
  - 报告保存为 JSON、Markdown 或文本,失败时同样保留结果。
61
+ - 使用 `--repeat 3` 或配置 `"repeat": 3` 重复运行每个发行版;同一发行版出现
62
+ 一次通过、一次失败时会标记为 `FLAKY`,避免偶发绿灯掩盖 CI 不稳定。
54
63
  - 自动发现跳过符号链接,并严格校验配置与执行参数。
55
64
 
56
65
  返回码 `0` 表示全部通过,`1` 表示检查失败或发生错误。`--dry-run` 成功只表示
@@ -65,7 +74,7 @@ Docker daemon 和可选的项目配置。
65
74
  - uses: actions/checkout@v7
66
75
  with:
67
76
  fetch-depth: 0
68
- - uses: Mresyzz/opsscript-gate@v0.8.2
77
+ - uses: Mresyzz/opsscript-gate@v0.9.0
69
78
  with:
70
79
  changed-since: ${{ github.event.pull_request.base.sha }}
71
80
  preset: minimal
@@ -4,6 +4,15 @@ This roadmap tracks features delivered in recent releases and areas under consid
4
4
 
5
5
  ---
6
6
 
7
+ ## Delivered in v0.9.0
8
+
9
+ - [x] **Flaky Runtime Detection (`--repeat` / `repeat`)**: Repeat each distribution
10
+ run and report mixed pass/fail outcomes as `FLAKY` with attempt counts.
11
+ - [x] **Bounded Configuration Loading**: Reject oversized project configuration files
12
+ before parsing them.
13
+ - [x] **Blocking Container Wait**: Prefer Docker's wait API over repeated synchronous
14
+ status reloads while retaining a test-double fallback.
15
+
7
16
  ## Delivered in v0.4.0
8
17
 
9
18
  - [x] **High-confidence Line-level GitHub Actions Annotations**: Emits safe `::error` annotations linking failure lines directly on pull request file diffs.
@@ -1,5 +1,5 @@
1
1
  name: 'OpsScript Gate'
2
- description: 'Run Linux shell installers across Debian, Ubuntu, and Alpine; a ShellCheck companion for runtime compatibility in CI.'
2
+ description: 'Cross-distro shell script compatibility checker for runtime testing in Debian, Ubuntu, and Alpine. Diagnoses command not found.'
3
3
  author: 'Mresyzz'
4
4
  branding:
5
5
  icon: 'shield'
@@ -22,6 +22,10 @@ inputs:
22
22
  description: 'Hard timeout in seconds per container (default: 60)'
23
23
  required: false
24
24
  default: ''
25
+ repeat:
26
+ description: 'Repeat each distribution run to detect flaky runtime behavior (default: 1)'
27
+ required: false
28
+ default: ''
25
29
  format:
26
30
  description: 'Output report format: table, markdown, json, or sarif'
27
31
  required: false
@@ -96,6 +100,7 @@ runs:
96
100
  INPUT_MATRIX: ${{ inputs.matrix }}
97
101
  INPUT_JOBS: ${{ inputs.jobs }}
98
102
  INPUT_TIMEOUT: ${{ inputs.timeout }}
103
+ INPUT_REPEAT: ${{ inputs.repeat }}
99
104
  INPUT_FORMAT: ${{ inputs.format }}
100
105
  INPUT_SHELL: ${{ inputs.shell }}
101
106
  INPUT_MEM_LIMIT: ${{ inputs.mem-limit }}
@@ -116,6 +121,7 @@ runs:
116
121
  fi
117
122
  # Only explicit inputs override project configuration.
118
123
  [ -z "$INPUT_TIMEOUT" ] || ARGS+=(--timeout "$INPUT_TIMEOUT")
124
+ [ -z "$INPUT_REPEAT" ] || ARGS+=(--repeat "$INPUT_REPEAT")
119
125
  [ -z "$INPUT_FORMAT" ] || ARGS+=(--format "$INPUT_FORMAT")
120
126
  [ -z "$INPUT_SHELL" ] || ARGS+=(--shell "$INPUT_SHELL")
121
127
  [ -z "$INPUT_MEM_LIMIT" ] || ARGS+=(--mem-limit "$INPUT_MEM_LIMIT")