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.
- {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/.github/workflow-templates/opsscript-gate.properties.json +1 -1
- {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/.github/workflow-templates/opsscript-gate.yml +1 -1
- opsscript_gate-0.9.0/.github/workflows/deploy-pages.yml +34 -0
- {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/CHANGELOG.md +16 -0
- {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/CITATION.cff +1 -1
- opsscript_gate-0.8.2/README.md → opsscript_gate-0.9.0/PKG-INFO +94 -19
- opsscript_gate-0.8.2/PKG-INFO → opsscript_gate-0.9.0/README.md +63 -49
- {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/README.zh-CN.md +16 -7
- {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/ROADMAP.md +9 -0
- {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/action.yml +7 -1
- opsscript_gate-0.9.0/demo.html +980 -0
- opsscript_gate-0.9.0/docs/command-not-found.html +122 -0
- opsscript_gate-0.9.0/docs/command-not-found.md +119 -0
- {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/docs/configuration.md +8 -3
- {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/docs/gpt-oss.md +1 -1
- opsscript_gate-0.9.0/docs/index.html +988 -0
- opsscript_gate-0.9.0/docs/llms.txt +26 -0
- opsscript_gate-0.9.0/docs/sitemap.xml +5 -0
- {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/examples/github-actions/README.md +1 -1
- {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/examples/github-actions/workflow.yml +1 -1
- opsscript_gate-0.9.0/index.html +988 -0
- opsscript_gate-0.9.0/llms.txt +26 -0
- {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/pyproject.toml +12 -4
- {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/src/opsscript_gate/__init__.py +1 -1
- {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/src/opsscript_gate/cli.py +38 -37
- {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/src/opsscript_gate/config.py +9 -2
- {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/src/opsscript_gate/models.py +20 -1
- {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/src/opsscript_gate/reporter.py +12 -1
- {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/src/opsscript_gate/runner.py +75 -26
- {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/tests/test_action_contract.py +2 -2
- {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/tests/test_onboarding.py +14 -1
- {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/tests/test_runner.py +60 -1
- {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/.gitattributes +0 -0
- {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/.github/ISSUE_TEMPLATE/distro_request.yml +0 -0
- {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/.github/assets/social-preview.png +0 -0
- {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/.github/pull_request_template.md +0 -0
- {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/.github/workflows/demo.yml +0 -0
- {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/.github/workflows/release.yml +0 -0
- {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/.github/workflows/test.yml +0 -0
- {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/.gitignore +0 -0
- {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/CONTRIBUTING.md +0 -0
- {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/LICENSE +0 -0
- {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/SECURITY.md +0 -0
- {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/docs/troubleshooting.md +0 -0
- {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/examples/alpine-incompatibility/README.md +0 -0
- {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/examples/alpine-incompatibility/apt_dependency.sh +0 -0
- {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/examples/basic/README.md +0 -0
- {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/examples/basic/clean_setup.sh +0 -0
- {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/examples/interactive-hang/README.md +0 -0
- {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/examples/interactive-hang/prompt_confirm.sh +0 -0
- {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/src/opsscript_gate/discovery.py +0 -0
- {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/src/opsscript_gate/remediation.py +0 -0
- {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/tests/fixtures/fail_deps.sh +0 -0
- {opsscript_gate-0.8.2 → opsscript_gate-0.9.0}/tests/fixtures/fail_hang.sh +0 -0
- {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
|
|
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$"]
|
|
@@ -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
|
|
@@ -1,8 +1,39 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
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
|
[](https://github.com/Mresyzz/opsscript-gate/actions/workflows/test.yml)
|
|
8
39
|
[](https://github.com/Mresyzz/opsscript-gate/actions/workflows/demo.yml)
|
|
@@ -13,23 +44,55 @@
|
|
|
13
44
|
[](https://opensource.org/licenses/MIT)
|
|
14
45
|
[](#default-test-matrix)
|
|
15
46
|
|
|
16
|
-
**OpsScript Gate** is a runtime compatibility checker for Linux
|
|
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
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
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
|
-
|
|
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.
|
|
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,
|
|
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
|
-
|
|
64
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
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
|
[](https://github.com/Mresyzz/opsscript-gate/actions/workflows/test.yml)
|
|
38
8
|
[](https://github.com/Mresyzz/opsscript-gate/actions/workflows/demo.yml)
|
|
@@ -43,23 +13,55 @@ Description-Content-Type: text/markdown
|
|
|
43
13
|
[](https://opensource.org/licenses/MIT)
|
|
44
14
|
[](#default-test-matrix)
|
|
45
15
|
|
|
46
|
-
**OpsScript Gate** is a runtime compatibility checker for Linux
|
|
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
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
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
|
-
|
|
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.
|
|
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,
|
|
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
|
-
|
|
94
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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:
|
|
1
|
+
# OpsScript Gate:cross-distro shell script runtime compatibility checker
|
|
2
2
|
|
|
3
|
-
|
|
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
|
-
也可以直接打开 [
|
|
18
|
+
也可以直接打开 [OpsScript Gate 在线演示](https://mresyzz.github.io/opsscript-gate/),先查看 ShellCheck 与运行时验证的差异,再复制 workflow 到自己的仓库。
|
|
12
19
|
|
|
13
|
-
## 当前版本 v0.
|
|
20
|
+
## 当前版本 v0.9.0
|
|
14
21
|
|
|
15
|
-
v0.
|
|
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.
|
|
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.
|
|
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: '
|
|
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")
|