Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
# Changelog

## [0.9.0] - 2026-10-03

### Added
- Added `--repeat` and Action/config `repeat` support to detect flaky runtime behavior per distribution.
- Added attempt counts and `FLAKY` status to JSON, Markdown, SARIF, terminal, and GitHub Step Summary reports.

### Fixed
- Bounded project configuration reads to prevent oversized configuration files from consuming unbounded memory.
- Prefer Docker's blocking wait API over repeated synchronous container reloads, while retaining a bounded compatibility fallback.
- Removed duplicated CLI execution error handling and the unused `asdict` import.

## [0.8.3] - 2026-10-02

- Corrected the PyPI homepage and demo links to point to the OpsScript Gate Pages site.
Expand Down
2 changes: 1 addition & 1 deletion CITATION.cff
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ type: software
authors:
- family-names: Mresyzz
given-names: Mresy
version: 0.8.3
version: 0.9.0
date-released: 2026-10-02
repository-code: https://github.com/Mresyzz/opsscript-gate
url: https://github.com/Mresyzz/opsscript-gate
Expand Down
27 changes: 20 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ apt-get --version
Run it locally with `opsscript-gate run ./install.sh`, or add the following step to CI:

```yaml
- uses: Mresyzz/opsscript-gate@v0.8.3
- uses: Mresyzz/opsscript-gate@v0.9.0
with:
script-path: install.sh
```
Expand All @@ -57,17 +57,20 @@ The result identifies the failing distribution, exit code, line, missing command

---

## Current release: v0.8.3
## Current release: v0.9.0

The current release includes a project config file, a dry-run plan, presets, exclusions,
saved reports, and changed-script selection for pull requests. The project controls
saved reports, changed-script selection for pull requests, and repeat runs for detecting
flaky runtime behavior. The project controls
were introduced in v0.5.0; projects on v0.4.1 and earlier do not include them.

```bash
opsscript-gate init
opsscript-gate doctor
opsscript-gate run --dry-run
opsscript-gate run --format json --output reports/compatibility.json
# Repeat each distro three times when diagnosing intermittent failures
opsscript-gate run ./install.sh --repeat 3
```

`init` creates `.opsscript-gate.json` and a GitHub Actions workflow without replacing
Expand Down Expand Up @@ -108,7 +111,7 @@ jobs:
- uses: actions/checkout@v7
with:
persist-credentials: false
- uses: Mresyzz/opsscript-gate@v0.8.3
- uses: Mresyzz/opsscript-gate@v0.9.0
```

This zero-configuration form discovers shell scripts in the repository. Use
Expand All @@ -119,11 +122,13 @@ repository has a single installer. For self-hosted model installers, see the
Or test a specific script with custom execution modes:

```yaml
- uses: Mresyzz/opsscript-gate@v0.8.3
- uses: Mresyzz/opsscript-gate@v0.9.0
with:
script-path: scripts/install.sh
shell: auto
jobs: 4
# Optional: expose intermittent runtime failures
repeat: 3
```

### In Local Terminal (CLI)
Expand Down Expand Up @@ -151,7 +156,7 @@ unrelated scripts:
with:
persist-credentials: false
fetch-depth: 0
- uses: Mresyzz/opsscript-gate@v0.8.3
- uses: Mresyzz/opsscript-gate@v0.9.0
with:
changed-since: ${{ github.event.pull_request.base.sha }}
preset: minimal
Expand All @@ -161,6 +166,14 @@ If the change does not include a shell script, the check passes without starting
container. The same selection can be previewed locally with
`opsscript-gate run --changed-since origin/main --dry-run`.

### Detect intermittent runtime failures

Use `--repeat N` when a script sometimes passes and sometimes fails in CI. OpsScript
Gate runs each distribution N times and reports `FLAKY` when the same distribution has
both passing and failing attempts. The JSON, Markdown, SARIF, annotations, and step
summary include the attempt counts so a retry cannot silently turn an unstable script
green.

### Example: package-manager mismatch

Create `install.sh`:
Expand Down Expand Up @@ -234,7 +247,7 @@ Use `sarif` when the result should appear in GitHub Code Scanning or another
SARIF-compatible viewer. Upload it explicitly with the official upload action:

```yaml
- uses: Mresyzz/opsscript-gate@v0.8.3
- uses: Mresyzz/opsscript-gate@v0.9.0
with:
script-path: scripts/install.sh
format: sarif
Expand Down
10 changes: 6 additions & 4 deletions README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ Bash 依赖、包管理器假设和交互式阻塞。它与 ShellCheck 互补。

