-
Notifications
You must be signed in to change notification settings - Fork 0
Refactor ratchet coverage action #21
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -33,7 +33,7 @@ runs: | |
| restore-keys: | | ||
| ${{ runner.os }}-llvmcov- | ||
| - name: Install cargo-llvm-cov | ||
| run: cargo install cargo-llvm-cov | ||
| run: uv run --script scripts/ratchet_coverage/install_cargo_llvm_cov.py | ||
| shell: bash | ||
| - if: runner.os == 'Windows' | ||
| name: Install bc (MSYS2) | ||
|
|
@@ -43,40 +43,12 @@ runs: | |
| path-type: inherit | ||
| - name: Run coverage | ||
| id: cov | ||
| run: | | ||
| set -euo pipefail | ||
| output=$(cargo llvm-cov --summary-only ${{ inputs.args }}) | ||
| echo "$output" | ||
| percent=$(echo "$output" | grep -oEm1 '[0-9]+(\.[0-9]+)?%' | tr -d '%') | ||
| echo "percent=$percent" >> "$GITHUB_OUTPUT" | ||
| run: uv run --script scripts/ratchet_coverage/run_coverage.py | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Use action path for script reference. Apply the same portability fix as suggested for the install script. - run: uv run --script scripts/ratchet_coverage/run_coverage.py
+ run: uv run --script ${{ github.action_path }}/src/run_coverage.py🤖 Prompt for AI Agents |
||
| shell: bash | ||
| - name: Ratchet coverage | ||
| run: | | ||
| set -euo pipefail | ||
| file="${{ inputs.baseline-file }}" | ||
| current="${{ steps.cov.outputs.percent }}" | ||
| baseline=0 | ||
| if [ -f "$file" ]; then | ||
| baseline=$(cat "$file") | ||
| fi | ||
| echo "Current coverage: $current%" | ||
| echo "Baseline coverage: $baseline%" | ||
|
|
||
| if ! echo "$current" | grep -Eq '^[0-9]+(\.[0-9]+)?$'; then | ||
| echo "Invalid coverage value: $current" >&2 | ||
| exit 1 | ||
| fi | ||
| if ! echo "$baseline" | grep -Eq '^[0-9]+(\.[0-9]+)?$'; then | ||
| baseline=0 | ||
| fi | ||
|
|
||
| if (( $(bc -l <<<"$current < $baseline") )); then | ||
| echo "Coverage decreased" >&2 | ||
| exit 1 | ||
| fi | ||
|
|
||
| mkdir -p "$(dirname "$file")" | ||
| printf '%.2f' "$current" > "$file" | ||
| run: uv run --script scripts/ratchet_coverage/ratchet_coverage.py | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Use action path for script reference. Apply the same portability fix as suggested for the other scripts. - run: uv run --script scripts/ratchet_coverage/ratchet_coverage.py
+ run: uv run --script ${{ github.action_path }}/src/ratchet_coverage.py🤖 Prompt for AI Agents |
||
| env: | ||
| CURRENT_PERCENT: ${{ steps.cov.outputs.percent }} | ||
| shell: bash | ||
| - name: Save baseline | ||
| if: success() | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,20 @@ | ||||||||||||||||||||||||||||||||
| #!/usr/bin/env -S uv run --script | ||||||||||||||||||||||||||||||||
| # /// script | ||||||||||||||||||||||||||||||||
| # requires-python = ">=3.12" | ||||||||||||||||||||||||||||||||
| # dependencies = ["plumbum", "typer"] | ||||||||||||||||||||||||||||||||
| # /// | ||||||||||||||||||||||||||||||||
| from plumbum.cmd import cargo | ||||||||||||||||||||||||||||||||
| import typer | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| def main() -> None: | ||||||||||||||||||||||||||||||||
| try: | ||||||||||||||||||||||||||||||||
| cargo["install", "cargo-llvm-cov"]() | ||||||||||||||||||||||||||||||||
| typer.echo("cargo-llvm-cov installed successfully") | ||||||||||||||||||||||||||||||||
| except Exception as e: | ||||||||||||||||||||||||||||||||
| typer.echo(f"Failed to install cargo-llvm-cov: {e}", err=True) | ||||||||||||||||||||||||||||||||
| raise typer.Exit(code=1) | ||||||||||||||||||||||||||||||||
|
Comment on lines
+10
to
+16
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Improve exception handling specificity and add documentation. Good work adding error handling as suggested in the previous review. Consider these improvements:
def main() -> None:
+ """Install cargo-llvm-cov using cargo."""
try:
cargo["install", "cargo-llvm-cov"]()
typer.echo("cargo-llvm-cov installed successfully")
- except Exception as e:
+ except Exception as e:
typer.echo(f"Failed to install cargo-llvm-cov: {e}", err=True)
- raise typer.Exit(code=1)
+ raise typer.Exit(code=1) from eNote: For more specific exception handling, you could import 📝 Committable suggestion
Suggested change
🧰 Tools🪛 Ruff (0.11.9)14-14: Do not catch blind exception: (BLE001) 16-16: Within an (B904) 🪛 Pylint (3.3.7)[convention] 10-10: Missing function or method docstring (C0116) 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| if __name__ == "__main__": | ||||||||||||||||||||||||||||||||
| typer.run(main) | ||||||||||||||||||||||||||||||||
|
leynos marked this conversation as resolved.
|
||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| #!/usr/bin/env -S uv run --script | ||
| # /// script | ||
| # requires-python = ">=3.12" | ||
| # dependencies = ["plumbum", "typer"] | ||
| # /// | ||
| from pathlib import Path | ||
| import typer | ||
|
|
||
|
|
||
| def read_baseline(file: Path) -> float: | ||
| """Return the stored baseline coverage or 0.0 if missing/invalid.""" | ||
| if file.is_file(): | ||
| try: | ||
| return float(file.read_text().strip()) | ||
| except ValueError: | ||
| return 0.0 | ||
| return 0.0 | ||
|
|
||
|
|
||
| def main( | ||
| baseline_file: Path = typer.Option( | ||
| Path(".coverage-baseline"), envvar="INPUT_BASELINE_FILE" | ||
| ), | ||
| current: float = typer.Option(..., envvar="CURRENT_PERCENT"), | ||
| ) -> None: | ||
| baseline = read_baseline(baseline_file) | ||
|
|
||
| typer.echo(f"Current coverage: {current}%") | ||
| typer.echo(f"Baseline coverage: {baseline}%") | ||
|
|
||
| if current < baseline: | ||
| typer.echo("Coverage decreased", err=True) | ||
| raise typer.Exit(code=1) | ||
|
|
||
| baseline_file.parent.mkdir(parents=True, exist_ok=True) | ||
| baseline_file.write_text(f"{current:.2f}") | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| typer.run(main) |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,36 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| #!/usr/bin/env -S uv run --script | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| # /// script | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| # requires-python = ">=3.12" | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| # dependencies = ["plumbum", "typer"] | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| # /// | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| from pathlib import Path | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| import re | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| import shlex | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| import typer | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| from plumbum.cmd import cargo | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| def extract_percent(output: str) -> str: | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| match = re.search(r"([0-9]+(?:\.[0-9]+)?)%", output) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| if not match: | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| typer.echo("Could not parse coverage percent", err=True) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| raise typer.Exit(code=1) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| return match[1] | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| def main( | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| args: str = typer.Option("", envvar="INPUT_ARGS"), | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| github_output: Path = typer.Option(..., envvar="GITHUB_OUTPUT"), | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) -> None: | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| cmd = cargo["llvm-cov", "--summary-only"] | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| if args: | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| cmd = cmd[shlex.split(args)] | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| output = cmd() | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| typer.echo(output) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| percent = extract_percent(output) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| with github_output.open("a") as fh: | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| fh.write(f"percent={percent}\n") | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+21
to
+32
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick (assertive) Address the function call in argument defaults. The use of def main(
- args: str = typer.Option("", envvar="INPUT_ARGS"),
- github_output: Path = typer.Option(..., envvar="GITHUB_OUTPUT"),
+ args: str = typer.Option("", envvar="INPUT_ARGS"),
+ github_output: Path = typer.Option(..., envvar="GITHUB_OUTPUT"),
) -> None:
+ """Run cargo llvm-cov and extract coverage percentage."""
cmd = cargo["llvm-cov", "--summary-only"]
if args:
cmd = cmd[shlex.split(args)]
output = cmd()
typer.echo(output)
percent = extract_percent(output)
with github_output.open("a") as fh:
fh.write(f"percent={percent}\n")Alternative approach to avoid the warning: +def main(
+ args: str = "",
+ github_output: str = "",
+) -> None:
+ """Run cargo llvm-cov and extract coverage percentage."""
+ # Get values from environment if not provided
+ if not args:
+ args = os.environ.get("INPUT_ARGS", "")
+ if not github_output:
+ github_output = os.environ["GITHUB_OUTPUT"]
+
+ github_output_path = Path(github_output)
+ # ... rest of the function📝 Committable suggestion
Suggested change
🧰 Tools🪛 Ruff (0.11.9)23-23: Do not perform function call (B008) 🪛 Pylint (3.3.7)[convention] 21-21: Missing function or method docstring (C0116) 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| if __name__ == "__main__": | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| typer.run(main) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Move scripts to action directory for portability.
The coding guidelines specify that actions should reference sibling scripts using
${{ github.action_path }}for portability. The current implementation references scripts in a global directory which violates this guideline.Consider moving the scripts to
.github/actions/ratchet-coverage/src/and updating the reference:📝 Committable suggestion
🤖 Prompt for AI Agents