opsscript-gate 0.1.2__tar.gz → 0.2.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.
Files changed (39) hide show
  1. opsscript_gate-0.2.1/.github/workflows/test.yml +52 -0
  2. {opsscript_gate-0.1.2 → opsscript_gate-0.2.1}/CHANGELOG.md +23 -0
  3. {opsscript_gate-0.1.2 → opsscript_gate-0.2.1}/PKG-INFO +36 -5
  4. {opsscript_gate-0.1.2 → opsscript_gate-0.2.1}/README.md +35 -4
  5. {opsscript_gate-0.1.2 → opsscript_gate-0.2.1}/ROADMAP.md +2 -2
  6. {opsscript_gate-0.1.2 → opsscript_gate-0.2.1}/SECURITY.md +2 -1
  7. {opsscript_gate-0.1.2 → opsscript_gate-0.2.1}/action.yml +19 -3
  8. {opsscript_gate-0.1.2 → opsscript_gate-0.2.1}/pyproject.toml +1 -1
  9. {opsscript_gate-0.1.2 → opsscript_gate-0.2.1}/src/opsscript_gate/__init__.py +1 -1
  10. {opsscript_gate-0.1.2 → opsscript_gate-0.2.1}/src/opsscript_gate/cli.py +7 -0
  11. {opsscript_gate-0.1.2 → opsscript_gate-0.2.1}/src/opsscript_gate/models.py +7 -0
  12. opsscript_gate-0.2.1/src/opsscript_gate/runner.py +586 -0
  13. opsscript_gate-0.2.1/tests/test_runner.py +885 -0
  14. opsscript_gate-0.1.2/.github/workflows/test.yml +0 -28
  15. opsscript_gate-0.1.2/src/opsscript_gate/runner.py +0 -292
  16. opsscript_gate-0.1.2/tests/test_runner.py +0 -456
  17. {opsscript_gate-0.1.2 → opsscript_gate-0.2.1}/.gitattributes +0 -0
  18. {opsscript_gate-0.1.2 → opsscript_gate-0.2.1}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  19. {opsscript_gate-0.1.2 → opsscript_gate-0.2.1}/.github/ISSUE_TEMPLATE/distro_request.yml +0 -0
  20. {opsscript_gate-0.1.2 → opsscript_gate-0.2.1}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  21. {opsscript_gate-0.1.2 → opsscript_gate-0.2.1}/.github/assets/social-preview.png +0 -0
  22. {opsscript_gate-0.1.2 → opsscript_gate-0.2.1}/.github/pull_request_template.md +0 -0
  23. {opsscript_gate-0.1.2 → opsscript_gate-0.2.1}/.github/workflows/demo.yml +0 -0
  24. {opsscript_gate-0.1.2 → opsscript_gate-0.2.1}/.github/workflows/release.yml +0 -0
  25. {opsscript_gate-0.1.2 → opsscript_gate-0.2.1}/.gitignore +0 -0
  26. {opsscript_gate-0.1.2 → opsscript_gate-0.2.1}/CONTRIBUTING.md +0 -0
  27. {opsscript_gate-0.1.2 → opsscript_gate-0.2.1}/LICENSE +0 -0
  28. {opsscript_gate-0.1.2 → opsscript_gate-0.2.1}/examples/alpine-incompatibility/README.md +0 -0
  29. {opsscript_gate-0.1.2 → opsscript_gate-0.2.1}/examples/alpine-incompatibility/apt_dependency.sh +0 -0
  30. {opsscript_gate-0.1.2 → opsscript_gate-0.2.1}/examples/basic/README.md +0 -0
  31. {opsscript_gate-0.1.2 → opsscript_gate-0.2.1}/examples/basic/clean_setup.sh +0 -0
  32. {opsscript_gate-0.1.2 → opsscript_gate-0.2.1}/examples/github-actions/README.md +0 -0
  33. {opsscript_gate-0.1.2 → opsscript_gate-0.2.1}/examples/github-actions/workflow.yml +0 -0
  34. {opsscript_gate-0.1.2 → opsscript_gate-0.2.1}/examples/interactive-hang/README.md +0 -0
  35. {opsscript_gate-0.1.2 → opsscript_gate-0.2.1}/examples/interactive-hang/prompt_confirm.sh +0 -0
  36. {opsscript_gate-0.1.2 → opsscript_gate-0.2.1}/src/opsscript_gate/reporter.py +0 -0
  37. {opsscript_gate-0.1.2 → opsscript_gate-0.2.1}/tests/fixtures/fail_deps.sh +0 -0
  38. {opsscript_gate-0.1.2 → opsscript_gate-0.2.1}/tests/fixtures/fail_hang.sh +0 -0
  39. {opsscript_gate-0.1.2 → opsscript_gate-0.2.1}/tests/fixtures/pass_basic.sh +0 -0