也可以直接打开 [OpsScript Gate 在线演示](https://mresyzz.github.io/opsscript-gate/),先查看 ShellCheck 与运行时验证的差异,再复制 workflow 到自己的仓库。

## 当前版本 v0.8.3
## 当前版本 v0.9.0

v0.8.3 已作为正式版本发布;如果你要从源码验证当前分支,也可以执行:
v0.9.0 已作为正式版本发布;如果你要从源码验证当前分支,也可以执行:

```bash
pip install -e .
Expand All @@ -35,7 +35,7 @@ opsscript-gate run --dry-run
opsscript-gate run --format json --output reports/compatibility.json
```

`init` 生成配置和 GitHub 工作流,不覆盖已有文件。工作流引用 `v0.8.3`。
`init` 生成配置和 GitHub 工作流,不覆盖已有文件。工作流引用 `v0.9.0`。
预览不需要 Docker;真实运行需要 Python 3.10+
和可访问的 Linux Docker 引擎。
`opsscript-gate doctor` 可以在真实运行前检查 Python 和 Docker。
Expand All @@ -58,6 +58,8 @@ opsscript-gate run --format json --output reports/compatibility.json
- 排除规则、发行版预设、扫描数量限制。
- 超过扫描上限明确报错,避免只测前 20 个却误以为全部通过。
- 报告保存为 JSON、Markdown 或文本,失败时同样保留结果。
- 使用 `--repeat 3` 或配置 `"repeat": 3` 重复运行每个发行版;同一发行版出现
一次通过、一次失败时会标记为 `FLAKY`,避免偶发绿灯掩盖 CI 不稳定。
- 自动发现跳过符号链接,并严格校验配置与执行参数。

返回码 `0` 表示全部通过,`1` 表示检查失败或发生错误。`--dry-run` 成功只表示
Expand All @@ -72,7 +74,7 @@ Docker daemon 和可选的项目配置。
- uses: actions/checkout@v7
with:
fetch-depth: 0
- uses: Mresyzz/opsscript-gate@v0.8.3
- uses: Mresyzz/opsscript-gate@v0.9.0
with:
changed-since: ${{ github.event.pull_request.base.sha }}
preset: minimal
Expand Down
9 changes: 9 additions & 0 deletions ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,15 @@ This roadmap tracks features delivered in recent releases and areas under consid

---

## Delivered in v0.9.0

- [x] **Flaky Runtime Detection (`--repeat` / `repeat`)**: Repeat each distribution
run and report mixed pass/fail outcomes as `FLAKY` with attempt counts.
- [x] **Bounded Configuration Loading**: Reject oversized project configuration files
before parsing them.
- [x] **Blocking Container Wait**: Prefer Docker's wait API over repeated synchronous
status reloads while retaining a test-double fallback.

## Delivered in v0.4.0

- [x] **High-confidence Line-level GitHub Actions Annotations**: Emits safe `::error` annotations linking failure lines directly on pull request file diffs.
Expand Down
6 changes: 6 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ inputs:
description: 'Hard timeout in seconds per container (default: 60)'
required: false
default: ''
repeat:
description: 'Repeat each distribution run to detect flaky runtime behavior (default: 1)'
required: false
default: ''
format:
description: 'Output report format: table, markdown, json, or sarif'
required: false
Expand Down Expand Up @@ -96,6 +100,7 @@ runs:
INPUT_MATRIX: ${{ inputs.matrix }}
INPUT_JOBS: ${{ inputs.jobs }}
INPUT_TIMEOUT: ${{ inputs.timeout }}
INPUT_REPEAT: ${{ inputs.repeat }}
INPUT_FORMAT: ${{ inputs.format }}
INPUT_SHELL: ${{ inputs.shell }}
INPUT_MEM_LIMIT: ${{ inputs.mem-limit }}
Expand All @@ -116,6 +121,7 @@ runs:
fi
# Only explicit inputs override project configuration.
[ -z "$INPUT_TIMEOUT" ] || ARGS+=(--timeout "$INPUT_TIMEOUT")
[ -z "$INPUT_REPEAT" ] || ARGS+=(--repeat "$INPUT_REPEAT")
[ -z "$INPUT_FORMAT" ] || ARGS+=(--format "$INPUT_FORMAT")
[ -z "$INPUT_SHELL" ] || ARGS+=(--shell "$INPUT_SHELL")
[ -z "$INPUT_MEM_LIMIT" ] || ARGS+=(--mem-limit "$INPUT_MEM_LIMIT")
Expand Down
8 changes: 4 additions & 4 deletions demo.html
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@
OpsScript Gate
</span>
<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)]">
v0.8.3
v0.9.0
</span>
</div>
</div>
Expand Down Expand Up @@ -367,7 +367,7 @@ <h2 class="font-serif text-xl text-[var(--text-hero)] font-medium">
<div class="panel-card p-4 flex flex-col justify-between space-y-3">
<div class="space-y-2.5">
<div class="flex items-center justify-between border-b border-[var(--border-light)] pb-2">
<span class="font-mono text-xs font-medium text-[var(--text-muted)]">OpsScript Gate Runtime (v0.8.3)</span>
<span class="font-mono text-xs font-medium text-[var(--text-muted)]">OpsScript Gate Runtime (v0.9.0)</span>
<span id="ops-status" class="font-mono text-xs font-semibold px-2 py-0.5 rounded border">
1 DISTRO FAILED
</span>
Expand Down Expand Up @@ -536,7 +536,7 @@ <h3 class="font-serif text-xl text-[var(--text-hero)] font-medium">
<span class="font-semibold text-[var(--text-hero)]">steps:</span>
- <span class="font-semibold text-[var(--text-hero)]">uses:</span> actions/checkout@v4
- <span class="font-semibold text-[var(--text-hero)]">name:</span> Validate scripts across distributions
<span class="font-semibold text-[var(--brand)]">uses:</span> Mresyzz/opsscript-gate@v0.8.3
<span class="font-semibold text-[var(--brand)]">uses:</span> Mresyzz/opsscript-gate@v0.9.0
<span class="font-semibold text-[var(--text-hero)]">with:</span>
<span class="text-[var(--text-body)]">script-path:</span> ./install.sh
<span class="text-[var(--text-body)]">shell:</span> auto
Expand Down Expand Up @@ -604,7 +604,7 @@ <h3 class="font-serif text-2xl sm:text-3xl text-[var(--text-hero)] font-normal t
steps:
- uses: actions/checkout@v4
- name: Validate scripts across distributions
uses: Mresyzz/opsscript-gate@v0.8.3
uses: Mresyzz/opsscript-gate@v0.9.0
with:
script-path: ./install.sh
shell: auto
Expand Down
2 changes: 1 addition & 1 deletion docs/command-not-found.html
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ <h2 id="workflow">A complete GitHub Actions workflow</h2>
- uses: actions/checkout@v7
with:
persist-credentials: false
- uses: Mresyzz/opsscript-gate@v0.8.3
- uses: Mresyzz/opsscript-gate@v0.9.0
with:
script-path: install.sh
shell: auto
Expand Down
2 changes: 1 addition & 1 deletion docs/command-not-found.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jobs:
- uses: actions/checkout@v7
with:
persist-credentials: false
- uses: Mresyzz/opsscript-gate@v0.8.3
- uses: Mresyzz/opsscript-gate@v0.9.0
with:
script-path: scripts/install.sh
shell: auto
Expand Down
11 changes: 8 additions & 3 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ opsscript-gate run --dry-run
```

`init` refuses to overwrite either `.opsscript-gate.json` or
`.github/workflows/opsscript-gate.yml`. The generated workflow uses the v0.8.3 tag.
`.github/workflows/opsscript-gate.yml`. The generated workflow uses the v0.9.0 tag.

`doctor` checks Python and Docker connectivity without executing repository scripts.
Use `opsscript-gate doctor --format json` when collecting a support report.
Expand All @@ -36,6 +36,7 @@ directory, not the config file's parent.
"network": "none",
"packages": [],
"timeout": 30,
"repeat": 1,
"jobs": 2,
"mem_limit": "256m",
"pids_limit": 128,
Expand All @@ -52,6 +53,9 @@ names to install inside each test container before the target script runs. The
runner uses `apt-get` for Debian/Ubuntu images and `apk` for Alpine images. It
accepts package names only, never shell commands, and requires `network: bridge`.
The default is an empty list, so existing networking settings and execution remain unchanged.
`repeat` runs each distribution more than once and reports `FLAKY` when at least one
attempt passes and another fails. Keep it at `1` for the normal fast gate; use `3` or
`5` while investigating intermittent CI failures.

| Preset | Images |
| --- | --- |
Expand Down Expand Up @@ -86,6 +90,7 @@ opsscript-gate run scripts/install.sh --matrix alpine:3.20 --network bridge

```bash
opsscript-gate run --format json --output reports/compatibility.json
opsscript-gate run --repeat 3 --format markdown
opsscript-gate run --dry-run --format json --output reports/plan.json
```

Expand All @@ -104,7 +109,7 @@ For pull requests, set `changed-since` to the base commit and fetch full Git his
- uses: actions/checkout@v7
with:
fetch-depth: 0
- uses: Mresyzz/opsscript-gate@v0.8.3
- uses: Mresyzz/opsscript-gate@v0.9.0
with:
changed-since: ${{ github.event.pull_request.base.sha }}
preset: minimal
Expand All @@ -114,7 +119,7 @@ The Action passes when no changed shell scripts are selected. This keeps unrelat
documentation or application changes from starting container jobs.

```yaml
- uses: Mresyzz/opsscript-gate@v0.8.3
- uses: Mresyzz/opsscript-gate@v0.9.0
with:
config: .opsscript-gate.json
format: json
Expand Down
2 changes: 1 addition & 1 deletion docs/gpt-oss.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ jobs:
fetch-depth: 0
persist-credentials: false

- uses: Mresyzz/opsscript-gate@v0.8.3
- uses: Mresyzz/opsscript-gate@v0.9.0
with:
changed-since: ${{ github.event.pull_request.base.sha }}
preset: minimal
Expand Down
8 changes: 4 additions & 4 deletions docs/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@
OpsScript Gate
</span>
<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)]">
v0.8.3
v0.9.0
</span>
</div>
</div>
Expand Down Expand Up @@ -375,7 +375,7 @@ <h2 class="font-serif text-xl text-[var(--text-hero)] font-medium">
<div class="panel-card p-4 flex flex-col justify-between space-y-3">
<div class="space-y-2.5">
<div class="flex items-center justify-between border-b border-[var(--border-light)] pb-2">
<span class="font-mono text-xs font-medium text-[var(--text-muted)]">OpsScript Gate Runtime (v0.8.3)</span>
<span class="font-mono text-xs font-medium text-[var(--text-muted)]">OpsScript Gate Runtime (v0.9.0)</span>
<span id="ops-status" class="font-mono text-xs font-semibold px-2 py-0.5 rounded border">
1 DISTRO FAILED
</span>
Expand Down Expand Up @@ -544,7 +544,7 @@ <h3 class="font-serif text-xl text-[var(--text-hero)] font-medium">
<span class="font-semibold text-[var(--text-hero)]">steps:</span>
- <span class="font-semibold text-[var(--text-hero)]">uses:</span> actions/checkout@v4
- <span class="font-semibold text-[var(--text-hero)]">name:</span> Validate scripts across distributions
<span class="font-semibold text-[var(--brand)]">uses:</span> Mresyzz/opsscript-gate@v0.8.3
<span class="font-semibold text-[var(--brand)]">uses:</span> Mresyzz/opsscript-gate@v0.9.0
<span class="font-semibold text-[var(--text-hero)]">with:</span>
<span class="text-[var(--text-body)]">script-path:</span> ./install.sh
<span class="text-[var(--text-body)]">shell:</span> auto
Expand Down Expand Up @@ -612,7 +612,7 @@ <h3 class="font-serif text-2xl sm:text-3xl text-[var(--text-hero)] font-normal t
steps:
- uses: actions/checkout@v4
- name: Validate scripts across distributions
uses: Mresyzz/opsscript-gate@v0.8.3
uses: Mresyzz/opsscript-gate@v0.9.0
with:
script-path: ./install.sh
shell: auto
Expand Down
2 changes: 1 addition & 1 deletion examples/github-actions/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@

