opsscript-gate 0.6.1__tar.gz → 0.6.3__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 (48) hide show
  1. {opsscript_gate-0.6.1 → opsscript_gate-0.6.3}/.github/workflow-templates/opsscript-gate.yml +3 -3
  2. {opsscript_gate-0.6.1 → opsscript_gate-0.6.3}/CHANGELOG.md +16 -0
  3. {opsscript_gate-0.6.1 → opsscript_gate-0.6.3}/CITATION.cff +2 -2
  4. {opsscript_gate-0.6.1 → opsscript_gate-0.6.3}/PKG-INFO +18 -7
  5. {opsscript_gate-0.6.1 → opsscript_gate-0.6.3}/README.md +14 -4
  6. {opsscript_gate-0.6.1 → opsscript_gate-0.6.3}/README.zh-CN.md +11 -4
  7. {opsscript_gate-0.6.1 → opsscript_gate-0.6.3}/action.yml +1 -1
  8. {opsscript_gate-0.6.1 → opsscript_gate-0.6.3}/docs/configuration.md +7 -3
  9. {opsscript_gate-0.6.1 → opsscript_gate-0.6.3}/docs/gpt-oss.md +1 -1
  10. {opsscript_gate-0.6.1 → opsscript_gate-0.6.3}/examples/github-actions/README.md +1 -1
  11. {opsscript_gate-0.6.1 → opsscript_gate-0.6.3}/examples/github-actions/workflow.yml +1 -1
  12. {opsscript_gate-0.6.1 → opsscript_gate-0.6.3}/pyproject.toml +7 -2
  13. {opsscript_gate-0.6.1 → opsscript_gate-0.6.3}/src/opsscript_gate/__init__.py +1 -1
  14. {opsscript_gate-0.6.1 → opsscript_gate-0.6.3}/src/opsscript_gate/cli.py +43 -0
  15. {opsscript_gate-0.6.1 → opsscript_gate-0.6.3}/src/opsscript_gate/config.py +1 -1
  16. {opsscript_gate-0.6.1 → opsscript_gate-0.6.3}/tests/test_onboarding.py +22 -0
  17. {opsscript_gate-0.6.1 → opsscript_gate-0.6.3}/.gitattributes +0 -0
  18. {opsscript_gate-0.6.1 → opsscript_gate-0.6.3}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  19. {opsscript_gate-0.6.1 → opsscript_gate-0.6.3}/.github/ISSUE_TEMPLATE/distro_request.yml +0 -0
  20. {opsscript_gate-0.6.1 → opsscript_gate-0.6.3}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  21. {opsscript_gate-0.6.1 → opsscript_gate-0.6.3}/.github/assets/social-preview.png +0 -0
  22. {opsscript_gate-0.6.1 → opsscript_gate-0.6.3}/.github/pull_request_template.md +0 -0
  23. {opsscript_gate-0.6.1 → opsscript_gate-0.6.3}/.github/workflow-templates/properties.json +0 -0
  24. {opsscript_gate-0.6.1 → opsscript_gate-0.6.3}/.github/workflows/demo.yml +0 -0
  25. {opsscript_gate-0.6.1 → opsscript_gate-0.6.3}/.github/workflows/release.yml +0 -0
  26. {opsscript_gate-0.6.1 → opsscript_gate-0.6.3}/.github/workflows/test.yml +0 -0
  27. {opsscript_gate-0.6.1 → opsscript_gate-0.6.3}/.gitignore +0 -0
  28. {opsscript_gate-0.6.1 → opsscript_gate-0.6.3}/CONTRIBUTING.md +0 -0
  29. {opsscript_gate-0.6.1 → opsscript_gate-0.6.3}/LICENSE +0 -0
  30. {opsscript_gate-0.6.1 → opsscript_gate-0.6.3}/ROADMAP.md +0 -0
  31. {opsscript_gate-0.6.1 → opsscript_gate-0.6.3}/SECURITY.md +0 -0
  32. {opsscript_gate-0.6.1 → opsscript_gate-0.6.3}/docs/troubleshooting.md +0 -0
  33. {opsscript_gate-0.6.1 → opsscript_gate-0.6.3}/examples/alpine-incompatibility/README.md +0 -0
  34. {opsscript_gate-0.6.1 → opsscript_gate-0.6.3}/examples/alpine-incompatibility/apt_dependency.sh +0 -0
  35. {opsscript_gate-0.6.1 → opsscript_gate-0.6.3}/examples/basic/README.md +0 -0
  36. {opsscript_gate-0.6.1 → opsscript_gate-0.6.3}/examples/basic/clean_setup.sh +0 -0
  37. {opsscript_gate-0.6.1 → opsscript_gate-0.6.3}/examples/interactive-hang/README.md +0 -0
  38. {opsscript_gate-0.6.1 → opsscript_gate-0.6.3}/examples/interactive-hang/prompt_confirm.sh +0 -0
  39. {opsscript_gate-0.6.1 → opsscript_gate-0.6.3}/src/opsscript_gate/discovery.py +0 -0
  40. {opsscript_gate-0.6.1 → opsscript_gate-0.6.3}/src/opsscript_gate/models.py +0 -0
  41. {opsscript_gate-0.6.1 → opsscript_gate-0.6.3}/src/opsscript_gate/remediation.py +0 -0
  42. {opsscript_gate-0.6.1 → opsscript_gate-0.6.3}/src/opsscript_gate/reporter.py +0 -0
  43. {opsscript_gate-0.6.1 → opsscript_gate-0.6.3}/src/opsscript_gate/runner.py +0 -0
  44. {opsscript_gate-0.6.1 → opsscript_gate-0.6.3}/tests/fixtures/fail_deps.sh +0 -0
  45. {opsscript_gate-0.6.1 → opsscript_gate-0.6.3}/tests/fixtures/fail_hang.sh +0 -0
  46. {opsscript_gate-0.6.1 → opsscript_gate-0.6.3}/tests/fixtures/pass_basic.sh +0 -0
  47. {opsscript_gate-0.6.1 → opsscript_gate-0.6.3}/tests/test_action_contract.py +0 -0
  48. {opsscript_gate-0.6.1 → opsscript_gate-0.6.3}/tests/test_runner.py +0 -0