@@ -0,0 +1,52 @@
1
+ name: Test opsscript-gate
2
+
3
+ on:
4
+ push:
5
+ branches: [ main, test ]
6
+ pull_request:
7
+ branches: [ main, test ]
8
+
9
+ jobs:
10
+ test:
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - name: Checkout Code
14
+ uses: actions/checkout@v7
15
+
16
+ - name: Set up Python
17
+ uses: actions/setup-python@v7
18
+ with:
19
+ python-version: '3.12'
20
+
21
+ - name: Install Dependencies
22
+ run: |
23
+ python -m pip install --upgrade pip
24
+ pip install -e .[test]
25
+
26
+ - name: Run Pytest
27
+ run: |
28
+ pytest -v -m "not integration"
29
+
30
+ integration:
31
+ name: Docker Integration Tests
32
+ runs-on: ubuntu-latest
33
+ steps:
34
+ - name: Checkout Code
35
+ uses: actions/checkout@v7
36
+
37
+ - name: Set up Python
38
+ uses: actions/setup-python@v7
39
+ with:
40
+ python-version: '3.12'
41
+
42
+ - name: Install Dependencies
43
+ run: |
44
+ python -m pip install --upgrade pip
45
+ pip install -e .[test]
46
+
47
+ - name: Verify Docker Available
48
+ run: docker version
49
+
50
+ - name: Run Docker Integration Tests
51
+ run: |
52
+ pytest -v -m integration
@@ -5,6 +5,29 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.2.1] - 2026-09-19
9
+
10
+ ### Fixed
11
+ - Strip complete ANSI CSI and OSC escape sequences from diagnostic text instead of leaving escape-sequence residue.
12
+ - Ensure diagnostic `max_length` includes the trailing ellipsis when truncation occurs.
13
+ - Add regression coverage for ANSI sanitization and truncation edge cases.
14
+
15
+ ---
16
+
17
+ ## [0.2.0] - 2026-09-18
18
+
19
+ ### Added
20
+ - Explicit shell execution modes (`--shell posix|shebang|auto`) in CLI and GitHub Action.
21
+ - `posix` (default): Strictly executes with `/bin/sh`, ignoring any script shebang to verify portability against minimal POSIX environments.
22
+ - `shebang`: Strictly honors recognized shebang interpreters (`sh`, `bash`, `/usr/bin/env`). Fails immediately with clear diagnostics if missing, malformed, or unsupported.
23
+ - `auto`: Uses recognized shebang when present; safely falls back to `/bin/sh` if no shebang is present; rejects unsupported/malformed shebangs without silent fallback.
24
+ - Exact interpreter-path preservation using fixed trusted container command constants (`SUPPORTED_SHEBANG_COMMANDS`), preventing `$PATH` resolution from masking missing paths like `/usr/bin/bash`.
25
+ - Hardened GitHub Action input passing via step-level environment variables to eliminate shell injection risks.
26
+ - Dedicated Docker integration test job in GitHub Actions workflow verifying real container behaviors (including bash missing on Alpine 3.20).
27
+ - Sanitized shebang error diagnostics against control character injection and multiline pollution.
28
+
29
+ ---
30
+
8
31
  ## [0.1.2] - 2026-09-18
