opsscript-gate 0.8.3__tar.gz → 0.9.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {opsscript_gate-0.8.3 → opsscript_gate-0.9.1}/.github/workflow-templates/opsscript-gate.properties.json +1 -1
- {opsscript_gate-0.8.3 → opsscript_gate-0.9.1}/CHANGELOG.md +20 -0
- {opsscript_gate-0.8.3 → opsscript_gate-0.9.1}/CITATION.cff +1 -1
- opsscript_gate-0.8.3/README.md → opsscript_gate-0.9.1/PKG-INFO +86 -9
- opsscript_gate-0.8.3/PKG-INFO → opsscript_gate-0.9.1/README.md +55 -39
- {opsscript_gate-0.8.3 → opsscript_gate-0.9.1}/README.zh-CN.md +15 -6
- {opsscript_gate-0.8.3 → opsscript_gate-0.9.1}/ROADMAP.md +9 -0
- {opsscript_gate-0.8.3 → opsscript_gate-0.9.1}/action.yml +7 -1
- {opsscript_gate-0.8.3 → opsscript_gate-0.9.1}/demo.html +4 -4
- opsscript_gate-0.9.1/docs/command-not-found.html +122 -0
- opsscript_gate-0.9.1/docs/command-not-found.md +119 -0
- {opsscript_gate-0.8.3 → opsscript_gate-0.9.1}/docs/configuration.md +8 -3
- {opsscript_gate-0.8.3 → opsscript_gate-0.9.1}/docs/gpt-oss.md +1 -1
- {opsscript_gate-0.8.3 → opsscript_gate-0.9.1}/docs/index.html +13 -5
- opsscript_gate-0.9.1/docs/llms.txt +26 -0
- opsscript_gate-0.9.1/docs/sitemap.xml +5 -0
- {opsscript_gate-0.8.3 → opsscript_gate-0.9.1}/examples/github-actions/README.md +1 -1
- {opsscript_gate-0.8.3 → opsscript_gate-0.9.1}/examples/github-actions/workflow.yml +1 -1
- {opsscript_gate-0.8.3 → opsscript_gate-0.9.1}/index.html +13 -5
- opsscript_gate-0.9.1/llms.txt +26 -0
- {opsscript_gate-0.8.3 → opsscript_gate-0.9.1}/pyproject.toml +10 -2
- {opsscript_gate-0.8.3 → opsscript_gate-0.9.1}/src/opsscript_gate/__init__.py +1 -1
- {opsscript_gate-0.8.3 → opsscript_gate-0.9.1}/src/opsscript_gate/cli.py +59 -42
- {opsscript_gate-0.8.3 → opsscript_gate-0.9.1}/src/opsscript_gate/config.py +9 -2
- {opsscript_gate-0.8.3 → opsscript_gate-0.9.1}/src/opsscript_gate/discovery.py +12 -2
- {opsscript_gate-0.8.3 → opsscript_gate-0.9.1}/src/opsscript_gate/models.py +20 -1
- {opsscript_gate-0.8.3 → opsscript_gate-0.9.1}/src/opsscript_gate/reporter.py +16 -5
- {opsscript_gate-0.8.3 → opsscript_gate-0.9.1}/src/opsscript_gate/runner.py +148 -34
- {opsscript_gate-0.8.3 → opsscript_gate-0.9.1}/tests/test_action_contract.py +2 -2
- {opsscript_gate-0.8.3 → opsscript_gate-0.9.1}/tests/test_onboarding.py +32 -1
- {opsscript_gate-0.8.3 → opsscript_gate-0.9.1}/tests/test_runner.py +132 -1
- {opsscript_gate-0.8.3 → opsscript_gate-0.9.1}/.gitattributes +0 -0
- {opsscript_gate-0.8.3 → opsscript_gate-0.9.1}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {opsscript_gate-0.8.3 → opsscript_gate-0.9.1}/.github/ISSUE_TEMPLATE/distro_request.yml +0 -0
- {opsscript_gate-0.8.3 → opsscript_gate-0.9.1}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {opsscript_gate-0.8.3 → opsscript_gate-0.9.1}/.github/assets/social-preview.png +0 -0
- {opsscript_gate-0.8.3 → opsscript_gate-0.9.1}/.github/pull_request_template.md +0 -0
- {opsscript_gate-0.8.3 → opsscript_gate-0.9.1}/.github/workflow-templates/opsscript-gate.yml +0 -0
- {opsscript_gate-0.8.3 → opsscript_gate-0.9.1}/.github/workflows/demo.yml +0 -0
- {opsscript_gate-0.8.3 → opsscript_gate-0.9.1}/.github/workflows/deploy-pages.yml +0 -0
- {opsscript_gate-0.8.3 → opsscript_gate-0.9.1}/.github/workflows/release.yml +0 -0
- {opsscript_gate-0.8.3 → opsscript_gate-0.9.1}/.github/workflows/test.yml +0 -0
- {opsscript_gate-0.8.3 → opsscript_gate-0.9.1}/.gitignore +0 -0
- {opsscript_gate-0.8.3 → opsscript_gate-0.9.1}/CONTRIBUTING.md +0 -0
- {opsscript_gate-0.8.3 → opsscript_gate-0.9.1}/LICENSE +0 -0
- {opsscript_gate-0.8.3 → opsscript_gate-0.9.1}/SECURITY.md +0 -0
- {opsscript_gate-0.8.3 → opsscript_gate-0.9.1}/docs/troubleshooting.md +0 -0
- {opsscript_gate-0.8.3 → opsscript_gate-0.9.1}/examples/alpine-incompatibility/README.md +0 -0
- {opsscript_gate-0.8.3 → opsscript_gate-0.9.1}/examples/alpine-incompatibility/apt_dependency.sh +0 -0
- {opsscript_gate-0.8.3 → opsscript_gate-0.9.1}/examples/basic/README.md +0 -0
- {opsscript_gate-0.8.3 → opsscript_gate-0.9.1}/examples/basic/clean_setup.sh +0 -0
- {opsscript_gate-0.8.3 → opsscript_gate-0.9.1}/examples/interactive-hang/README.md +0 -0
- {opsscript_gate-0.8.3 → opsscript_gate-0.9.1}/examples/interactive-hang/prompt_confirm.sh +0 -0
- {opsscript_gate-0.8.3 → opsscript_gate-0.9.1}/src/opsscript_gate/remediation.py +0 -0
- {opsscript_gate-0.8.3 → opsscript_gate-0.9.1}/tests/fixtures/fail_deps.sh +0 -0
- {opsscript_gate-0.8.3 → opsscript_gate-0.9.1}/tests/fixtures/fail_hang.sh +0 -0
- {opsscript_gate-0.8.3 → opsscript_gate-0.9.1}/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$"]
|
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.9.1] - 2026-10-03
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
- Normalized discovery exclusions so top-level paths match with or without `./`.
|
|
7
|
+
- Made SARIF output conform to the 2.1.0 result schema.
|
|
8
|
+
- Failed closed when Docker omitted an exit code and separated package setup errors from script failures.
|
|
9
|
+
- Validated project configuration in `doctor` and handled UTF-8 BOM scripts.
|
|
10
|
+
- Distinguished Docker wait API errors from genuine execution timeouts.
|
|
11
|
+
|
|
12
|
+
## [0.9.0] - 2026-10-03
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
- Added `--repeat` and Action/config `repeat` support to detect flaky runtime behavior per distribution.
|
|
16
|
+
- Added attempt counts and `FLAKY` status to JSON, Markdown, SARIF, terminal, and GitHub Step Summary reports.
|
|
17
|
+
|
|
18
|
+
### Fixed
|
|
19
|
+
- Bounded project configuration reads to prevent oversized configuration files from consuming unbounded memory.
|
|
20
|
+
- Prefer Docker's blocking wait API over repeated synchronous container reloads, while retaining a bounded compatibility fallback.
|
|
21
|
+
- Removed duplicated CLI execution error handling and the unused `asdict` import.
|
|
22
|
+
|
|
3
23
|
## [0.8.3] - 2026-10-02
|
|
4
24
|
|
|
5
25
|
- Corrected the PyPI homepage and demo links to point to the OpsScript Gate Pages site.
|
|
@@ -1,8 +1,39 @@
|
|
|
1
|
-
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: opsscript-gate
|
|
3
|
+
Version: 0.9.1
|
|
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
|
|
2
33
|
|
|
3
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)
|
|
4
35
|
|
|
5
|
-
>
|
|
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,21 +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
|
|
|
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
|
+
|
|
20
63
|
If your repository contains an installer, bootstrap script, or shell entrypoint, start with the
|
|
21
64
|
[interactive demo](https://mresyzz.github.io/opsscript-gate/), then copy the maintained
|
|
22
65
|
[zero-configuration workflow](.github/workflow-templates/opsscript-gate.yml). The demo explains the
|
|
23
66
|
ShellCheck-versus-runtime gap and the workflow is ready to review in your own repository.
|
|
24
67
|
|
|
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.1
|
|
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.
|
|
88
|
+
|
|
25
89
|
---
|
|
26
90
|
|
|
27
|
-
## Current release: v0.
|
|
91
|
+
## Current release: v0.9.1
|
|
28
92
|
|
|
29
93
|
The current release includes a project config file, a dry-run plan, presets, exclusions,
|
|
30
|
-
saved reports,
|
|
94
|
+
saved reports, changed-script selection for pull requests, and repeat runs for detecting
|
|
95
|
+
flaky runtime behavior. The project controls
|
|
31
96
|
were introduced in v0.5.0; projects on v0.4.1 and earlier do not include them.
|
|
32
97
|
|
|
33
98
|
```bash
|
|
@@ -35,6 +100,8 @@ opsscript-gate init
|
|
|
35
100
|
opsscript-gate doctor
|
|
36
101
|
opsscript-gate run --dry-run
|
|
37
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
|
|
38
105
|
```
|
|
39
106
|
|
|
40
107
|
`init` creates `.opsscript-gate.json` and a GitHub Actions workflow without replacing
|
|
@@ -75,7 +142,7 @@ jobs:
|
|
|
75
142
|
- uses: actions/checkout@v7
|
|
76
143
|
with:
|
|
77
144
|
persist-credentials: false
|
|
78
|
-
- uses: Mresyzz/opsscript-gate@v0.
|
|
145
|
+
- uses: Mresyzz/opsscript-gate@v0.9.1
|
|
79
146
|
```
|
|
80
147
|
|
|
81
148
|
This zero-configuration form discovers shell scripts in the repository. Use
|
|
@@ -86,11 +153,13 @@ repository has a single installer. For self-hosted model installers, see the
|
|
|
86
153
|
Or test a specific script with custom execution modes:
|
|
87
154
|
|
|
88
155
|
```yaml
|
|
89
|
-
- uses: Mresyzz/opsscript-gate@v0.
|
|
156
|
+
- uses: Mresyzz/opsscript-gate@v0.9.1
|
|
90
157
|
with:
|
|
91
158
|
script-path: scripts/install.sh
|
|
92
159
|
shell: auto
|
|
93
160
|
jobs: 4
|
|
161
|
+
# Optional: expose intermittent runtime failures
|
|
162
|
+
repeat: 3
|
|
94
163
|
```
|
|
95
164
|
|
|
96
165
|
### In Local Terminal (CLI)
|
|
@@ -118,7 +187,7 @@ unrelated scripts:
|
|
|
118
187
|
with:
|
|
119
188
|
persist-credentials: false
|
|
120
189
|
fetch-depth: 0
|
|
121
|
-
- uses: Mresyzz/opsscript-gate@v0.
|
|
190
|
+
- uses: Mresyzz/opsscript-gate@v0.9.1
|
|
122
191
|
with:
|
|
123
192
|
changed-since: ${{ github.event.pull_request.base.sha }}
|
|
124
193
|
preset: minimal
|
|
@@ -128,6 +197,14 @@ If the change does not include a shell script, the check passes without starting
|
|
|
128
197
|
container. The same selection can be previewed locally with
|
|
129
198
|
`opsscript-gate run --changed-since origin/main --dry-run`.
|
|
130
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
|
+
|
|
131
208
|
### Example: package-manager mismatch
|
|
132
209
|
|
|
133
210
|
Create `install.sh`:
|
|
@@ -201,7 +278,7 @@ Use `sarif` when the result should appear in GitHub Code Scanning or another
|
|
|
201
278
|
SARIF-compatible viewer. Upload it explicitly with the official upload action:
|
|
202
279
|
|
|
203
280
|
```yaml
|
|
204
|
-
- uses: Mresyzz/opsscript-gate@v0.
|
|
281
|
+
- uses: Mresyzz/opsscript-gate@v0.9.1
|
|
205
282
|
with:
|
|
206
283
|
script-path: scripts/install.sh
|
|
207
284
|
format: sarif
|
|
@@ -1,38 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
Name: opsscript-gate
|
|
3
|
-
Version: 0.8.3
|
|
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/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
|
-
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 — GitHub Action for cross-distro shell installer testing
|
|
1
|
+
# OpsScript Gate — cross-distro shell script runtime compatibility checker
|
|
32
2
|
|
|
33
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)
|
|
34
4
|
|
|
35
|
-
>
|
|
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,21 +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
|
|
|
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
|
+
|
|
50
32
|
If your repository contains an installer, bootstrap script, or shell entrypoint, start with the
|
|
51
33
|
[interactive demo](https://mresyzz.github.io/opsscript-gate/), then copy the maintained
|
|
52
34
|
[zero-configuration workflow](.github/workflow-templates/opsscript-gate.yml). The demo explains the
|
|
53
35
|
ShellCheck-versus-runtime gap and the workflow is ready to review in your own repository.
|
|
54
36
|
|
|
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.1
|
|
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.
|
|
57
|
+
|
|
55
58
|
---
|
|
56
59
|
|
|
57
|
-
## Current release: v0.
|
|
60
|
+
## Current release: v0.9.1
|
|
58
61
|
|
|
59
62
|
The current release includes a project config file, a dry-run plan, presets, exclusions,
|
|
60
|
-
saved reports,
|
|
63
|
+
saved reports, changed-script selection for pull requests, and repeat runs for detecting
|
|
64
|
+
flaky runtime behavior. The project controls
|
|
61
65
|
were introduced in v0.5.0; projects on v0.4.1 and earlier do not include them.
|
|
62
66
|
|
|
63
67
|
```bash
|
|
@@ -65,6 +69,8 @@ opsscript-gate init
|
|
|
65
69
|
opsscript-gate doctor
|
|
66
70
|
opsscript-gate run --dry-run
|
|
67
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
|
|
68
74
|
```
|
|
69
75
|
|
|
70
76
|
`init` creates `.opsscript-gate.json` and a GitHub Actions workflow without replacing
|
|
@@ -105,7 +111,7 @@ jobs:
|
|
|
105
111
|
- uses: actions/checkout@v7
|
|
106
112
|
with:
|
|
107
113
|
persist-credentials: false
|
|
108
|
-
- uses: Mresyzz/opsscript-gate@v0.
|
|
114
|
+
- uses: Mresyzz/opsscript-gate@v0.9.1
|
|
109
115
|
```
|
|
110
116
|
|
|
111
117
|
This zero-configuration form discovers shell scripts in the repository. Use
|
|
@@ -116,11 +122,13 @@ repository has a single installer. For self-hosted model installers, see the
|
|
|
116
122
|
Or test a specific script with custom execution modes:
|
|
117
123
|
|
|
118
124
|
```yaml
|
|
119
|
-
- uses: Mresyzz/opsscript-gate@v0.
|
|
125
|
+
- uses: Mresyzz/opsscript-gate@v0.9.1
|
|
120
126
|
with:
|
|
121
127
|
script-path: scripts/install.sh
|
|
122
128
|
shell: auto
|
|
123
129
|
jobs: 4
|
|
130
|
+
# Optional: expose intermittent runtime failures
|
|
131
|
+
repeat: 3
|
|
124
132
|
```
|
|
125
133
|
|
|
126
134
|
### In Local Terminal (CLI)
|
|
@@ -148,7 +156,7 @@ unrelated scripts:
|
|
|
148
156
|
with:
|
|
149
157
|
persist-credentials: false
|
|
150
158
|
fetch-depth: 0
|
|
151
|
-
- uses: Mresyzz/opsscript-gate@v0.
|
|
159
|
+
- uses: Mresyzz/opsscript-gate@v0.9.1
|
|
152
160
|
with:
|
|
153
161
|
changed-since: ${{ github.event.pull_request.base.sha }}
|
|
154
162
|
preset: minimal
|
|
@@ -158,6 +166,14 @@ If the change does not include a shell script, the check passes without starting
|
|
|
158
166
|
container. The same selection can be previewed locally with
|
|
159
167
|
`opsscript-gate run --changed-since origin/main --dry-run`.
|
|
160
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
|
+
|
|
161
177
|
### Example: package-manager mismatch
|
|
162
178
|
|
|
163
179
|
Create `install.sh`:
|
|
@@ -231,7 +247,7 @@ Use `sarif` when the result should appear in GitHub Code Scanning or another
|
|
|
231
247
|
SARIF-compatible viewer. Upload it explicitly with the official upload action:
|
|
232
248
|
|
|
233
249
|
```yaml
|
|
234
|
-
- uses: Mresyzz/opsscript-gate@v0.
|
|
250
|
+
- uses: Mresyzz/opsscript-gate@v0.9.1
|
|
235
251
|
with:
|
|
236
252
|
script-path: scripts/install.sh
|
|
237
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")
|
|
@@ -232,7 +232,7 @@
|
|
|
232
232
|
OpsScript Gate
|
|
233
233
|
</span>
|
|
234
234
|
<span class="font-mono text-[11px] px-1.5 py-0.5 rounded bg-[var(--surface-muted)] text-[var(--text-muted)] border border-[var(--border-light)]">
|
|
235
|
-
v0.
|
|
235
|
+
v0.9.0
|
|
236
236
|
</span>
|
|
237
237
|
</div>
|
|
238
238
|
</div>
|
|
@@ -367,7 +367,7 @@
|
|
|
367
367
|
<div class="panel-card p-4 flex flex-col justify-between space-y-3">
|
|
368
368
|
<div class="space-y-2.5">
|
|
369
369
|
<div class="flex items-center justify-between border-b border-[var(--border-light)] pb-2">
|
|
370
|
-
<span class="font-mono text-xs font-medium text-[var(--text-muted)]">OpsScript Gate Runtime (v0.
|
|
370
|
+
<span class="font-mono text-xs font-medium text-[var(--text-muted)]">OpsScript Gate Runtime (v0.9.0)</span>
|
|
371
371
|
<span id="ops-status" class="font-mono text-xs font-semibold px-2 py-0.5 rounded border">
|
|
372
372
|
1 DISTRO FAILED
|
|
373
373
|
</span>
|
|
@@ -536,7 +536,7 @@
|
|
|
536
536
|
<span class="font-semibold text-[var(--text-hero)]">steps:</span>
|
|
537
537
|
- <span class="font-semibold text-[var(--text-hero)]">uses:</span> actions/checkout@v4
|
|
538
538
|
- <span class="font-semibold text-[var(--text-hero)]">name:</span> Validate scripts across distributions
|
|
539
|
-
<span class="font-semibold text-[var(--brand)]">uses:</span> Mresyzz/opsscript-gate@v0.
|
|
539
|
+
<span class="font-semibold text-[var(--brand)]">uses:</span> Mresyzz/opsscript-gate@v0.9.0
|
|
540
540
|
<span class="font-semibold text-[var(--text-hero)]">with:</span>
|
|
541
541
|
<span class="text-[var(--text-body)]">script-path:</span> ./install.sh
|
|
542
542
|
<span class="text-[var(--text-body)]">shell:</span> auto
|
|
@@ -604,7 +604,7 @@ jobs:
|
|
|
604
604
|
steps:
|
|
605
605
|
- uses: actions/checkout@v4
|
|
606
606
|
- name: Validate scripts across distributions
|
|
607
|
-
uses: Mresyzz/opsscript-gate@v0.
|
|
607
|
+
uses: Mresyzz/opsscript-gate@v0.9.0
|
|
608
608
|
with:
|
|
609
609
|
script-path: ./install.sh
|
|
610
610
|
shell: auto
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
6
|
+
<title>Test shell scripts in Debian, Ubuntu and Alpine: command not found | OpsScript Gate</title>
|
|
7
|
+
<meta name="description" content="Test a shell installer in real Debian, Ubuntu and Alpine containers. Diagnose command not found, exit code 127 and missing Bash with OpsScript Gate, a GitHub Action and CLI.">
|
|
8
|
+
<link rel="canonical" href="https://mresyzz.github.io/opsscript-gate/command-not-found.html">
|
|
9
|
+
<meta property="og:title" content="ShellCheck passed. Does your installer run on Alpine?">
|
|
10
|
+
<meta property="og:description" content="A reproducible shell runtime compatibility check for Debian, Ubuntu and Alpine, with a copyable GitHub Actions workflow.">
|
|
11
|
+
<meta property="og:url" content="https://mresyzz.github.io/opsscript-gate/command-not-found.html">
|
|
12
|
+
<style>
|
|
13
|
+
:root { color-scheme: light; --ink:#262420; --muted:#59544b; --accent:#a94a31; --line:#ddd6c9; }
|
|
14
|
+
* { box-sizing:border-box; }
|
|
15
|
+
body { margin:0; background:#faf8f5; color:var(--ink); font:17px/1.7 system-ui,sans-serif; }
|
|
16
|
+
main { width:min(900px,100%); margin:auto; padding:32px 24px 64px; }
|
|
17
|
+
nav { display:flex; flex-wrap:wrap; justify-content:space-between; gap:12px; padding-bottom:28px; }
|
|
18
|
+
a { color:var(--accent); text-underline-offset:4px; }
|
|
19
|
+
a:focus-visible { outline:3px solid var(--accent); outline-offset:5px; }
|
|
20
|
+
h1 { font:normal clamp(32px,6vw,48px)/1.18 Georgia,serif; letter-spacing:-.025em; margin:12px 0 20px; }
|
|
21
|
+
h2 { font:normal 28px/1.3 Georgia,serif; margin:38px 0 12px; }
|
|
22
|
+
h3 { font-size:18px; margin:0 0 10px; }
|
|
23
|
+
p { margin:12px 0; } .eyebrow,.muted { color:var(--muted); }
|
|
24
|
+
.eyebrow { font-size:13px; letter-spacing:.05em; text-transform:uppercase; }
|
|
25
|
+
pre { background:#f0ebe2; padding:20px; border:1px solid var(--line); border-radius:9px; overflow:auto; font:14px/1.65 Consolas,monospace; }
|
|
26
|
+
code { font-family:Consolas,monospace; } p code,td code { font-size:.9em; }
|
|
27
|
+
.table-wrap { overflow:auto; } table { border-collapse:collapse; width:100%; }
|
|
28
|
+
th,td { text-align:left; padding:12px; border-bottom:1px solid var(--line); }
|
|
29
|
+
.pass { color:#1e593d; } .fail { color:#8a342b; }
|
|
30
|
+
.cards { display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:14px; }
|
|
31
|
+
.card { border:1px solid var(--line); background:white; border-radius:9px; padding:20px; font-size:15px; }
|
|
32
|
+
.cta { display:inline-block; background:var(--accent); color:white; padding:10px 18px; border-radius:6px; text-decoration:none; margin:16px 0; }
|
|
33
|
+
footer { margin-top:40px; padding-top:20px; border-top:1px solid var(--line); font-size:14px; }
|
|
34
|
+
@media (max-width:650px) { .cards { grid-template-columns:1fr; } main { padding:24px 18px 48px; } }
|
|
35
|
+
</style>
|
|
36
|
+
</head>
|
|
37
|
+
<body>
|
|
38
|
+
<main>
|
|
39
|
+
<nav aria-label="Primary"><a href="./">OpsScript Gate</a><a href="https://github.com/Mresyzz/opsscript-gate">GitHub repository</a></nav>
|
|
40
|
+
<p class="eyebrow">Cross-distro shell script runtime compatibility checker</p>
|
|
41
|
+
<h1>ShellCheck passed.<br>Your installer still failed on Alpine.</h1>
|
|
42
|
+
<p><strong>OpsScript Gate tests shell scripts in real Debian, Ubuntu, and Alpine containers.</strong>
|
|
43
|
+
It is a GitHub Action and Python CLI that reports each distribution's PASS/FAIL result and
|
|
44
|
+
diagnoses runtime failures such as <code>command not found</code>.</p>
|
|
45
|
+
<p>Use it for standalone installers, bootstrap scripts, and shell entrypoints. You supply the script;
|
|
46
|
+
the tool runs the distribution matrix and collects the diagnostic report.</p>
|
|
47
|
+
<a class="cta" href="#workflow">Add the runtime check to CI</a>
|
|
48
|
+
|
|
49
|
+
<h2>A valid shell script can assume the wrong command</h2>
|
|
50
|
+
<p>Save this as <code>install.sh</code>. The syntax is valid POSIX shell, but Alpine uses
|
|
51
|
+
<code>apk</code> and does not supply <code>apt-get</code> in its standard image.</p>
|
|
52
|
+
<pre><code>#!/bin/sh
|
|
53
|
+
set -eu
|
|
54
|
+
apt-get --version</code></pre>
|
|
55
|
+
<p class="muted">Expected outcome for this example; this page does not execute containers in your browser.</p>
|
|
56
|
+
<div class="table-wrap"><table>
|
|
57
|
+
<thead><tr><th scope="col">Image</th><th scope="col">Result</th><th scope="col">Diagnostic</th></tr></thead>
|
|
58
|
+
<tbody>
|
|
59
|
+
<tr><td><code>debian:12-slim</code></td><td class="pass">PASS</td><td>Exit 0</td></tr>
|
|
60
|
+
<tr><td><code>ubuntu:22.04</code></td><td class="pass">PASS</td><td>Exit 0</td></tr>
|
|
61
|
+
<tr><td><code>ubuntu:24.04</code></td><td class="pass">PASS</td><td>Exit 0</td></tr>
|
|
62
|
+
<tr><td><code>alpine:3.20</code></td><td class="fail">FAIL</td><td>Exit 127: <code>apt-get: not found</code>, line 3</td></tr>
|
|
63
|
+
</tbody>
|
|
64
|
+
</table></div>
|
|
65
|
+
<p>A shell linter checks source code. Executing the script tests which commands actually exist in the target image.
|
|
66
|
+
Run both checks to cover source mistakes and runtime assumptions.</p>
|
|
67
|
+
|
|
68
|
+
<h2 id="workflow">A complete GitHub Actions workflow</h2>
|
|
69
|
+
<p>Copy this into <code>.github/workflows/shell-runtime.yml</code> and set <code>script-path</code>
|
|
70
|
+
to your installer. The Ubuntu runner starts the Debian, Ubuntu, and Alpine containers.</p>
|
|
71
|
+
<pre><code>name: Shell runtime compatibility
|
|
72
|
+
on: [push, pull_request]
|
|
73
|
+
permissions:
|
|
74
|
+
contents: read
|
|
75
|
+
jobs:
|
|
76
|
+
runtime:
|
|
77
|
+
runs-on: ubuntu-latest
|
|
78
|
+
steps:
|
|
79
|
+
- uses: actions/checkout@v7
|
|
80
|
+
with:
|
|
81
|
+
persist-credentials: false
|
|
82
|
+
- uses: Mresyzz/opsscript-gate@v0.9.0
|
|
83
|
+
with:
|
|
84
|
+
script-path: install.sh
|
|
85
|
+
shell: auto
|
|
86
|
+
format: markdown
|
|
87
|
+
output: reports/compatibility.md</code></pre>
|
|
88
|
+
<p>The report includes the image, exit code, script line where available, missing command, and remediation hint.
|
|
89
|
+
GitHub Actions also receives workflow annotations and a Step Summary.
|
|
90
|
+
<a href="https://github.com/Mresyzz/opsscript-gate/actions/workflows/demo.yml">Inspect the project's real CI demo runs</a>.</p>
|
|
91
|
+
|
|
92
|
+
<h2>What the failure tells you</h2>
|
|
93
|
+
<div class="cards">
|
|
94
|
+
<article class="card"><h3><code>apt-get: not found</code></h3><p>Check for APT or <code>apk</code> before calling it.
|
|
95
|
+
Package names differ by distribution; do not replace them blindly.</p></article>
|
|
96
|
+
<article class="card"><h3><code>/bin/bash: not found</code></h3><p>Minimal Alpine omits Bash by default.
|
|
97
|
+
Use POSIX shell or declare an image or package prerequisite that supplies Bash.</p></article>
|
|
98
|
+
<article class="card"><h3><code>curl</code> or <code>jq</code> missing</h3><p>Minimal images omit many convenience tools.
|
|
99
|
+
Declare required tools through <code>packages</code> or explain the prerequisite in your installer.</p></article>
|
|
100
|
+
</div>
|
|
101
|
+
|
|
102
|
+
<h2>Run the same check locally</h2>
|
|
103
|
+
<p>Requires Python 3.10+ and a reachable Docker engine running Linux containers.</p>
|
|
104
|
+
<pre><code>pip install opsscript-gate
|
|
105
|
+
opsscript-gate doctor
|
|
106
|
+
opsscript-gate run ./install.sh</code></pre>
|
|
107
|
+
<p>The CLI supports table, Markdown, JSON, and SARIF reports.
|
|
108
|
+
<code>--dry-run</code> previews the plan without Docker; it does not verify runtime compatibility.</p>
|
|
109
|
+
|
|
110
|
+
<h2>Where this check fits</h2>
|
|
111
|
+
<p>ShellCheck analyzes shell source; OpsScript Gate executes it across distributions. A handwritten Docker matrix
|
|
112
|
+
can also run scripts, but you maintain its image list, timeouts, log parsing, and reports.</p>
|
|
113
|
+
<p>OpsScript Gate mounts each script independently. Sibling files and repository dependencies are not mounted.
|
|
114
|
+
These are distribution user-space tests in containers, not separate Linux kernels or full-machine tests.
|
|
115
|
+
Passing checks do not prove security or replace project integration tests.</p>
|
|
116
|
+
<footer>Read the <a href="https://github.com/Mresyzz/opsscript-gate/blob/main/docs/configuration.md">configuration guide</a>,
|
|
117
|
+
<a href="https://github.com/Mresyzz/opsscript-gate/blob/main/docs/troubleshooting.md">troubleshooting</a>,
|
|
118
|
+
or <a href="https://github.com/Mresyzz/opsscript-gate/blob/main/SECURITY.md">security boundaries</a>.
|
|
119
|
+
<a href="./">Open the interactive demo</a>.</footer>
|
|
120
|
+
</main>
|
|
121
|
+
</body>
|
|
122
|
+
</html>
|