@@ -6,7 +6,7 @@ on:
6
6
  - '**/*.sh'
7
7
  - '**/*.bash'
8
8
  push:
9
- branches: [main]
9
+ branches: [$default-branch]
10
10
  paths:
11
11
  - '**/*.sh'
12
12
  - '**/*.bash'
@@ -20,12 +20,12 @@ jobs:
20
20
  runs-on: ubuntu-latest
21
21
  steps:
22
22
  - name: Checkout
23
- uses: actions/checkout@v4
23
+ uses: actions/checkout@v7
24
24
  with:
25
25
  persist-credentials: false
26
26
 
27
27
  - name: Run OpsScript Gate
28
- uses: Mresyzz/opsscript-gate@v0.6.0
28
+ uses: Mresyzz/opsscript-gate@v0.6.3
29
29
  with:
30
30
  shell: auto
31
31
  network: none
@@ -1,5 +1,21 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.6.3] - 2026-10-01
4
+
5
+ ### Added
6
+ - Added `opsscript-gate doctor` to diagnose Python and Docker prerequisites before a local run.
7
+
8
+ ### Changed
9
+ - Expanded package and Marketplace keywords for shell installers, ShellCheck users, portability, and BusyBox.
10
+ - Clarified the Action description around shell installer runtime compatibility.
11
+
12
+ ## [0.6.2] - 2026-10-01
13
+
14
+ ### Changed
15
+ - Updated the published README and Action examples to the current release tag.
16
+ - Added the InstallReady browser scanner to the package homepage and project links.
17
+ - Made the starter workflow follow each repository's default branch.
18
+
3
19
  ## [0.6.1] - 2026-10-01
4
20
 
5
21
  ### Added
@@ -5,8 +5,8 @@ type: software
5
5
  authors:
6
6
  - family-names: Mresyzz
7
7
  given-names: Mresy
8
- version: 0.6.0
9
- date-released: 2026-09-30
8
+ version: 0.6.3
9
+ date-released: 2026-10-01
10
10
  repository-code: https://github.com/Mresyzz/opsscript-gate
11
11
  url: https://github.com/Mresyzz/opsscript-gate
12
12
  license: MIT
@@ -1,8 +1,9 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: opsscript-gate
3
- Version: 0.6.1
3
+ Version: 0.6.3
4
4
  Summary: Run Linux shell scripts in Debian, Ubuntu and Alpine containers to catch runtime compatibility failures before merge
