opsscript-gate 0.1.2__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.1.2/.gitattributes +9 -0
- opsscript_gate-0.1.2/.github/ISSUE_TEMPLATE/bug_report.yml +41 -0
- opsscript_gate-0.1.2/.github/ISSUE_TEMPLATE/distro_request.yml +33 -0
- opsscript_gate-0.1.2/.github/ISSUE_TEMPLATE/feature_request.yml +33 -0
- opsscript_gate-0.1.2/.github/assets/social-preview.png +0 -0
- opsscript_gate-0.1.2/.github/pull_request_template.md +18 -0
- opsscript_gate-0.1.2/.github/workflows/demo.yml +55 -0
- opsscript_gate-0.1.2/.github/workflows/release.yml +121 -0
- opsscript_gate-0.1.2/.github/workflows/test.yml +28 -0
- opsscript_gate-0.1.2/.gitignore +52 -0
- opsscript_gate-0.1.2/CHANGELOG.md +43 -0
- opsscript_gate-0.1.2/CONTRIBUTING.md +82 -0
- opsscript_gate-0.1.2/LICENSE +21 -0
- opsscript_gate-0.1.2/PKG-INFO +246 -0
- opsscript_gate-0.1.2/README.md +218 -0
- opsscript_gate-0.1.2/ROADMAP.md +33 -0
- opsscript_gate-0.1.2/SECURITY.md +35 -0
- opsscript_gate-0.1.2/action.yml +46 -0
- opsscript_gate-0.1.2/examples/alpine-incompatibility/README.md +18 -0
- opsscript_gate-0.1.2/examples/alpine-incompatibility/apt_dependency.sh +10 -0
- opsscript_gate-0.1.2/examples/basic/README.md +13 -0
- opsscript_gate-0.1.2/examples/basic/clean_setup.sh +19 -0
- opsscript_gate-0.1.2/examples/github-actions/README.md +5 -0
- opsscript_gate-0.1.2/examples/github-actions/workflow.yml +25 -0
- opsscript_gate-0.1.2/examples/interactive-hang/README.md +15 -0
- opsscript_gate-0.1.2/examples/interactive-hang/prompt_confirm.sh +12 -0
- opsscript_gate-0.1.2/pyproject.toml +65 -0
- opsscript_gate-0.1.2/src/opsscript_gate/__init__.py +4 -0
- opsscript_gate-0.1.2/src/opsscript_gate/cli.py +129 -0
- opsscript_gate-0.1.2/src/opsscript_gate/models.py +55 -0
- opsscript_gate-0.1.2/src/opsscript_gate/reporter.py +158 -0
- opsscript_gate-0.1.2/src/opsscript_gate/runner.py +292 -0
- opsscript_gate-0.1.2/tests/fixtures/fail_deps.sh +9 -0
- opsscript_gate-0.1.2/tests/fixtures/fail_hang.sh +21 -0
- opsscript_gate-0.1.2/tests/fixtures/pass_basic.sh +26 -0
- opsscript_gate-0.1.2/tests/test_runner.py +456 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
name: Bug Report
|
|
2
|
+
description: File an issue about an unexpected failure or compatibility bug in opsscript-gate
|
|
3
|
+
title: "[BUG] "
|
|
4
|
+
labels: ["bug"]
|
|
5
|
+
body:
|
|
6
|
+
- type: markdown
|
|
7
|
+
attributes:
|
|
8
|
+
value: |
|
|
9
|
+
Thanks for taking the time to report an issue! Please provide as much detail as possible.
|
|
10
|
+
- type: textarea
|
|
11
|
+
id: description
|
|
12
|
+
attributes:
|
|
13
|
+
label: Bug Description
|
|
14
|
+
description: A clear and concise description of what happened.
|
|
15
|
+
placeholder: What went wrong?
|
|
16
|
+
validations:
|
|
17
|
+
required: true
|
|
18
|
+
- type: textarea
|
|
19
|
+
id: script
|
|
20
|
+
attributes:
|
|
21
|
+
label: Reproducible Shell Script
|
|
22
|
+
description: Provide a minimal shell script snippet reproducing the issue.
|
|
23
|
+
render: bash
|
|
24
|
+
validations:
|
|
25
|
+
required: true
|
|
26
|
+
- type: textarea
|
|
27
|
+
id: logs
|
|
28
|
+
attributes:
|
|
29
|
+
label: Output / Failure Diagnostics
|
|
30
|
+
description: Terminal output or GitHub Actions step summary.
|
|
31
|
+
render: text
|
|
32
|
+
validations:
|
|
33
|
+
required: true
|
|
34
|
+
- type: input
|
|
35
|
+
id: environment
|
|
36
|
+
attributes:
|
|
37
|
+
label: Environment Info
|
|
38
|
+
description: Operating system, Docker version, Python version, opsscript-gate version.
|
|
39
|
+
placeholder: Ubuntu 24.04, Docker 27.2, Python 3.12, opsscript-gate 0.1.1
|
|
40
|
+
validations:
|
|
41
|
+
required: false
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
name: Distribution Support Request
|
|
2
|
+
description: Request adding a new Linux distribution or version to the default matrix
|
|
3
|
+
title: "[DISTRO] Support "
|
|
4
|
+
labels: ["distro-matrix"]
|
|
5
|
+
body:
|
|
6
|
+
- type: markdown
|
|
7
|
+
attributes:
|
|
8
|
+
value: |
|
|
9
|
+
Suggesting a new Linux distribution? Please ensure an official public image exists and boots without interactive init.
|
|
10
|
+
- type: input
|
|
11
|
+
id: distro_image
|
|
12
|
+
attributes:
|
|
13
|
+
label: Proposed Docker Image
|
|
14
|
+
description: The official public container image tag.
|
|
15
|
+
placeholder: e.g. fedora:40, rockylinux:9
|
|
16
|
+
validations:
|
|
17
|
+
required: true
|
|
18
|
+
- type: textarea
|
|
19
|
+
id: use_case
|
|
20
|
+
attributes:
|
|
21
|
+
label: Rationale & Use Case
|
|
22
|
+
description: Why is testing this distribution valuable for production ops scripts?
|
|
23
|
+
validations:
|
|
24
|
+
required: true
|
|
25
|
+
- type: checkboxes
|
|
26
|
+
id: checks
|
|
27
|
+
attributes:
|
|
28
|
+
label: Distribution Compatibility Checklist
|
|
29
|
+
options:
|
|
30
|
+
- label: Image provides a standard POSIX /bin/sh.
|
|
31
|
+
required: true
|
|
32
|
+
- label: Container starts without systemd or interactive configuration.
|
|
33
|
+
required: true
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
name: Feature Request
|
|
2
|
+
description: Suggest an idea or architectural improvement for opsscript-gate
|
|
3
|
+
title: "[FEATURE] "
|
|
4
|
+
labels: ["enhancement"]
|
|
5
|
+
body:
|
|
6
|
+
- type: markdown
|
|
7
|
+
attributes:
|
|
8
|
+
value: |
|
|
9
|
+
We appreciate feature suggestions! Please note our security boundaries: no privileged containers, read-only script mounts, and timeouts.
|
|
10
|
+
- type: textarea
|
|
11
|
+
id: problem
|
|
12
|
+
attributes:
|
|
13
|
+
label: Problem Statement
|
|
14
|
+
description: What problem are you trying to solve?
|
|
15
|
+
validations:
|
|
16
|
+
required: true
|
|
17
|
+
- type: textarea
|
|
18
|
+
id: solution
|
|
19
|
+
attributes:
|
|
20
|
+
label: Proposed Solution
|
|
21
|
+
description: Describe your proposed change or command option.
|
|
22
|
+
validations:
|
|
23
|
+
required: true
|
|
24
|
+
- type: checkboxes
|
|
25
|
+
id: security_check
|
|
26
|
+
attributes:
|
|
27
|
+
label: Security Assessment
|
|
28
|
+
description: Please verify that this proposal adheres to unprivileged runtime boundaries.
|
|
29
|
+
options:
|
|
30
|
+
- label: Does NOT require container privilege or root access on the host.
|
|
31
|
+
required: true
|
|
32
|
+
- label: Respects timeouts and non-interactive execution.
|
|
33
|
+
required: true
|
|
Binary file
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
## Description
|
|
2
|
+
|
|
3
|
+
Briefly describe the change and the motivation behind it.
|
|
4
|
+
|
|
5
|
+
## Changes Made
|
|
6
|
+
-
|
|
7
|
+
|
|
8
|
+
## Runner Safety Verification
|
|
9
|
+
Please check all that apply:
|
|
10
|
+
- [ ] Unprivileged mode maintained (`privileged=False`)
|
|
11
|
+
- [ ] Capabilities drop maintained (`cap_drop=["ALL"]`)
|
|
12
|
+
- [ ] `no-new-privileges:true` maintained
|
|
13
|
+
- [ ] Target scripts remain mounted read-only (`:ro`)
|
|
14
|
+
- [ ] Timeout and container cleanup logic preserved
|
|
15
|
+
|
|
16
|
+
## Testing
|
|
17
|
+
- [ ] Unit tests added/updated (`pytest -v -m "not integration"`)
|
|
18
|
+
- [ ] All tests passing locally
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
name: Demo Shell Script Compatibility Gate
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [ main ]
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
compatibility-demo:
|
|
10
|
+
name: Cross-Distro Compatibility Demos
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
steps:
|
|
13
|
+
- name: Checkout repository
|
|
14
|
+
uses: actions/checkout@v7
|
|
15
|
+
|
|
16
|
+
# Scenario 1: Fully compatible POSIX script passes on all 4 distributions
|
|
17
|
+
- name: "Scenario 1: POSIX script verification (Expect: ALL PASS)"
|
|
18
|
+
uses: ./
|
|
19
|
+
with:
|
|
20
|
+
script-path: 'tests/fixtures/pass_basic.sh'
|
|
21
|
+
matrix: 'debian:12-slim,ubuntu:22.04,ubuntu:24.04,alpine:3.20'
|
|
22
|
+
timeout: '30'
|
|
23
|
+
format: 'table'
|
|
24
|
+
|
|
25
|
+
# Scenario 2: Alpine catches missing apt-get dependency (exit 127 intercepted)
|
|
26
|
+
- name: "Scenario 2: Missing dependency interception (Expect: Alpine FAIL 127)"
|
|
27
|
+
id: demo_fail_deps
|
|
28
|
+
continue-on-error: true
|
|
29
|
+
uses: ./
|
|
30
|
+
with:
|
|
31
|
+
script-path: 'tests/fixtures/fail_deps.sh'
|
|
32
|
+
matrix: 'debian:12-slim,ubuntu:22.04,ubuntu:24.04,alpine:3.20'
|
|
33
|
+
timeout: '30'
|
|
34
|
+
format: 'table'
|
|
35
|
+
|
|
36
|
+
- name: Verify Scenario 2 Interception
|
|
37
|
+
if: steps.demo_fail_deps.outcome == 'failure'
|
|
38
|
+
run: |
|
|
39
|
+
echo "::notice title=Interception Verified::Successfully caught missing apt-get on Alpine (Exit code 127 intercepted)!"
|
|
40
|
+
|
|
41
|
+
# Scenario 3: Script waiting for interactive input terminated immediately by /dev/null
|
|
42
|
+
- name: "Scenario 3: Interactive hang defense (Expect: /dev/null EOF failure intercepted)"
|
|
43
|
+
id: demo_fail_hang
|
|
44
|
+
continue-on-error: true
|
|
45
|
+
uses: ./
|
|
46
|
+
with:
|
|
47
|
+
script-path: 'tests/fixtures/fail_hang.sh'
|
|
48
|
+
matrix: 'alpine:3.20'
|
|
49
|
+
timeout: '15'
|
|
50
|
+
format: 'table'
|
|
51
|
+
|
|
52
|
+
- name: Verify Scenario 3 Interception
|
|
53
|
+
if: steps.demo_fail_hang.outcome == 'failure'
|
|
54
|
+
run: |
|
|
55
|
+
echo "::notice title=Anti-Hang Verified::Interactive prompt prevented from hanging CI by automatic /dev/null redirection!"
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
name: Build and Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- 'v*'
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
contents: read
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
test:
|
|
14
|
+
name: Run Test Suite
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
steps:
|
|
17
|
+
- name: Checkout Code
|
|
18
|
+
uses: actions/checkout@v7
|
|
19
|
+
|
|
20
|
+
- name: Set up Python
|
|
21
|
+
uses: actions/setup-python@v7
|
|
22
|
+
with:
|
|
23
|
+
python-version: '3.12'
|
|
24
|
+
|
|
25
|
+
- name: Install Dependencies
|
|
26
|
+
run: |
|
|
27
|
+
python -m pip install --upgrade pip
|
|
28
|
+
pip install -e .[test]
|
|
29
|
+
|
|
30
|
+
- name: Run Tests
|
|
31
|
+
run: |
|
|
32
|
+
pytest -v -m "not integration"
|
|
33
|
+
|
|
34
|
+
build:
|
|
35
|
+
name: Build Distribution Packages
|
|
36
|
+
needs: test
|
|
37
|
+
runs-on: ubuntu-latest
|
|
38
|
+
permissions:
|
|
39
|
+
contents: write
|
|
40
|
+
steps:
|
|
41
|
+
- name: Checkout Code
|
|
42
|
+
uses: actions/checkout@v7
|
|
43
|
+
|
|
44
|
+
- name: Set up Python
|
|
45
|
+
uses: actions/setup-python@v7
|
|
46
|
+
with:
|
|
47
|
+
python-version: '3.12'
|
|
48
|
+
|
|
49
|
+
- name: Verify Version Consistency
|
|
50
|
+
shell: bash
|
|
51
|
+
run: |
|
|
52
|
+
TOML_VERSION=$(python -c "import tomllib; f=open('pyproject.toml', 'rb'); print(tomllib.load(f)['project']['version'])")
|
|
53
|
+
INIT_VERSION=$(python -c "import sys; sys.path.insert(0, 'src'); import opsscript_gate; print(opsscript_gate.__version__)")
|
|
54
|
+
|
|
55
|
+
echo "pyproject.toml version: $TOML_VERSION"
|
|
56
|
+
echo "opsscript_gate version: $INIT_VERSION"
|
|
57
|
+
|
|
58
|
+
if [ "$TOML_VERSION" != "$INIT_VERSION" ]; then
|
|
59
|
+
echo "::error::Version mismatch: pyproject.toml ($TOML_VERSION) != __init__.py ($INIT_VERSION)"
|
|
60
|
+
exit 1
|
|
61
|
+
fi
|
|
62
|
+
|
|
63
|
+
if [[ "${{ github.ref }}" =~ ^refs/tags/v ]]; then
|
|
64
|
+
TAG_VERSION="${GITHUB_REF_NAME#v}"
|
|
65
|
+
echo "Git tag version: $TAG_VERSION"
|
|
66
|
+
if [ "$TAG_VERSION" != "$TOML_VERSION" ]; then
|
|
67
|
+
echo "::error::Tag mismatch: Git tag v$TAG_VERSION does not match project version $TOML_VERSION"
|
|
68
|
+
exit 1
|
|
69
|
+
fi
|
|
70
|
+
fi
|
|
71
|
+
|
|
72
|
+
echo "Version consistency verified: $TOML_VERSION"
|
|
73
|
+
|
|
74
|
+
- name: Install build tools
|
|
75
|
+
run: |
|
|
76
|
+
python -m pip install --upgrade pip
|
|
77
|
+
pip install build twine
|
|
78
|
+
|
|
79
|
+
- name: Build sdist and wheel
|
|
80
|
+
run: |
|
|
81
|
+
python -m build
|
|
82
|
+
|
|
83
|
+
- name: Verify Package Metadata
|
|
84
|
+
run: |
|
|
85
|
+
python -m twine check dist/*
|
|
86
|
+
|
|
87
|
+
- name: Upload dist artifacts
|
|
88
|
+
uses: actions/upload-artifact@v4
|
|
89
|
+
with:
|
|
90
|
+
name: dist
|
|
91
|
+
path: dist/
|
|
92
|
+
retention-days: 7
|
|
93
|
+
|
|
94
|
+
- name: Create GitHub Release and Upload Assets
|
|
95
|
+
uses: softprops/action-gh-release@v2
|
|
96
|
+
if: startsWith(github.ref, 'refs/tags/v')
|
|
97
|
+
with:
|
|
98
|
+
files: dist/*
|
|
99
|
+
generate_release_notes: true
|
|
100
|
+
|
|
101
|
+
publish-pypi:
|
|
102
|
+
name: Publish to PyPI via OIDC
|
|
103
|
+
needs: [test, build]
|
|
104
|
+
if: startsWith(github.ref, 'refs/tags/v')
|
|
105
|
+
runs-on: ubuntu-latest
|
|
106
|
+
environment:
|
|
107
|
+
name: pypi
|
|
108
|
+
url: https://pypi.org/p/opsscript-gate
|
|
109
|
+
permissions:
|
|
110
|
+
id-token: write
|
|
111
|
+
steps:
|
|
112
|
+
- name: Download dist artifacts
|
|
113
|
+
uses: actions/download-artifact@v4
|
|
114
|
+
with:
|
|
115
|
+
name: dist
|
|
116
|
+
path: dist
|
|
117
|
+
|
|
118
|
+
- name: Publish package distributions to PyPI
|
|
119
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
120
|
+
with:
|
|
121
|
+
packages-dir: dist/
|
|
@@ -0,0 +1,28 @@
|
|
|
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"
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# Distribution / packaging
|
|
7
|
+
.Python
|
|
8
|
+
build/
|
|
9
|
+
develop-eggs/
|
|
10
|
+
dist/
|
|
11
|
+
downloads/
|
|
12
|
+
eggs/
|
|
13
|
+
.eggs/
|
|
14
|
+
lib/
|
|
15
|
+
lib64/
|
|
16
|
+
parts/
|
|
17
|
+
sdist/
|
|
18
|
+
var/
|
|
19
|
+
wheels/
|
|
20
|
+
share/python-wheels/
|
|
21
|
+
*.egg-info/
|
|
22
|
+
.installed.cfg
|
|
23
|
+
*.egg
|
|
24
|
+
MANIFEST
|
|
25
|
+
|
|
26
|
+
# Pytest / Test / Coverage
|
|
27
|
+
.pytest_cache/
|
|
28
|
+
.coverage
|
|
29
|
+
.coverage.*
|
|
30
|
+
.cache
|
|
31
|
+
nosetests.xml
|
|
32
|
+
coverage.xml
|
|
33
|
+
*.cover
|
|
34
|
+
*.log
|
|
35
|
+
|
|
36
|
+
# Environments
|
|
37
|
+
.env
|
|
38
|
+
.venv
|
|
39
|
+
env/
|
|
40
|
+
venv/
|
|
41
|
+
ENV/
|
|
42
|
+
env.bak/
|
|
43
|
+
venv.bak/
|
|
44
|
+
|
|
45
|
+
# IDE & OS files
|
|
46
|
+
.vscode/
|
|
47
|
+
.idea/
|
|
48
|
+
*.swp
|
|
49
|
+
*.swo
|
|
50
|
+
*~
|
|
51
|
+
.DS_Store
|
|
52
|
+
Thumbs.db
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [0.1.2] - 2026-09-18
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- Configured PyPI Trusted Publishing via GitHub Actions OIDC (`pypa/gh-action-pypi-publish`).
|
|
12
|
+
- Added full PyPI package metadata, classifiers, and project URLs to `pyproject.toml`.
|
|
13
|
+
- Ensured absolute asset URLs in `README.md` for seamless PyPI rendering.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## [0.1.1] - 2026-09-18
|
|
18
|
+
|
|
19
|
+
### Added
|
|
20
|
+
- Created `examples/` directory showcasing basic setup, Alpine package manager incompatibility, and interactive hang prevention.
|
|
21
|
+
- Added GitHub Issue templates for bug reports, feature requests, and distribution support requests.
|
|
22
|
+
- Added `CONTRIBUTING.md`, `SECURITY.md`, and `ROADMAP.md`.
|
|
23
|
+
- Enforced `security_opt=["no-new-privileges:true"]` on all container executions.
|
|
24
|
+
|
|
25
|
+
### Fixed
|
|
26
|
+
- Upgraded GitHub Actions dependencies to `actions/checkout@v7` and `actions/setup-python@v7` (Node 24 runtime).
|
|
27
|
+
- Fixed secret referencing syntax in release workflow to ensure reliable binary asset uploads.
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## [0.1.0] - 2026-09-18
|
|
32
|
+
|
|
33
|
+
### Added
|
|
34
|
+
- Initial MVP release of `opsscript-gate`.
|
|
35
|
+
- CLI entrypoint (`opsscript-gate run <script_path>`).
|
|
36
|
+
- Unprivileged container isolation engine supporting `debian:12-slim`, `ubuntu:22.04`, `ubuntu:24.04`, and `alpine:3.20`.
|
|
37
|
+
- Safe read-only script mounting (`:ro`).
|
|
38
|
+
- Hard per-container timeout with forced `SIGKILL` and cleanup.
|
|
39
|
+
- Stdin disconnection (`</dev/null`) and non-interactive environment enforcement.
|
|
40
|
+
- Windows CRLF line-ending normalization defense.
|
|
41
|
+
- Unified ASCII table, GitHub Actions Step Summary Markdown, and JSON reporting formats.
|
|
42
|
+
- Composite GitHub Action published to Marketplace.
|
|
43
|
+
- Unit and integration test suite.
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# Contributing to OpsScript Gate
|
|
2
|
+
|
|
3
|
+
Thank you for your interest in contributing to **OpsScript Gate**! We welcome bug reports, compatibility test fixtures, feature suggestions, and pull requests.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Development Setup
|
|
8
|
+
|
|
9
|
+
OpsScript Gate requires **Python 3.10+** and a standard virtual environment.
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
# Clone the repository
|
|
13
|
+
git clone https://github.com/Mresyzz/opsscript-gate.git
|
|
14
|
+
cd opsscript-gate
|
|
15
|
+
|
|
16
|
+
# Create and activate virtual environment
|
|
17
|
+
python -m venv .venv
|
|
18
|
+
source .venv/bin/activate # On Windows: .venv\Scripts\activate
|
|
19
|
+
|
|
20
|
+
# Install package in editable mode with test dependencies
|
|
21
|
+
pip install -e .[test]
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Running Tests
|
|
27
|
+
|
|
28
|
+
The test suite separates mocked unit tests from Docker integration tests:
|
|
29
|
+
- **Unit tests**: Use mocking and do not require a running Docker daemon.
|
|
30
|
+
- **Integration tests**: Labeled with `@pytest.mark.integration` and run against real Docker containers.
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
# Run unit tests (recommended for daily development)
|
|
34
|
+
pytest -v -m "not integration"
|
|
35
|
+
|
|
36
|
+
# Run full test suite including live Docker integration tests
|
|
37
|
+
pytest -v
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Pull requests should pass the unit test suite.
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Runner safety constraints
|
|
45
|
+
|
|
46
|
+
Any changes affecting the container runner should preserve these constraints:
|
|
47
|
+
|
|
48
|
+
1. **Unprivileged execution**:
|
|
49
|
+
- Containers must not run with `privileged=True`.
|
|
50
|
+
- `cap_drop` must remain `["ALL"]`.
|
|
51
|
+
- `security_opt` must include `["no-new-privileges:true"]`.
|
|
52
|
+
2. **Read-only script mount**:
|
|
53
|
+
- Target scripts must remain read-only (`:ro`).
|
|
54
|
+
- Do not mount additional host filesystem paths into test containers.
|
|
55
|
+
3. **Timeout & cleanup**:
|
|
56
|
+
- Containers reaching timeout limits should be terminated with `container.kill()`.
|
|
57
|
+
- Container removal in `finally` blocks must be preserved.
|
|
58
|
+
4. **Non-interactive execution**:
|
|
59
|
+
- Standard input should remain detached (`stdin_open=False`, `tty=False`, `</dev/null`).
|
|
60
|
+
- Keep non-interactive environment variables (`DEBIAN_FRONTEND=noninteractive`, `CI=true`).
|
|
61
|
+
5. **Scope**:
|
|
62
|
+
- Avoid emulating complex init systems (like systemd) inside containers; the runner focuses on standard script execution, command availability, and exit codes.
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## Adding a New Linux Distribution
|
|
67
|
+
|
|
68
|
+
To propose or add a new distribution image:
|
|
69
|
+
1. Ensure the official image is available on Docker Hub and is publicly accessible.
|
|
70
|
+
2. Confirm the image contains `/bin/sh` for minimal POSIX execution.
|
|
71
|
+
3. Add a representative compatibility test fixture in `tests/fixtures/` demonstrating standard behavior.
|
|
72
|
+
4. Ensure the image does not require interactive initialization.
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## Pull Request Workflow
|
|
77
|
+
|
|
78
|
+
1. Fork the repository and create a descriptive feature branch from `main`.
|
|
79
|
+
2. Make your modifications, adhering to standard Python formatting (PEP 8) and type hints.
|
|
80
|
+
3. Add or update unit tests in `tests/test_runner.py` verifying both success and failure paths.
|
|
81
|
+
4. Verify tests pass locally: `pytest -v -m "not integration"`.
|
|
82
|
+
5. Open a Pull Request against the `main` branch with a clear summary of changes.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 OpsScript Gate Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|