Skip to content

Commit 0d23f9a

Browse files
authored
feat: release OpsScript Gate v0.4.0 with annotations, parallel execution, and hardened runtime controls
Release OpsScript Gate v0.4.0 with a major upgrade to runtime compatibility diagnostics, GitHub Actions integration, execution performance, and container safety controls. Key changes: Add high-confidence GitHub Actions line-level annotations for runtime failures, including exact script paths and line numbers. Normalize annotation paths to repository-relative POSIX paths so annotations correctly map to pull request diffs. Add workflow-command escaping to prevent untrusted container output from injecting GitHub Actions commands. Add deterministic, distro-aware remediation hints for common compatibility failures such as apt/apk mismatches, missing Bash, missing curl/wget, and unsupported shebang interpreters. Redesign the GitHub Step Summary with a compatibility matrix, actionable diagnostics, and copyable Markdown output. Add parallel distro execution through --jobs while preserving deterministic report ordering. Add container resource controls with configurable memory limits, PID limits, and network mode. Add zero-config shell script discovery when no script path is provided. Ignore common generated and dependency directories including .git, node_modules, vendor, target, dist, build, venv, and .venv during auto-discovery. Add MultiScriptReport support for consolidated multi-script results and correct failure propagation. Optimize GitHub Action startup by removing unnecessary pip upgrade work. Refine README and SECURITY documentation to accurately describe hardened container defaults without presenting the execution environment as a complete security sandbox. Clarify that container cleanup is attempted across normal, failure, and timeout execution paths rather than making an absolute cleanup guarantee. Expand regression coverage for annotations, escaping, path normalization, discovery exclusions, parallel execution, timeouts, resource limits, and reporting. Validation: 53 unit tests passed locally. GitHub Actions test workflow passed across supported Python versions. Real Docker integration tests passed. End-to-end demo workflow passed on GitHub Actions. Verified Debian 12, Ubuntu 22.04, Ubuntu 24.04, and Alpine 3.20 compatibility reporting. Verified a real Alpine apt-get failure produces the expected line-level GitHub annotation and remediation hint. This release preserves the existing CLI and GitHub Action workflow while making OpsScript Gate faster, easier to adopt, and significantly more useful during pull request review.
2 parents 3038bff + 7e0bfca commit 0d23f9a

15 files changed

Lines changed: 1253 additions & 211 deletions

File tree

‎.github/workflows/demo.yml‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ name: Demo Shell Script Compatibility Gate
33
on:
44
push:
55
branches: [ main ]
6+
pull_request:
7+
branches: [ main ]
68
workflow_dispatch:
79

810
jobs:

‎CHANGELOG.md‎

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,30 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [0.4.0] - 2026-09-19
9+
10+
### Added
11+
- **High-confidence line-level GitHub Actions annotations**: Emits inline `::error` annotations with exact script line numbers directly on pull request file diffs.
12+
- **Workflow command injection defense**: Strictly escapes parameters (`%`, `\r`, `\n`, `:`, `,`) and message bodies (`%`, `\r`, `\n`) to eliminate command injection from unclassified container logs.
13+
- **Conservative distro-aware remediation hints**: Suggests testable, high-confidence remediation recommendations (`RemediationRule`) with conservative phrasing (`normally`, `may`, `consider`), covering:
14+
- Alpine package manager mismatches (`apt`/`apt-get` -> `apk`)
15+
- Debian/Ubuntu package manager mismatches (`apk` -> `apt-get`)
16+
- Alpine minimal missing Bash (`bash` -> consider POSIX sh or installing bash)
17+
- Missing network prerequisites (`curl`, `wget`)
18+
- Missing shebang interpreter paths.
19+
- **Re-engineered Compatibility Card**: Overhauled GitHub Actions Step Summary with an instant 5-second triage table and an expandable copy-pasteable Markdown snippet ready for PR descriptions and Issue comments.
20+
- **Parallel matrix execution (`--jobs` / `jobs`)**: Concurrently runs container checks using `ThreadPoolExecutor` (defaults to `min(2, matrix_size)`), strictly preserving matrix output order and ensuring reliable container cleanup.
21+
- **Hardened container resource limits**: Added `--mem-limit` (default: 256m) and `--pids-limit` (default: 128) flags and Action inputs to prevent runaway resource exhaustion.
22+
- **Configurable network isolation (`--network`)**: Supports `--network bridge` (default) and `--network none` for offline script execution.
23+
- **Zero-config repository script auto-discovery**: Running `opsscript-gate run` without arguments automatically discovers and validates shell scripts in the repository, ignoring directories like `.git`, `node_modules`, and `.venv`, capped at 20 scripts and 1 MB per file.
24+
- **Multi-script test consolidation (`MultiScriptReport`)**: Supports aggregate reporting and Step Summary cards when multiple scripts are evaluated in a single run.
25+
26+
### Changed
27+
- **Action initialization performance**: Removed redundant `pip install --upgrade pip` step in composite `action.yml` to minimize Action startup latency.
28+
- **Flexible Action inputs**: Made `script-path` optional in `action.yml` (triggers auto-discovery if omitted); added inputs `jobs`, `mem-limit`, `pids-limit`, and `network`.
29+
30+
---
31+
832
## [0.3.0] - 2026-09-19
933