This example shows a GitHub Actions workflow for checking a shell script on pull requests.

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.8.3 Action release.
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.9.0 Action release.
2 changes: 1 addition & 1 deletion examples/github-actions/workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
persist-credentials: false

- name: Run OpsScript Gate
uses: Mresyzz/opsscript-gate@v0.8.3
uses: Mresyzz/opsscript-gate@v0.9.0
with:
script-path: 'scripts/deploy.sh'
shell: auto
Expand Down
8 changes: 4 additions & 4 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@
OpsScript Gate
</span>
<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)]">
v0.8.3
v0.9.0
</span>
</div>
</div>
Expand Down Expand Up @@ -375,7 +375,7 @@ <h2 class="font-serif text-xl text-[var(--text-hero)] font-medium">
<div class="panel-card p-4 flex flex-col justify-between space-y-3">
<div class="space-y-2.5">
<div class="flex items-center justify-between border-b border-[var(--border-light)] pb-2">
<span class="font-mono text-xs font-medium text-[var(--text-muted)]">OpsScript Gate Runtime (v0.8.3)</span>
<span class="font-mono text-xs font-medium text-[var(--text-muted)]">OpsScript Gate Runtime (v0.9.0)</span>
<span id="ops-status" class="font-mono text-xs font-semibold px-2 py-0.5 rounded border">
1 DISTRO FAILED
</span>
Expand Down Expand Up @@ -544,7 +544,7 @@ <h3 class="font-serif text-xl text-[var(--text-hero)] font-medium">
<span class="font-semibold text-[var(--text-hero)]">steps:</span>
- <span class="font-semibold text-[var(--text-hero)]">uses:</span> actions/checkout@v4
- <span class="font-semibold text-[var(--text-hero)]">name:</span> Validate scripts across distributions
<span class="font-semibold text-[var(--brand)]">uses:</span> Mresyzz/opsscript-gate@v0.8.3
<span class="font-semibold text-[var(--brand)]">uses:</span> Mresyzz/opsscript-gate@v0.9.0
<span class="font-semibold text-[var(--text-hero)]">with:</span>
<span class="text-[var(--text-body)]">script-path:</span> ./install.sh
<span class="text-[var(--text-body)]">shell:</span> auto
Expand Down Expand Up @@ -612,7 +612,7 @@ <h3 class="font-serif text-2xl sm:text-3xl text-[var(--text-hero)] font-normal t
steps:
- uses: actions/checkout@v4
- name: Validate scripts across distributions
uses: Mresyzz/opsscript-gate@v0.8.3
uses: Mresyzz/opsscript-gate@v0.9.0
with:
script-path: ./install.sh
shell: auto
Expand Down
Loading
Loading