fix(policy): handle OSError from is_file() on macOS PATH_MAX limit#860
fix(policy): handle OSError from is_file() on macOS PATH_MAX limit#860chaobo8484 wants to merge 11 commits intomicrosoft:mainfrom
Conversation
When load_policy() receives a YAML string that exceeds ~1023 bytes, the is_file() syscall fails on macOS (PATH_MAX ≈ 1024) with OSError [Errno 63] File name too long. Wrap the call in try/except to gracefully fall back to treating the input as a YAML string. Fixes microsoft#848
There was a problem hiding this comment.
Pull request overview
Fixes load_policy() to avoid crashing on macOS when given a long YAML string that triggers Path.is_file() to raise OSError: [Errno 63] File name too long, preserving the intended "path or YAML content" input behavior.
Changes:
- Wraps the
Path.is_file()probe intry/except OSErrorand falls back to treating the input as YAML content when the probe fails.
Show a summary per file
| File | Description |
|---|---|
src/apm_cli/policy/parser.py |
Adds defensive handling around Path.is_file() so long YAML inputs do not raise on macOS PATH_MAX limits. |
Copilot's findings
- Files reviewed: 1/1 changed files
- Comments generated: 2
danielmeppiel
left a comment
There was a problem hiding this comment.
Per Copilot reviewer
* docs(ci): document merge-gate architecture and ruleset context gotcha
- Document merge-gate.yml as the single-authority PR-time aggregator
- Mark ci-integration-pr-stub.yml as DEPRECATED (slated for deletion)
- Renumber workflow list (now 6 entries, was misnumbered with two #3s)
- New section: Branch Protection & Required Checks
- Ruleset 'context' field MUST match check-run name ('gate'), not the
UI display string ('Merge Gate / gate'). Storing the display string
causes permanent 'Expected - Waiting for status to be reported' that
blocked PR #860 today
- Adding new required checks goes through EXPECTED_CHECKS in
merge-gate.yml, not the ruleset
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* chore(ci): remove deprecated PR-time stub workflow
The four PR stubs (Build/Smoke/Integration/Release Validation - Linux)
were a holdover from the pre-merge-gate model where branch protection
required each Tier 2 check name directly. After #867, branch protection
requires only the single 'gate' check from merge-gate.yml, so the stubs
are dead weight that fire on every PR for no reason.
Changes:
- Delete .github/workflows/ci-integration-pr-stub.yml
- Reduce EXPECTED_CHECKS in merge-gate.yml to just 'Build & Test (Linux)'
(the only PR-time check we still emit)
- Update merge-gate.yml + ci-integration.yml header comments
- Update cicd.instructions.md (drop DEPRECATED entry, renumber to 5
workflows)
- Drop stale CODEOWNERS reference to the deleted file
- CHANGELOG entry under [Unreleased] > Removed
Stacked on #874 (docs).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
@danielmeppiel I have made adjustments according to Copilot's suggestion.Have a good day! |
DevX UX Review — PR #860Scope: CLI error ergonomics & silent-failure risk. No command surface / flag / help-text changes in this PR — review is limited to internal Findings
Verdict: Ship it. Clean defensive fix, no UX regressions, no silent failures introduced. 👍
|
APM Review Panel VerdictDisposition: APPROVE (with one minor pre-merge fix: CHANGELOG entry) Per-persona findingsPython Architect: Routine bug-fix PR. One helper extracted ( OO / class diagram classDiagram
class ApmPolicy {
<<dataclass>>
+name: str
+version: str
+enforcement: str
}
class load_policy:::touched {
<<function>>
+source: Union[str, Path]
+returns: Tuple[ApmPolicy, List[str]]
}
class _looks_like_yaml_content:::touched {
<<function>>
+source: str
+returns: bool
}
class _build_policy {
<<function>>
+data: dict
+returns: ApmPolicy
}
load_policy:::touched ..> _looks_like_yaml_content:::touched : calls (new guard)
load_policy:::touched ..> _build_policy : calls
_build_policy ..> ApmPolicy : creates
note for _looks_like_yaml_content "Guard: avoids Path.is_file() on large\nstrings (macOS ENAMETOOLONG fix)"
note for load_policy "Fixed: OSError ENAMETOOLONG caught\nand treated as is_file=False"
Execution-flow diagram flowchart TD
A["load_policy(source)"] --> B{"isinstance(source, Path)?"}
B -- Yes --> C["source.read_text() if is_file else str(source)"]
B -- No --> D{"_looks_like_yaml_content(source)?<br/>(newline, YAML marker, key: val)"}
D -- Yes --> E["raw = source (skip filesystem probe)"]
D -- No --> F["path = Path(source)"]
F --> G["try: path.is_file()"]
G -- "OSError ENAMETOOLONG" --> H["is_file = False"]
G -- "other OSError" --> I["re-raise"]
G -- success --> J{"is_file?"}
J -- Yes --> K["raw = path.read_text()"]
J -- No --> L["raw = source"]
H --> L
E --> M["yaml.safe_load(raw)"]
K --> M
L --> M
M --> N["_build_policy(data)"]
N --> O["return ApmPolicy, warnings"]
Design patterns: Guard clause ( Coverage gap (not a blocker): The test exercises only the CLI Logging Expert: No output, logging, DevX UX Expert: No CLI command surface, flag, help text, or user-facing error message changes. The fix is transparent to users (silent crash eliminated on macOS). No documentation update required -- no command surface changed. No UX regression. Supply Chain Security Expert: Auth Expert: Not activated -- changed files ( OSS Growth Hacker: macOS is the primary developer platform for APM's target audience. A crash when loading large inline policy strings is a trust regression that disproportionately hits enterprise users (who are more likely to have complex, multi-line policies). The fix is correct and the test is appropriate. One missing item: no CHANGELOG entry. Per repo convention, every code change needs a CEO arbitrationThe panel is unanimous and the findings are clean. This is a targeted, non-breaking, correct bug fix for a real macOS platform crash. There are no architectural concerns, no security regressions, no UX changes, and no auth implications. The only gap is the missing Required actions before merge
Optional follow-ups
|
When load_policy() receives a YAML string that exceeds ~1023 bytes, the is_file() syscall fails on macOS (PATH_MAX ≈ 1024) with OSError [Errno 63] File name too long. Wrap the call in try/except to gracefully fall back to treating the input as a YAML string.
Fixes #848
Description
Brief description of changes and motivation.
Fixes # (issue)
Type of change
Testing