1034
### Added

‎README.md‎

Lines changed: 125 additions & 110 deletions
Large diffs are not rendered by default.

‎ROADMAP.md‎

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,41 @@
11
# OpsScript Gate Roadmap
22

3-
This roadmap tracks features being considered for future releases.
3+
This roadmap tracks features delivered in recent releases and areas under consideration for future versions.
44

5-
> **Note:** Features listed below are planned or under consideration; they are not implemented in current releases.
5+
---
6+
7+
## Delivered in v0.4.0
8+
9+
- [x] **High-confidence Line-level GitHub Actions Annotations**: Emits safe `::error` annotations linking failure lines directly on pull request file diffs.
10+
- [x] **Distro-aware Remediation Hints**: Conservative, testable hints for Alpine vs Debian package managers, missing bash interpreters, and core utilities.
11+
- [x] **Interactive Compatibility Card & Copyable Summary**: Rich GitHub Actions Step Summary table with copy-pasteable Markdown snippets for PR/Issue triage.
12+
- [x] **Parallel Matrix Execution (`--jobs` / `jobs`)**: Concurrent multi-container testing via `ThreadPoolExecutor` with strict matrix order preservation.
13+
- [x] **Hardened Resource Limits**: Added `--mem-limit` (default: 256m) and `--pids-limit` (default: 128) container controls.
14+
- [x] **Configurable Network Isolation (`--network none|bridge`)**: Run scripts offline when network access is not required.
15+
- [x] **Zero-Config Script Auto-Discovery**: Automatically discovers candidate shell scripts in repository root when `script_path` is omitted.
16+
- [x] **Composite Action Initialization Optimization**: Stripped redundant pip upgrade steps for rapid Action startup.
617

718
---
819

9-
## Planned Features
20+
## Delivered in v0.2.0 - v0.3.0
1021

11-
### 1. Execution Modes (`--shell`)
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.
22+
- [x] **Structured Runtime Failure Diagnostics**: Detects "command not found" errors with exit code 127 validation (v0.3.0).
23+
- [x] **Shebang-aware execution (`--shell shebang | auto`)**: Parses and honors recognized shebang forms (`sh`, `bash`) across distributions using fixed trusted container commands (v0.2.0).
24+
- [x] **Explicit POSIX mode (`--shell posix`)**: Retains `/bin/sh` baseline across all containers to verify strict POSIX portability (v0.2.0).
25+
26+
---
1427

15-
### 2. Resource Constraints
16-
- [ ] **Memory limits (`--mem-limit`)**: Planned. Constrain container memory usage for scripts under test.
17-
- [ ] **PID limits (`--pids-limit`)**: Under consideration. Guard against fork bombs within the timeout window.
28+
## Planned for Future Releases (v0.5.0+)
1829

19-
### 3. Network Isolation
20-
- [ ] **Offline execution (`--network none`)**: Planned. Run verification without network access for scripts that should not require network connectivity.
30+
### 1. Matrix & Distribution Presets
31+
- [ ] **RPM-based distributions**: Evaluate support for Enterprise Linux baselines (e.g. Rocky Linux 9, AlmaLinux, Fedora).
32+
- [ ] **Matrix presets**: Predefined profiles (e.g. `--preset minimal`, `--preset enterprise`, `--preset all`).
2133

22-
### 4. Matrix & Distribution Presets
23-
- [ ] **Additional distributions**: Under evaluation (e.g. Rocky Linux, Fedora).
24-
- [ ] **Parallel container execution**: Under consideration to reduce execution time on multi-core runners.
34+
### 2. Performance & Caching
35+
- [ ] **Docker image pre-pull & caching action**: Optional helper step to leverage GitHub Actions cache for test container base images.
2536

26-
### 5. Tooling & CI Integration
27-
- [ ] **GitHub Workflow Problem Matchers**: Under consideration. Provide inline annotations on pull request diffs for failure lines.
37+
### 3. Pre-run Setup Hooks
38+
- [ ] **Script prerequisites hook**: Declarative environment setup (e.g. install custom apt packages before testing the target script).
2839

2940
---
3041

‎SECURITY.md‎

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ Only the latest release of **OpsScript Gate** receives security updates and bug
66

77
| Version | Supported |
88
| :--- | :---: |
9-
| 0.2.x | :white_check_mark: |
10-
| 0.1.x | :x: |
11-
| < 0.1.0 | :x: |
9+
| 0.4.x | :white_check_mark: |
10+
| 0.3.x | :white_check_mark: |
11+
| < 0.3.0 | :x: |
1212

1313
---
1414

@@ -34,5 +34,7 @@ OpsScript Gate is not a security sandbox for untrusted code. Containers may run
3434