9
32
 
10
33
  ### Added
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: opsscript-gate
3
- Version: 0.1.2
3
+ Version: 0.2.1
4
4
  Summary: Run Linux shell scripts across Debian, Ubuntu and Alpine before release to catch runtime compatibility failures
5
5
  Project-URL: Homepage, https://github.com/Mresyzz/opsscript-gate
6
6
  Project-URL: Repository, https://github.com/Mresyzz/opsscript-gate
@@ -32,9 +32,10 @@ Description-Content-Type: text/markdown
32
32
 
33
33
  [![CI](https://github.com/Mresyzz/opsscript-gate/actions/workflows/test.yml/badge.svg)](https://github.com/Mresyzz/opsscript-gate/actions/workflows/test.yml)
34
34
  [![Demo](https://github.com/Mresyzz/opsscript-gate/actions/workflows/demo.yml/badge.svg)](https://github.com/Mresyzz/opsscript-gate/actions/workflows/demo.yml)
35
+ [![PyPI](https://img.shields.io/pypi/v/opsscript-gate)](https://pypi.org/project/opsscript-gate/)
36
+ [![Python Versions](https://img.shields.io/pypi/pyversions/opsscript-gate)](https://pypi.org/project/opsscript-gate/)
35
37
  [![GitHub Marketplace](https://img.shields.io/badge/Marketplace-OpsScript%20Gate-blue?logo=github&color=2088FF)](https://github.com/marketplace/actions/opsscript-gate)
36
38
  [![Release](https://img.shields.io/github/v/release/Mresyzz/opsscript-gate?color=green)](https://github.com/Mresyzz/opsscript-gate/releases)
37
- [![Python Version](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
38
39
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
39
40
  [![Supported Distros](https://img.shields.io/badge/matrix-Debian%20%7C%20Ubuntu%20%7C%20Alpine-orange.svg)](#default-test-matrix)
40
41
 
@@ -54,9 +55,10 @@ Add one step to your pull request workflow (`.github/workflows/gate.yml`):
54
55
 
55
56
  ```yaml
56
57
  - name: Verify Shell Script Portability
57
- uses: Mresyzz/opsscript-gate@v0.1.1
58
+ uses: Mresyzz/opsscript-gate@v0.2.1
58
59
  with:
59
60
  script-path: scripts/setup.sh
61
+ # shell: posix # optional: 'posix' (default), 'shebang', or 'auto'
60
62
  ```
61
63
 
62
64
  ### In Local Terminal (CLI)
@@ -64,7 +66,10 @@ Add one step to your pull request workflow (`.github/workflows/gate.yml`):
64
66
  Requires Python 3.10+ and a local Docker engine:
65
67
 
66
68
  ```bash
67
- # Install directly from GitHub
69
+ # Install from PyPI
70
+ pip install opsscript-gate
71
+
72
+ # Latest development version
68
73
  pip install git+https://github.com/Mresyzz/opsscript-gate.git
69
74
 
70
75
  # Run compatibility gate against your script
@@ -175,6 +180,7 @@ You can customize the matrix at any time via `--matrix` or Action input `matrix`
175
180
  ```text
176
181
  usage: opsscript-gate run [-h] [--matrix MATRIX] [--timeout TIMEOUT]
177
182
  [--format {table,markdown,json}]
183
+ [--shell {posix,shebang,auto}]
178
184
  script_path
179
185
  ```
180
186
 
@@ -184,9 +190,16 @@ usage: opsscript-gate run [-h] [--matrix MATRIX] [--timeout TIMEOUT]
184
190
  | `--matrix` | String | `debian:12-slim,ubuntu:22.04,ubuntu:24.04,alpine:3.20` | Comma-separated list of Docker images |
185
191
  | `--timeout` | Integer | `60` | Hard timeout per container in seconds |
186
192
  | `--format` | Choice | `table` | Output format: `table`, `markdown`, or `json` |
193
+ | `--shell` | Choice | `posix` | Execution mode: `posix` (default), `shebang`, or `auto` |
187
194
  | `--version` | Flag | - | Show version number |
188
195
  | `-h, --help` | Flag | - | Show argument help |
189
196
 
197
+ ### Shell Execution Modes (`--shell`)
198
+
199
+ - **`posix`** (default): Strictly executes with `/bin/sh`, ignoring any script shebang. Ideal for verifying that your script runs in minimal POSIX-compliant environments (e.g. Alpine BusyBox).
200
+ - **`shebang`**: Strictly honors the interpreter specified in the script's shebang (`#!/bin/sh`, `#!/bin/bash`, `#!/usr/bin/sh`, `#!/usr/bin/bash`, `#!/usr/bin/env sh`, `#!/usr/bin/env bash`). If the shebang is missing, malformed, or specifies an unsupported interpreter/flag, the check fails immediately with an error before running containers.
201
+ - **`auto`**: Honors recognized shebangs if present; falls back to `/bin/sh` if no shebang is declared. Scripts with explicit unsupported or malformed shebangs fail immediately with an error (does not silently execute as POSIX).
202
+
190
203
  ### Exit Code Convention
191
204
  - **`0`**: All distributions passed (`PASS`).
192
205
  - **`1`**: At least one distribution failed (`FAIL`), timed out (`TIMED_OUT`), or errored (`ERROR`).
@@ -204,6 +217,14 @@ Check out the [examples/](examples/) directory for self-contained, runnable scen
204
217
 
205
218
  ---
206
219
 
220
+ ## Dogfooding
221
+
222
+ OpsScript Gate is used in [`Mresyzz/linux-dev-bootstrap`](https://github.com/Mresyzz/linux-dev-bootstrap) to validate its `install.sh` script across the default Debian, Ubuntu, and Alpine matrix in GitHub Actions. That workflow pins `Mresyzz/opsscript-gate@v0.2.0` with `shell: auto`.
223
+
224
+ See the downstream workflow: [`.github/workflows/test.yml`](https://github.com/Mresyzz/linux-dev-bootstrap/blob/main/.github/workflows/test.yml).
225
+
226
+ ---
227
+
207
228
  ## Development & Testing
208
229
 
209
230
  The test suite uses Docker SDK mocking to ensure fast unit tests without needing a local daemon:
@@ -223,10 +244,20 @@ pytest -v
223
244
 
224
245
  ---
225
246
 
247
+ ## Current limitations
248
+
249
+ - Requires access to a Docker daemon.
250
+ - Scripts are executed with `/bin/sh` by default; use `--shell shebang` or `--shell auto` for shebang-aware execution.
251
+ - Distribution runs are currently sequential.
252
+ - Containers use bridge networking by default.
253
+ - Failure reports currently include only a tail of captured output.
254
+ - OpsScript Gate checks runtime execution and exit status; it does not validate application-specific outcomes.
255
+
256
+ ---
257
+
226
258
  ## Roadmap
227
259
 
228
260
  See [ROADMAP.md](ROADMAP.md) for planned capabilities, including:
229
- - Shebang-aware execution modes (`--shell auto|posix|shebang`)
230
261
  - Container resource limits (`--mem-limit`, `--pids-limit`)
231
262
  - Configurable network isolation (`--network none|bridge`)
232
263
  - Parallel matrix execution
@@ -4,9 +4,10 @@
4
4
 
5
5
  [![CI](https://github.com/Mresyzz/opsscript-gate/actions/workflows/test.yml/badge.svg)](https://github.com/Mresyzz/opsscript-gate/actions/workflows/test.yml)
6
6
  [![Demo](https://github.com/Mresyzz/opsscript-gate/actions/workflows/demo.yml/badge.svg)](https://github.com/Mresyzz/opsscript-gate/actions/workflows/demo.yml)
7
+ [![PyPI](https://img.shields.io/pypi/v/opsscript-gate)](https://pypi.org/project/opsscript-gate/)
8
+ [![Python Versions](https://img.shields.io/pypi/pyversions/opsscript-gate)](https://pypi.org/project/opsscript-gate/)
7
9
  [![GitHub Marketplace](https://img.shields.io/badge/Marketplace-OpsScript%20Gate-blue?logo=github&color=2088FF)](https://github.com/marketplace/actions/opsscript-gate)
8
10
  [![Release](https://img.shields.io/github/v/release/Mresyzz/opsscript-gate?color=green)](https://github.com/Mresyzz/opsscript-gate/releases)
9
- [![Python Version](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
10
11
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
11
12
  [![Supported Distros](https://img.shields.io/badge/matrix-Debian%20%7C%20Ubuntu%20%7C%20Alpine-orange.svg)](#default-test-matrix)
12
13
 
@@ -26,9 +27,10 @@ Add one step to your pull request workflow (`.github/workflows/gate.yml`):
26
27
 
27
28
  ```yaml
28
29
  - name: Verify Shell Script Portability
29
- uses: Mresyzz/opsscript-gate@v0.1.1
30
+ uses: Mresyzz/opsscript-gate@v0.2.1
30
31
  with:
31
32
  script-path: scripts/setup.sh
33
+ # shell: posix # optional: 'posix' (default), 'shebang', or 'auto'
32
34
  ```
33
35
 
34
36
  ### In Local Terminal (CLI)
@@ -36,7 +38,10 @@ Add one step to your pull request workflow (`.github/workflows/gate.yml`):
36
38
  Requires Python 3.10+ and a local Docker engine:
37
39
 
38
40
  ```bash
39
- # Install directly from GitHub
41
+ # Install from PyPI
42
+ pip install opsscript-gate
43
+
44
+ # Latest development version
40
45
  pip install git+https://github.com/Mresyzz/opsscript-gate.git
41
46
 
42
47
  # Run compatibility gate against your script
@@ -147,6 +152,7 @@ You can customize the matrix at any time via `--matrix` or Action input `matrix`
147
152
  ```text
148
153
  usage: opsscript-gate run [-h] [--matrix MATRIX] [--timeout TIMEOUT]
149
154
  [--format {table,markdown,json}]
155
+ [--shell {posix,shebang,auto}]
150
156
  script_path
151
157
  ```
152
158
 
@@ -156,9 +162,16 @@ usage: opsscript-gate run [-h] [--matrix MATRIX] [--timeout TIMEOUT]
156
162
  | `--matrix` | String | `debian:12-slim,ubuntu:22.04,ubuntu:24.04,alpine:3.20` | Comma-separated list of Docker images |
157
163
  | `--timeout` | Integer | `60` | Hard timeout per container in seconds |
158
164
  | `--format` | Choice | `table` | Output format: `table`, `markdown`, or `json` |
165
+ | `--shell` | Choice | `posix` | Execution mode: `posix` (default), `shebang`, or `auto` |
159
166
  | `--version` | Flag | - | Show version number |
160
167
  | `-h, --help` | Flag | - | Show argument help |
161
168
 
169
+ ### Shell Execution Modes (`--shell`)
170
+
171
+ - **`posix`** (default): Strictly executes with `/bin/sh`, ignoring any script shebang. Ideal for verifying that your script runs in minimal POSIX-compliant environments (e.g. Alpine BusyBox).
172
+ - **`shebang`**: Strictly honors the interpreter specified in the script's shebang (`#!/bin/sh`, `#!/bin/bash`, `#!/usr/bin/sh`, `#!/usr/bin/bash`, `#!/usr/bin/env sh`, `#!/usr/bin/env bash`). If the shebang is missing, malformed, or specifies an unsupported interpreter/flag, the check fails immediately with an error before running containers.
173
+ - **`auto`**: Honors recognized shebangs if present; falls back to `/bin/sh` if no shebang is declared. Scripts with explicit unsupported or malformed shebangs fail immediately with an error (does not silently execute as POSIX).
174
+
162
175
  ### Exit Code Convention
163
176
  - **`0`**: All distributions passed (`PASS`).
164
177
  - **`1`**: At least one distribution failed (`FAIL`), timed out (`TIMED_OUT`), or errored (`ERROR`).
@@ -176,6 +189,14 @@ Check out the [examples/](examples/) directory for self-contained, runnable scen
176
189
 
177
190
  ---
178
191
 
192
+ ## Dogfooding
193
+
194
+ OpsScript Gate is used in [`Mresyzz/linux-dev-bootstrap`](https://github.com/Mresyzz/linux-dev-bootstrap) to validate its `install.sh` script across the default Debian, Ubuntu, and Alpine matrix in GitHub Actions. That workflow pins `Mresyzz/opsscript-gate@v0.2.0` with `shell: auto`.
195
+
196
+ See the downstream workflow: [`.github/workflows/test.yml`](https://github.com/Mresyzz/linux-dev-bootstrap/blob/main/.github/workflows/test.yml).
197
+
198
+ ---
199
+
179
200
  ## Development & Testing
180
201
 
181
202
  The test suite uses Docker SDK mocking to ensure fast unit tests without needing a local daemon:
@@ -195,10 +216,20 @@ pytest -v
195
216
 
196
217
  ---
197
218
 
219
+ ## Current limitations
220
+
221
+ - Requires access to a Docker daemon.
222
+ - Scripts are executed with `/bin/sh` by default; use `--shell shebang` or `--shell auto` for shebang-aware execution.
223
+ - Distribution runs are currently sequential.
224
+ - Containers use bridge networking by default.
225
+ - Failure reports currently include only a tail of captured output.
226
+ - OpsScript Gate checks runtime execution and exit status; it does not validate application-specific outcomes.
227
+
228
+ ---
229
+
198
230
  ## Roadmap
199
231
 
200
232
  See [ROADMAP.md](ROADMAP.md) for planned capabilities, including:
201
- - Shebang-aware execution modes (`--shell auto|posix|shebang`)
202
233
  - Container resource limits (`--mem-limit`, `--pids-limit`)
203
234
  - Configurable network isolation (`--network none|bridge`)
204
235
  - Parallel matrix execution
@@ -9,8 +9,8 @@ This roadmap tracks features being considered for future releases.
9
9
  ## Planned Features
10
10
 
11
11
  ### 1. Execution Modes (`--shell`)
12
- - [ ] **Shebang-aware execution (`--shell shebang | auto`)**: Under consideration. Parse and honor `#!/usr/bin/env bash` or `#!/bin/bash` in distributions where Bash is present, while maintaining unprivileged container defaults.
13
- - [ ] **Explicit POSIX mode (`--shell posix`)**: Retain the current baseline of `/bin/sh` across all containers to verify portability.
12
+ - [x] **Shebang-aware execution (`--shell shebang | auto`)**: Implemented in v0.2.0. Parses and honors recognized shebang forms (`sh`, `bash`) across distributions using fixed trusted container commands.
13
+ - [x] **Explicit POSIX mode (`--shell posix`)**: Implemented in v0.2.0. Retains `/bin/sh` baseline across all containers to verify strict POSIX portability.
14
14
 
15
15
  ### 2. Resource Constraints
16
16
  - [ ] **Memory limits (`--mem-limit`)**: Planned. Constrain container memory usage for scripts under test.
@@ -6,7 +6,8 @@ Only the latest release of **OpsScript Gate** receives security updates and bug
6
6
 
7
7
  | Version | Supported |
8
8
  | :--- | :---: |
9
- | 0.1.x | :white_check_mark: |
9
+ | 0.2.x | :white_check_mark: |
10
+ | 0.1.x | :x: |
10
11
  | < 0.1.0 | :x: |
11
12
 
12
13
  ---
@@ -21,6 +21,10 @@ inputs:
21
21
  description: 'Output report format: table, markdown, or json'
22
22
  required: false
23
23
  default: 'table'
24
+ shell:
25
+ description: "Shell execution mode: 'posix' (default), 'shebang', or 'auto'"
26
+ required: false
27
+ default: 'posix'
24
28
 
25
29
  runs:
26
30
  using: 'composite'
@@ -38,9 +42,21 @@ runs:
38
42
 
39
43
  - name: Run compatibility gate
40
44
  shell: bash
45
+ env:
46
+ INPUT_SCRIPT_PATH: ${{ inputs.script-path }}
47
+ INPUT_MATRIX: ${{ inputs.matrix }}
48
+ INPUT_TIMEOUT: ${{ inputs.timeout }}
49
+ INPUT_FORMAT: ${{ inputs.format }}
50
+ INPUT_SHELL: ${{ inputs.shell }}
41
51
  run: |
42
- ARGS=("run" "${{ inputs.script-path }}" "--timeout" "${{ inputs.timeout }}" "--format" "${{ inputs.format }}")
43
- if [ -n "${{ inputs.matrix }}" ]; then
44
- ARGS+=("--matrix" "${{ inputs.matrix }}")
52
+ ARGS=(
53
+ "run"
54
+ "$INPUT_SCRIPT_PATH"
55
+ "--timeout" "$INPUT_TIMEOUT"
56
+ "--format" "$INPUT_FORMAT"
57
+ "--shell" "$INPUT_SHELL"
58
+ )
59
+ if [ -n "$INPUT_MATRIX" ]; then
60
+ ARGS+=("--matrix" "$INPUT_MATRIX")
45
61
  fi
46
62
  python -m opsscript_gate.cli "${ARGS[@]}"
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "opsscript-gate"
7
- version = "0.1.2"
7
+ version = "0.2.1"
8
8
  description = "Run Linux shell scripts across Debian, Ubuntu and Alpine before release to catch runtime compatibility failures"
9
9
  readme = "README.md"
10
10
  license = { text = "MIT" }
@@ -1,4 +1,4 @@
1
1
  """OpsScript Gate: Lightweight cross-distro compatibility pre-check for Linux ops scripts."""
2
2
 
3
- __version__ = "0.1.2"
3
+ __version__ = "0.2.1"
4
4
  __all__ = ["__version__"]
@@ -64,6 +64,12 @@ def build_parser() -> argparse.ArgumentParser:
64
64
  default="table",
65
65
  help="Output report format: 'table' (default ASCII), 'markdown', or 'json'",
66
66
  )
67
+ run_parser.add_argument(
68
+ "--shell",
69
+ choices=["posix", "shebang", "auto"],
70
+ default="posix",
71
+ help="Shell execution mode: 'posix' (default, /bin/sh), 'shebang' (honors script shebang), or 'auto' (shebang if recognized, else /bin/sh)",
72
+ )
67
73
 
68
74
  return parser
69
75
 
@@ -98,6 +104,7 @@ def main(argv: list[str] | None = None) -> int:
98
104
  script_path=script_path,
99
105
  matrix=matrix,
100
106
  timeout=args.timeout,
107
+ shell_mode=args.shell,
101
108
  )
102
109
  except DockerDaemonError as err:
103
110
  sys.stderr.write(f"Docker Error: {err}\n")
@@ -13,6 +13,13 @@ class DistroStatus(str, Enum):
13
13
  ERROR = "ERROR"
14
14
 
15
15
 
16
+ class ShellMode(str, Enum):
17
+ """Execution mode for shell scripts."""
18
+ POSIX = "posix"
19
+ SHEBANG = "shebang"
20
+ AUTO = "auto"
21
+
22
+
16
23
  @dataclass
17
24
  class SingleResult:
18
25
  """Execution result for a single Linux distribution."""