5
- Project-URL: Homepage, https://github.com/Mresyzz/opsscript-gate
5
+ Project-URL: Homepage, https://mresyzz.github.io/InstallReady/
6
+ Project-URL: Demo, https://mresyzz.github.io/InstallReady/?repo=Mresyzz%2Fopsscript-gate
6
7
  Project-URL: Repository, https://github.com/Mresyzz/opsscript-gate
7
8
  Project-URL: Issues, https://github.com/Mresyzz/opsscript-gate/issues
8
9
  Project-URL: Changelog, https://github.com/Mresyzz/opsscript-gate/blob/main/CHANGELOG.md
@@ -10,7 +11,7 @@ Project-URL: Documentation, https://github.com/Mresyzz/opsscript-gate/tree/main/
10
11
  Author: Mresyzz
11
12
  License: MIT
12
13
  License-File: LICENSE
13
- Keywords: alpine,bootstrap,ci,compatibility,cross-distro,debian,devops,docker,github-actions,installer,linux,posix,shell,shellcheck-alternative,testing,ubuntu
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
14
15
  Classifier: Development Status :: 4 - Beta
15
16
  Classifier: Intended Audience :: Developers
16
17
  Classifier: Intended Audience :: System Administrators
@@ -51,9 +52,11 @@ copy the [zero-configuration workflow](.github/workflow-templates/opsscript-gate
51
52
  shell files change, uses offline containers by default, and uploads a report that can be attached to a PR.
52
53
  No account, API key, or service signup is required.
53
54
 
55
+ Try the browser scanner: [InstallReady](https://mresyzz.github.io/InstallReady/?repo=Mresyzz%2Fopsscript-gate) checks this repository without executing code or requiring a login.
56
+
54
57
  ---
55
58
 
56
- ## Current release: v0.6.0
59
+ ## Current release: v0.6.3
57
60
 
58
61
  The current release includes a project config file, a dry-run plan, presets, exclusions,
59
62
  saved reports, and changed-script selection for pull requests. The project controls
@@ -61,6 +64,7 @@ were introduced in v0.5.0; projects on v0.4.1 and earlier do not include them.
61
64
 
62
65
  ```bash
63
66
  opsscript-gate init
67
+ opsscript-gate doctor
64
68
  opsscript-gate run --dry-run
65
69
  opsscript-gate run --format json --output reports/compatibility.json
66
70
  ```
@@ -68,6 +72,7 @@ opsscript-gate run --format json --output reports/compatibility.json
68
72
  `init` creates `.opsscript-gate.json` and a GitHub Actions workflow without replacing
69
73
  existing files. Review its exclusions (`tests/*`, `examples/*`) and offline network
70
74
  default before running. No Docker is required for `init` or `--dry-run`.
75
+ Use `opsscript-gate doctor` to check Python and Docker before a real run.
71
76
 
72
77
  Useful for standalone installers, container entrypoints and release scripts that
73
78
  must work on both GNU/Linux and Alpine/BusyBox. Each script runs independently;
@@ -96,7 +101,7 @@ jobs:
96
101
  runs-on: ubuntu-latest
97
102
  steps:
98
103
  - uses: actions/checkout@v7
99
- - uses: Mresyzz/opsscript-gate@v0.6.0
104
+ - uses: Mresyzz/opsscript-gate@v0.6.3
100
105
  ```
101
106
 
102
107
  This zero-configuration form discovers shell scripts in the repository. Use
@@ -107,7 +112,7 @@ repository has a single installer. For self-hosted model installers, see the
107
112
  Or test a specific script with custom execution modes:
108
113
 
109
114
  ```yaml
110
- - uses: Mresyzz/opsscript-gate@v0.6.0
115
+ - uses: Mresyzz/opsscript-gate@v0.6.3
111
116
  with:
112
117
  script-path: scripts/install.sh
113
118
  shell: auto
@@ -138,7 +143,7 @@ unrelated scripts:
138
143
  - uses: actions/checkout@v7
139
144
  with:
140
145
  fetch-depth: 0
141
- - uses: Mresyzz/opsscript-gate@v0.6.0
146
+ - uses: Mresyzz/opsscript-gate@v0.6.3
142
147
  with:
143
148
  changed-since: ${{ github.event.pull_request.base.sha }}
144
149
  preset: minimal
@@ -350,6 +355,12 @@ Customize the matrix at any time via `--matrix` or Action input `matrix`.
350
355
 
351
356
  ## CLI reference
352
357
 
358
+ Check local prerequisites before starting containers:
359
+
360
+ ```text
361
+ opsscript-gate doctor [--format table|json]
362
+ ```
363
+
353
364
  ```text
354
365
  usage: opsscript-gate run [-h] [--matrix MATRIX] [-j JOBS] [--timeout TIMEOUT]
355
366
  [--format {table,markdown,json}]
@@ -22,9 +22,11 @@ copy the [zero-configuration workflow](.github/workflow-templates/opsscript-gate
22
22
  shell files change, uses offline containers by default, and uploads a report that can be attached to a PR.
23
23
  No account, API key, or service signup is required.
24
24
 
25
+ Try the browser scanner: [InstallReady](https://mresyzz.github.io/InstallReady/?repo=Mresyzz%2Fopsscript-gate) checks this repository without executing code or requiring a login.
26
+
25
27
  ---
26
28
 
27
- ## Current release: v0.6.0
29
+ ## Current release: v0.6.3
28
30
 
29
31
  The current release includes a project config file, a dry-run plan, presets, exclusions,
30
32
  saved reports, and changed-script selection for pull requests. The project controls
@@ -32,6 +34,7 @@ were introduced in v0.5.0; projects on v0.4.1 and earlier do not include them.
32
34
 
33
35
  ```bash
34
36
  opsscript-gate init
37
+ opsscript-gate doctor
35
38
  opsscript-gate run --dry-run
36
39
  opsscript-gate run --format json --output reports/compatibility.json
37
40
  ```
@@ -39,6 +42,7 @@ opsscript-gate run --format json --output reports/compatibility.json
39
42
  `init` creates `.opsscript-gate.json` and a GitHub Actions workflow without replacing
40
43
  existing files. Review its exclusions (`tests/*`, `examples/*`) and offline network
41
44
  default before running. No Docker is required for `init` or `--dry-run`.
45
+ Use `opsscript-gate doctor` to check Python and Docker before a real run.
42
46
 
43
47
  Useful for standalone installers, container entrypoints and release scripts that
44
48
  must work on both GNU/Linux and Alpine/BusyBox. Each script runs independently;
@@ -67,7 +71,7 @@ jobs:
67
71
  runs-on: ubuntu-latest
68
72
  steps:
69
73
  - uses: actions/checkout@v7
70
- - uses: Mresyzz/opsscript-gate@v0.6.0
74
+ - uses: Mresyzz/opsscript-gate@v0.6.3
71
75
  ```
72
76
 
73
77
  This zero-configuration form discovers shell scripts in the repository. Use
@@ -78,7 +82,7 @@ repository has a single installer. For self-hosted model installers, see the
78
82
  Or test a specific script with custom execution modes:
79
83
 
80
84
  ```yaml
81
- - uses: Mresyzz/opsscript-gate@v0.6.0
85
+ - uses: Mresyzz/opsscript-gate@v0.6.3
82
86
  with:
83
87
  script-path: scripts/install.sh
84
88
  shell: auto
@@ -109,7 +113,7 @@ unrelated scripts:
109
113
  - uses: actions/checkout@v7
110
114
  with:
111
115
  fetch-depth: 0
112
- - uses: Mresyzz/opsscript-gate@v0.6.0
116
+ - uses: Mresyzz/opsscript-gate@v0.6.3
113
117
  with:
114
118
  changed-since: ${{ github.event.pull_request.base.sha }}
115
119
  preset: minimal
@@ -321,6 +325,12 @@ Customize the matrix at any time via `--matrix` or Action input `matrix`.
321
325
 
322
326
  ## CLI reference
323
327
 
328
+ Check local prerequisites before starting containers:
329
+
330
+ ```text
331
+ opsscript-gate doctor [--format table|json]
332
+ ```
333
+
324
334
  ```text
325
335
  usage: opsscript-gate run [-h] [--matrix MATRIX] [-j JOBS] [--timeout TIMEOUT]
326
336
  [--format {table,markdown,json}]
@@ -8,9 +8,11 @@ Bash 依赖、包管理器假设和交互式阻塞。它与 ShellCheck 互补。
8
8
  适合独立安装脚本、容器入口脚本和发布脚本。每次只挂载目标脚本,
9
9
  不挂载整个仓库;依赖其他仓库文件的脚本需要现有项目测试配合。
10
10
 
11
- ## 当前版本 v0.6.0
11
+ 也可以直接打开 [InstallReady 在线扫描器](https://mresyzz.github.io/InstallReady/?repo=Mresyzz%2Fopsscript-gate),无需登录即可检查公开仓库。
12
12
 
13
- v0.6.0 已作为正式版本发布;如果你要从源码验证当前分支,也可以执行:
13
+ ## 当前版本 v0.6.3
14
+
15
+ v0.6.3 已作为正式版本发布;如果你要从源码验证当前分支,也可以执行:
14
16
 
15
17
  ```bash
16
18
  pip install -e .
@@ -21,13 +23,15 @@ opsscript-gate run examples/basic/clean_setup.sh --dry-run
21
23
 
22
24
  ```bash
23
25
  opsscript-gate init
26
+ opsscript-gate doctor
24
27
  opsscript-gate run --dry-run
25
28
  opsscript-gate run --format json --output reports/compatibility.json
26
29
  ```
27
30
 
28
- `init` 生成配置和 GitHub 工作流,不覆盖已有文件。工作流引用 `v0.6.0`。
31
+ `init` 生成配置和 GitHub 工作流,不覆盖已有文件。工作流引用 `v0.6.3`。
29
32
  预览不需要 Docker;真实运行需要 Python 3.10+
30
33
  和可访问的 Linux Docker 引擎。
34
+ `opsscript-gate doctor` 可以在真实运行前检查 Python 和 Docker。
31
35
 
32
36
  生成的配置默认排除 `tests/*`、`examples/*`,使用 Debian + Alpine,尊重
33
37
  脚本 shebang,并关闭网络。请根据实际脚本审核配置;需要下载文件时启用
@@ -45,13 +49,16 @@ opsscript-gate run --format json --output reports/compatibility.json
45
49
  返回码 `0` 表示全部通过,`1` 表示检查失败或发生错误。`--dry-run` 成功只表示
46
50
  执行计划生成成功。容器不是不可信代码的安全沙箱。
47
51
 
52
+ 需要排查本地环境时运行 `opsscript-gate doctor --format json`;它会检查 Python、
53
+ Docker daemon 和可选的项目配置。
54
+
48
55
  在 Pull Request 中只检查本次修改的脚本,可以先获取完整 Git 历史,再传入目标分支提交:
49
56
 
50
57
  ```yaml
51
58
  - uses: actions/checkout@v7
52
59
  with:
53
60
  fetch-depth: 0
54
- - uses: Mresyzz/opsscript-gate@v0.6.0
61
+ - uses: Mresyzz/opsscript-gate@v0.6.3
55
62
  with:
56
63
  changed-since: ${{ github.event.pull_request.base.sha }}
57
64
  preset: minimal
@@ -1,5 +1,5 @@
1
1
  name: 'OpsScript Gate'
2
- description: 'Run Linux shell scripts in Debian, Ubuntu and Alpine containers to catch runtime compatibility failures before merge'
2
+ description: 'Run Linux shell installers across Debian, Ubuntu, and Alpine; a ShellCheck companion for runtime compatibility in CI.'
3
3
  author: 'Mresyzz'
4
4
  branding:
5
5
  icon: 'shield'
@@ -7,11 +7,15 @@ have these commands.
7
7
 
8
8
  ```bash
9
9
  opsscript-gate init
10
+ opsscript-gate doctor
10
11
  opsscript-gate run --dry-run
11
12
  ```
12
13
 
13
14
  `init` refuses to overwrite either `.opsscript-gate.json` or
14
- `.github/workflows/opsscript-gate.yml`. The generated workflow uses the v0.6.0 tag.
15
+ `.github/workflows/opsscript-gate.yml`. The generated workflow uses the v0.6.3 tag.
16
+
17
+ `doctor` checks Python and Docker connectivity without executing repository scripts.
18
+ Use `opsscript-gate doctor --format json` when collecting a support report.
15
19
 
16
20
  The generated config uses the two-image `minimal` preset, honors recognized shell
17
21
  shebangs, disables networking, and excludes `tests/*` and `examples/*`. Review these
@@ -95,7 +99,7 @@ For pull requests, set `changed-since` to the base commit and fetch full Git his
95
99
  - uses: actions/checkout@v7
96
100
  with:
97
101
  fetch-depth: 0
98
- - uses: Mresyzz/opsscript-gate@v0.6.0
102
+ - uses: Mresyzz/opsscript-gate@v0.6.3
99
103
  with:
100
104
  changed-since: ${{ github.event.pull_request.base.sha }}
101
105
  preset: minimal
@@ -105,7 +109,7 @@ The Action passes when no changed shell scripts are selected. This keeps unrelat
105
109
  documentation or application changes from starting container jobs.
106
110
 
107
111
  ```yaml
108
- - uses: Mresyzz/opsscript-gate@v0.6.0
112
+ - uses: Mresyzz/opsscript-gate@v0.6.3
109
113
  with:
110
114
  config: .opsscript-gate.json
111
115
  format: json
@@ -33,7 +33,7 @@ jobs:
33
33
  fetch-depth: 0
34
34
  persist-credentials: false
35
35
 
36
- - uses: Mresyzz/opsscript-gate@v0.6.0
36
+ - uses: Mresyzz/opsscript-gate@v0.6.3
37
37
  with:
38
38
  changed-since: ${{ github.event.pull_request.base.sha }}
39
39
  preset: minimal
@@ -2,4 +2,4 @@
2
2
 
3
3
  This example shows a GitHub Actions workflow for checking a shell script on pull requests.
4
4
 
5
- Copy `workflow.yml` into your repository at `.github/workflows/script-gate.yml` and point `script-path` to the script you want to validate. The example uses the current v0.6.0 Action release.
5
+ Copy `workflow.yml` into your repository at `.github/workflows/script-gate.yml` and point `script-path` to the script you want to validate. The example uses the current v0.6.3 Action release.
@@ -19,7 +19,7 @@ jobs:
19
19
  persist-credentials: false
20
20
 
21
21
  - name: Run OpsScript Gate
22
- uses: Mresyzz/opsscript-gate@v0.6.0
22
+ uses: Mresyzz/opsscript-gate@v0.6.3
23
23
  with:
24
24
  script-path: 'scripts/deploy.sh'
25
25
  shell: auto
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "opsscript-gate"
7
- version = "0.6.1"
7
+ version = "0.6.3"
8
8
  description = "Run Linux shell scripts in Debian, Ubuntu and Alpine containers to catch runtime compatibility failures before merge"
9
9
  readme = "README.md"
10
10
  license = { text = "MIT" }
@@ -29,6 +29,10 @@ keywords = [
29
29
  "ubuntu",
30
30
  "alpine",
31
31
  "shellcheck-alternative",
32
+ "shellcheck",
33
+ "shell-portability",
34
+ "installer-testing",
35
+ "busybox",
32
36
  ]
33
37
  classifiers = [
34
38
  "Development Status :: 4 - Beta",
@@ -47,7 +51,8 @@ dependencies = [
47
51
  ]
48
52
 
49
53
  [project.urls]
50
- Homepage = "https://github.com/Mresyzz/opsscript-gate"
54
+ Homepage = "https://mresyzz.github.io/InstallReady/"
55
+ Demo = "https://mresyzz.github.io/InstallReady/?repo=Mresyzz%2Fopsscript-gate"
51
56
  Repository = "https://github.com/Mresyzz/opsscript-gate"
52
57
  Issues = "https://github.com/Mresyzz/opsscript-gate/issues"
53
58
  Changelog = "https://github.com/Mresyzz/opsscript-gate/blob/main/CHANGELOG.md"
@@ -1,4 +1,4 @@
1
1
  """OpsScript Gate: Lightweight cross-distro compatibility pre-check for Linux ops scripts."""
2
2
 
3
- __version__ = "0.6.1"
3
+ __version__ = "0.6.3"
4
4
  __all__ = ["__version__"]
@@ -24,6 +24,7 @@ from opsscript_gate.runner import (
24
24
  DEFAULT_MATRIX,
25
25
  DEFAULT_TIMEOUT,
26
26
  DockerDaemonError,
27
+ get_docker_client,
27
28
  run_matrix,
28
29
  )
29
30
 
@@ -43,6 +44,16 @@ def build_parser() -> argparse.ArgumentParser:
43
44
 
44
45
  subparsers = parser.add_subparsers(dest="command", help="Available subcommands")
45
46
  subparsers.add_parser("init", help="Create project configuration and GitHub workflow")
47
+ doctor_parser = subparsers.add_parser(
48
+ "doctor",
49
+ help="Check the local environment before running containers",
50
+ )
51
+ doctor_parser.add_argument(
52
+ "--format",
53
+ choices=["table", "json"],
54
+ default="table",
55
+ help="Output format: 'table' (default) or 'json'",
56
+ )
46
57
 
47
58
  # 'run' subcommand
48
59
  run_parser = subparsers.add_parser(
@@ -149,6 +160,38 @@ def main(argv: list[str] | None = None) -> int:
149
160
  sys.stderr.write(f"Error: {err}\n")
150
161
  return 1
151
162
 
163
+ if args.command == "doctor":
164
+ checks = [
165
+ {
166
+ "name": "python",
167
+ "ok": sys.version_info >= (3, 10),
168
+ "detail": f"Python {sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}",
169
+ }
170
+ ]
171
+ try:
172
+ get_docker_client()
173
+ checks.append({"name": "docker", "ok": True, "detail": "Docker daemon is reachable"})
174
+ except DockerDaemonError as err:
175
+ checks.append({"name": "docker", "ok": False, "detail": str(err)})
176
+
177
+ config_path = Path(".opsscript-gate.json")
178
+ checks.append({
179
+ "name": "project",
180
+ "ok": True,
181
+ "detail": f"Found {config_path}" if config_path.is_file() else "No project config (optional)",
182
+ })
183
+ passed = all(check["ok"] for check in checks)
184
+ if args.format == "json":
185
+ print(json.dumps({"status": "PASS" if passed else "FAIL", "checks": checks}, indent=2))
186
+ else:
187
+ print("OpsScript Gate doctor")
188
+ for check in checks:
189
+ marker = "PASS" if check["ok"] else "FAIL"
190
+ print(f"[{marker}] {check['name']}: {check['detail']}")
191
+ if not passed:
192
+ print("Run `opsscript-gate init` after fixing the failed check, then preview with `opsscript-gate run --dry-run`.")
193
+ return 0 if passed else 1
194
+
152
195
  if args.command == "run":
153
196
  try:
154
197
  config = load_config(args.config)
@@ -63,7 +63,7 @@ jobs:
63
63
  - uses: actions/checkout@v7
64
64
  with:
65
65
  persist-credentials: false
66
- - uses: Mresyzz/opsscript-gate@v0.6.0
66
+ - uses: Mresyzz/opsscript-gate@v0.6.3
67
67
  with:
68
68
  config: .opsscript-gate.json
69
69
  """,
@@ -8,6 +8,7 @@ from opsscript_gate.cli import main
8
8
  from opsscript_gate.config import CONFIG_NAME, init_project, load_config
9
9
  from opsscript_gate.discovery import discover_changed_scripts, discover_scripts, is_shell_script
10
10
  from opsscript_gate.models import RunReport, SingleResult, DistroStatus
11
+ from opsscript_gate.runner import DockerDaemonError
11
12
 
12
13
 
13
14
  @pytest.fixture
@@ -35,6 +36,27 @@ def test_init_preview_and_no_overwrite(project, capsys):
35
36
  assert Path(CONFIG_NAME).read_bytes() == original
36
37
 
37
38
 
39
+ def test_doctor_reports_local_prerequisites(project, capsys):
40
+ with patch("opsscript_gate.cli.get_docker_client"):
41
+ assert main(["doctor"]) == 0
42
+ output = capsys.readouterr().out
43
+ assert "OpsScript Gate doctor" in output
44
+ assert "[PASS] python" in output
45
+ assert "[PASS] docker" in output
46
+ assert "No project config (optional)" in output
47
+
48
+
49
+ def test_doctor_json_reports_docker_failure(project, capsys):
50
+ with patch(
51
+ "opsscript_gate.cli.get_docker_client",
52
+ side_effect=DockerDaemonError("Docker is not running"),
53
+ ):
54
+ assert main(["doctor", "--format", "json"]) == 1
55
+ report = json.loads(capsys.readouterr().out)
56
+ assert report["status"] == "FAIL"
57
+ assert next(check for check in report["checks"] if check["name"] == "docker")["ok"] is False
58
+
59
+
38
60
  def test_init_existing_workflow_leaves_config_absent(project):
39
61
  workflow = project / ".github/workflows/opsscript-gate.yml"
40
62
  workflow.parent.mkdir(parents=True)
File without changes