3535
OpsScript Gate applies conservative container defaults when running scripts:
3636
- **Restricted Container Defaults**: Containers run with `privileged=False`, `cap_drop=["ALL"]`, and `security_opt=["no-new-privileges:true"]`.
37+
- **Resource Limits & Isolation**: Enforces memory caps (`--mem-limit`, default 256m), process table caps (`--pids-limit`, default 128), and optional network isolation (`--network none`).
3738
- **Read-Only Mounting**: Target scripts are mounted read-only (`:ro`). OpsScript Gate does not mount additional host filesystem paths into test containers.
38-
- **Resource Protection**: Containers are subject to timeouts and `SIGKILL` termination. Container removal is attempted from a `finally` block during normal Python execution paths, including failures and timeouts.
39+
- **Resource Protection & Hard Timeout**: Containers are subject to hard timeouts (default 60s) with `SIGKILL` termination. Container removal is attempted from a `finally` block in normal, failure, and timeout execution paths.
40+
- **Workflow Command Injection Defense**: All GitHub Actions workflow commands (`::error`) apply strict percent-encoding for properties (`%`, `\r`, `\n`, `:`, `,`) and data (`%`, `\r`, `\n`), completely preventing command injection from unclassified container output.

‎action.yml‎

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,17 @@ branding:
77

88
inputs:
99
script-path:
10-
description: 'Path to the target shell script to test'
11-
required: true
10+
description: 'Path to the target shell script to test (auto-discovers repository scripts if omitted)'
11+
required: false
12+
default: ''
1213
matrix:
1314
description: 'Comma-separated container images to test (e.g. debian:12-slim,ubuntu:22.04,ubuntu:24.04,alpine:3.20)'
1415
required: false
1516
default: 'debian:12-slim,ubuntu:22.04,ubuntu:24.04,alpine:3.20'
17+
jobs:
18+
description: 'Number of parallel container execution jobs (default: min(2, matrix_size))'
19+
required: false
20+
default: ''
1621
timeout:
1722
description: 'Hard timeout in seconds per container (default: 60)'
1823
required: false
@@ -25,6 +30,18 @@ inputs:
2530
description: "Shell execution mode: 'posix' (default), 'shebang', or 'auto'"
2631
required: false
2732
default: 'posix'
33+
mem-limit:
34+
description: 'Memory limit for containers (default: 256m)'
35+
required: false
36+
default: '256m'
37+
pids-limit:
38+
description: 'Maximum number of processes per container (default: 128)'
39+
required: false
40+
default: '128'
41+
network:
42+
description: "Container network mode: 'bridge' or 'none' (default: bridge)"
43+
required: false
44+
default: 'bridge'
2845

2946
runs:
3047
using: 'composite'
@@ -37,26 +54,37 @@ runs:
3754
- name: Install opsscript-gate
3855
shell: bash
3956
run: |
40-
python -m pip install --upgrade pip
4157
pip install "${{ github.action_path }}"
4258
4359
- name: Run compatibility gate
4460
shell: bash
4561
env:
4662
INPUT_SCRIPT_PATH: ${{ inputs.script-path }}
4763
INPUT_MATRIX: ${{ inputs.matrix }}
64+
INPUT_JOBS: ${{ inputs.jobs }}
4865
INPUT_TIMEOUT: ${{ inputs.timeout }}
4966
INPUT_FORMAT: ${{ inputs.format }}
5067
INPUT_SHELL: ${{ inputs.shell }}
68+
INPUT_MEM_LIMIT: ${{ inputs.mem-limit }}
69+
INPUT_PIDS_LIMIT: ${{ inputs.pids-limit }}
70+
INPUT_NETWORK: ${{ inputs.network }}
5171
run: |
52-
ARGS=(
53-
"run"
54-
"$INPUT_SCRIPT_PATH"
72+
ARGS=("run")
73+
if [ -n "$INPUT_SCRIPT_PATH" ]; then
74+
ARGS+=("$INPUT_SCRIPT_PATH")
75+
fi
76+
ARGS+=(
5577
"--timeout" "$INPUT_TIMEOUT"
5678
"--format" "$INPUT_FORMAT"
5779
"--shell" "$INPUT_SHELL"
80+
"--mem-limit" "$INPUT_MEM_LIMIT"
81+
"--pids-limit" "$INPUT_PIDS_LIMIT"
82+
"--network" "$INPUT_NETWORK"
5883
)
5984
if [ -n "$INPUT_MATRIX" ]; then
6085
ARGS+=("--matrix" "$INPUT_MATRIX")
6186
fi
87+
if [ -n "$INPUT_JOBS" ]; then
88+
ARGS+=("--jobs" "$INPUT_JOBS")
89+
fi
6290
python -m opsscript_gate.cli "${ARGS[@]}"

‎pyproject.toml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
44

55
[project]
66
name = "opsscript-gate"
7-
version = "0.3.0"
7+
version = "0.4.0"
88
description = "Run Linux shell scripts across Debian, Ubuntu and Alpine before release to catch runtime compatibility failures"
99
readme = "README.md"
1010
license = { text = "MIT" }

‎src/opsscript_gate/__init__.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
"""OpsScript Gate: Lightweight cross-distro compatibility pre-check for Linux ops scripts."""
22

3-
__version__ = "0.3.0"
3+
__version__ = "0.4.0"
44
__all__ = ["__version__"]

0 commit comments

Comments
 (0)