Skip to content

P-013: ship the CI/CLI distribution surface (Action + dotnet tool)#10

Merged
PhysShell merged 4 commits into
mainfrom
claude/csharp-integration-strategy-gs41zk
Jun 15, 2026
Merged

P-013: ship the CI/CLI distribution surface (Action + dotnet tool)#10
PhysShell merged 4 commits into
mainfrom
claude/csharp-integration-strategy-gs41zk

Conversation

@PhysShell

@PhysShell PhysShell commented Jun 15, 2026

Copy link
Copy Markdown
Owner

Make the P-001 pipeline (C# -> extractor -> facts -> core) something people
can actually run on their own code, in the form that fits "one checker":
a CI/CLI surface where Python already lives, not a native Roslyn analyzer
(which would force a second checker in C# or per-keystroke shelling to Python).

Core (ownlang):

  • ownir --format {human,github,msbuild}: the finding renderer lives in the
    core, so the wrappers stay thin. github = PR annotations, msbuild = VS Error
    List, human = unchanged default. Machine formats keep stdout to annotations
    only (summary to stderr); GitHub metacharacters escaped.

Extractor (Roslyn):

  • walk directories recursively for *.cs (skip bin/obj/.git/node_modules/
    packages + generated files), so it can point at a whole repo;
  • report finding paths relative to cwd (forward slashes) so annotations land on
    the right file when names collide;
  • PackAsTool: dotnet tool install --global OwnSharp.Extractor.

Orchestration:

  • scripts/own-check.sh chains both stages (--format, --fail-on-finding);
  • action.yml composite Action wraps it; examples/ci/own-check.yml for consumers.

Tests/CI:

  • test_ownir: render-format + GitHub-escaping unit checks (24/24);
  • new own-check-surface CI job: repo scan in github + msbuild formats,
    --fail-on-finding exit code, and the composite action end-to-end.

Docs: P-013 records the decision and the three-surface cost ladder; frontend
README gains a real-repo/CI usage section; ROADMAP index updated.

https://claude.ai/code/session_01BE8MeHTtFcrTBjtMAQ7Yc6

Summary by CodeRabbit

Release Notes

  • New Features

    • Added an integrated GitHub leak-check workflow and a reusable composite GitHub Action for scanning and reporting findings.
    • Extended ownir rendering to support GitHub annotations and MSBuild/VS error output in addition to human-readable results.
    • Made the Roslyn extractor available as a .NET tool for easier local runs.
  • Documentation

    • Documented the CI/CLI “distribution surface” approach and how to run checks on real repositories.
  • Tests

    • Added coverage for output formatting across supported surfaces.

claude added 3 commits June 15, 2026 17:40
Make the P-001 pipeline (C# -> extractor -> facts -> core) something people
can actually run on their own code, in the form that fits "one checker":
a CI/CLI surface where Python already lives, not a native Roslyn analyzer
(which would force a second checker in C# or per-keystroke shelling to Python).

Core (ownlang):
- `ownir --format {human,github,msbuild}`: the finding renderer lives in the
  core, so the wrappers stay thin. github = PR annotations, msbuild = VS Error
  List, human = unchanged default. Machine formats keep stdout to annotations
  only (summary to stderr); GitHub metacharacters escaped.

Extractor (Roslyn):
- walk directories recursively for *.cs (skip bin/obj/.git/node_modules/
  packages + generated files), so it can point at a whole repo;
- report finding paths relative to cwd (forward slashes) so annotations land on
  the right file when names collide;
- PackAsTool: `dotnet tool install --global OwnSharp.Extractor`.

Orchestration:
- scripts/own-check.sh chains both stages (--format, --fail-on-finding);
- action.yml composite Action wraps it; examples/ci/own-check.yml for consumers.

Tests/CI:
- test_ownir: render-format + GitHub-escaping unit checks (24/24);
- new own-check-surface CI job: repo scan in github + msbuild formats,
  --fail-on-finding exit code, and the composite action end-to-end.

Docs: P-013 records the decision and the three-surface cost ladder; frontend
README gains a real-repo/CI usage section; ROADMAP index updated.

https://claude.ai/code/session_01BE8MeHTtFcrTBjtMAQ7Yc6
The PackAsTool comment in the csproj contained '--global', and '--' is
illegal inside an XML comment, so MSBuild refused to load the project
(every extractor job failed at build). Reword the comment without '--'.

https://claude.ai/code/session_01BE8MeHTtFcrTBjtMAQ7Yc6
…test

The own-check-surface self-test aborted with exit 134 (an unhandled .NET
exception), and the cause was invisible because the step piped the
extractor's stderr to /dev/null. Fix robustness + visibility:

- extractor: skip an input that is not a readable file instead of letting
  File.ReadAllText throw; walk directories with EnumerationOptions
  (IgnoreInaccessible) so a locked subdir cannot abort the whole scan;
- own-check.sh: drop the unproven 'dotnet run --nologo' flag;
- CI: stop redirecting the script's stderr to /dev/null, so build chatter
  and any error land in the job log (stdout still carries only annotations).

https://claude.ai/code/session_01BE8MeHTtFcrTBjtMAQ7Yc6
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@coderabbitai

coderabbitai Bot commented Jun 15, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: bca00368-0e70-42d8-a804-02875a025f1a

📥 Commits

Reviewing files that changed from the base of the PR and between 36b8f5c and 4011549.

📒 Files selected for processing (4)
  • action.yml
  • frontend/roslyn/OwnSharp.Extractor/Program.cs
  • ownlang/__main__.py
  • scripts/own-check.sh
🚧 Files skipped from review as they are similar to previous changes (4)
  • ownlang/main.py
  • scripts/own-check.sh
  • action.yml
  • frontend/roslyn/OwnSharp.Extractor/Program.cs

📝 Walkthrough

Walkthrough

Adds a CI/CLI distribution surface (P-013) for Own.NET: the Python ownir renderer gains GitHub Actions annotation and MSBuild error-list output formats; the Roslyn extractor gains repo-walk directory expansion, relative path normalization, and dotnet tool packaging metadata; a new scripts/own-check.sh orchestrates the two-stage pipeline; and a composite action.yml wraps everything for consumer CI use.

Changes

P-013 Distribution Surface

Layer / File(s) Summary
Finding renderers and CLI format dispatch
ownlang/ownir.py, ownlang/__main__.py, tests/test_ownir.py
ownir.py adds _esc_data/_esc_prop helpers, render_github(), render_msbuild() methods on Finding, and a render_finding dispatcher. __main__.py adds _FORMATS, updates cmd_ownir to accept fmt and route machine-format status lines to stderr, and extends main() to parse and validate --format. Tests verify all three format outputs and escaping behavior.
Roslyn extractor repo-walk and dotnet tool packaging
frontend/roslyn/OwnSharp.Extractor/OwnSharp.Extractor.csproj, frontend/roslyn/OwnSharp.Extractor/Program.cs
.csproj gains PackAsTool, ToolCommandName (ownsharp-extract), PackageId, Version 0.1.0, and Description. Program.cs replaces single-path input with multi-path rawInputs, adds -o flag, implements recursive .cs discovery with skip rules for build/VCS/vendor/generated files, normalizes paths to CWD-relative, and adds per-file existence guard.
own-check.sh two-stage orchestration pipeline
scripts/own-check.sh
New Bash script: parses --root, --format, --fail-on-finding, and path args; creates a temp facts file with EXIT trap; runs dotnet run extractor with stdout suppressed; runs python -m ownlang ownir and applies exit-code logic for findings vs. hard errors vs. --fail-on-finding.
Composite GitHub Action
action.yml
Defines Own.NET resource-leak check composite action with inputs for path, format, fail-on-finding, and runtime version pins; runs setup-python@v5, setup-dotnet@v4, then own-check.sh with conditionally appended --fail-on-finding.
CI surface test, example workflow, and docs
.github/workflows/ci.yml, examples/ci/own-check.yml, docs/proposals/P-013-distribution-surface.md, docs/ROADMAP.md, frontend/roslyn/README.md
CI gains own-check-surface job asserting github/msbuild output patterns, --fail-on-finding exit code, and composite action end-to-end run. examples/ci/own-check.yml provides a consumer workflow template. P-013 proposal doc, ROADMAP entry, and README section document the design, non-goals, and open questions.

Sequence Diagram(s)

sequenceDiagram
  actor Consumer as Consumer CI Job
  participant action as action.yml (composite)
  participant script as own-check.sh
  participant extractor as dotnet OwnSharp.Extractor
  participant checker as python -m ownlang ownir

  Consumer->>action: uses: PhysShell/own.net@main<br/>path, format, fail-on-finding
  action->>action: setup-python@v5, setup-dotnet@v4
  action->>script: own-check.sh --root --format [--fail-on-finding] path
  script->>extractor: dotnet run -o facts.tmp path(s)
  extractor-->>script: facts.tmp (OwnIR JSON)
  script->>checker: python -m ownlang ownir --format facts.tmp
  checker-->>script: exit 0 (clean) / 1 (findings) / 2+ (error)
  script-->>action: exit 0 or propagated finding exit code
  action-->>Consumer: annotations in github/msbuild format
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐇 Hop-hop, the rabbit checks for leaks,
In GitHub annotations it squeaks!
MSBuild errors line by line,
own-check.sh runs just fine.
A composite action wraps it neat—
No resource left un-found, how sweet! 🎉

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 72.73% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: delivering the P-013 CI/CLI distribution surface (GitHub Action + dotnet tool) for Own.NET, which is the core objective of all file changes in this PR.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/csharp-integration-strategy-gs41zk

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@action.yml`:
- Around line 49-53: The shell command in the run block directly interpolates
action inputs without proper quoting, creating a shell injection vulnerability.
Fix this by adding an env section that passes all user inputs (inputs.format and
inputs.path) as environment variables, then modify the run block to reference
these environment variables with proper quoting instead of direct template
interpolation. Specifically, replace the unquoted ${{ inputs.path }} on line 53
and the ${{ inputs.format }} reference on line 50 with references to
safely-defined environment variables, ensuring all variable expansions in the
shell command are wrapped in quotes to prevent command execution.

In `@frontend/roslyn/OwnSharp.Extractor/Program.cs`:
- Around line 133-142: The defensive check only validates file existence at line
136, but the File.ReadAllText call at line 141 can still throw exceptions for
locked or unauthorized files, causing the entire scan to abort. Wrap the
File.ReadAllText invocation in a try-catch block to handle any exceptions that
may occur during file access (such as IOException or
UnauthorizedAccessException), logging an appropriate error message via
Console.Error.WriteLine and using continue to skip that file and proceed with
the next one, consistent with the defensive intent expressed in the comment
above the existence check.

In `@ownlang/__main__.py`:
- Around line 228-248: The argument parsing loop in the while block (iterating
through rest) allows bare `--format` flags without values to be appended as
positional arguments, and extra positional arguments beyond the first are
silently ignored, both hiding CLI usage errors. After the while loop ends and
before using positional[0], add validation to reject a bare `--format` flag if
it appears in the positional list (which indicates missing its value), and
reject if there are more than one positional arguments provided. In both error
cases, print a descriptive message to sys.stderr and return exit code 2,
consistent with the existing validation pattern for unknown formats and format
misapplication.

In `@scripts/own-check.sh`:
- Around line 30-34: The `--root` and `--format` option handlers in the case
statement read `$2` without validating that the argument value exists. When
these options are invoked without a following value and `set -u` is enabled, the
script crashes with an unhelpful shell error instead of providing clear
feedback. Add validation checks before accessing `$2` for both the `--root` and
`--format` cases to ensure the argument exists, and output a descriptive error
message with usage information before exiting if a required value is missing.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: d6547ddb-f1f3-4d00-9212-4af8c0d0ce35

📥 Commits

Reviewing files that changed from the base of the PR and between 4c1b71a and 36b8f5c.

📒 Files selected for processing (12)
  • .github/workflows/ci.yml
  • action.yml
  • docs/ROADMAP.md
  • docs/proposals/P-013-distribution-surface.md
  • examples/ci/own-check.yml
  • frontend/roslyn/OwnSharp.Extractor/OwnSharp.Extractor.csproj
  • frontend/roslyn/OwnSharp.Extractor/Program.cs
  • frontend/roslyn/README.md
  • ownlang/__main__.py
  • ownlang/ownir.py
  • scripts/own-check.sh
  • tests/test_ownir.py

Comment thread action.yml Outdated
Comment thread frontend/roslyn/OwnSharp.Extractor/Program.cs
Comment thread ownlang/__main__.py
Comment thread scripts/own-check.sh
- action.yml: pass user inputs (path/format/fail-on-finding) via env vars
  instead of template-interpolating them into the run block — closes a shell
  injection vector where a crafted path would be expanded as code (Major);
- extractor: wrap File.ReadAllText in try/catch (IOException /
  UnauthorizedAccessException) so a locked/unreadable file is skipped, not an
  abort — the File.Exists gate alone did not cover it (Major);
- ownlang CLI: reject a bare --format (missing value) and more than one
  positional arg with a clear error/usage instead of a misleading file error;
- own-check.sh: validate --root/--format have a value before reading $2, so a
  malformed call under set -u returns a usage error, not a shell crash.

Verified locally: ownir 24/24, ruff + mypy --strict clean, CLI guards return 2.

https://claude.ai/code/session_01BE8MeHTtFcrTBjtMAQ7Yc6
@PhysShell PhysShell merged commit 0014acb into main Jun 15, 2026
17 checks passed
PhysShell pushed a commit that referenced this pull request Jul 12, 2026
From independent review of PR #245 (Codex + CodeRabbit both caught the
permissions gap independently; each caught one issue the other missed):

- consumer-simulation's `uses: PhysShell/Own.NET@${{ github.sha }}`
  cannot work at all: GitHub Actions does not evaluate expressions in
  `jobs.<job_id>.steps.uses` (not among the expression-capable fields
  the context-availability docs list, unlike with/env/if/run) - the
  job would never have resolved an action. There is no way to
  parameterize `uses:` with "the commit under test"; a genuinely
  dynamic remote-ref proof isn't automatable pre-tag. Switched to
  `uses: ./` (the same mechanism ci.yml's own-check-codescan dog-food
  job already relies on, correctly) - full checkout instead of a
  sparse one, since `./` needs the whole action definition present.
  docs/notes/action-marketplace-readiness.md and the fixture's own
  README corrected to match; the honest-limitation framing now
  matches what's actually achievable pre-tag.

- consumer-simulation's upload-sarif step needs security-events:write
  (required for every workflow that calls it, not just push events);
  the job only granted contents:read. Added the permission, and
  guarded the SARIF/upload steps with the same fork-PR check
  own-check-codescan already uses (a fork PR's GITHUB_TOKEN is
  read-only, so the upload would 403 through no fault of an external
  contributor) - the leak/clean checks still run for forks, only the
  SARIF steps are skipped there.

- move-major-tag's shell steps interpolated
  `${{ inputs.move_major_tag_to }}` and step outputs directly into
  `run:` bodies - a template-injection risk (flagged by zizmor via
  CodeRabbit), the same class of bug action.yml's own CodeRabbit #10
  fix already guards against elsewhere in this repo. Moved both
  through `env:` and added a SemVer-shape validation as a second,
  independent guard.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants