Skip to content

fix(openapi): fix the problem of keeping the server running after make openapi and make api.json deterministically ordered#1438

Open
Artifizer wants to merge 7 commits intocyberfabric:mainfrom
Artifizer:main
Open

fix(openapi): fix the problem of keeping the server running after make openapi and make api.json deterministically ordered#1438
Artifizer wants to merge 7 commits intocyberfabric:mainfrom
Artifizer:main

Conversation

@Artifizer
Copy link
Copy Markdown
Contributor

@Artifizer Artifizer commented Apr 4, 2026

fix(openapi): fix the problem of keeping the server running after make openapi
build(openapi): make generated api.json deterministically ordered
fix(tests): allow mini-chat tests to be running on Python 3.9 to fix 'make all' on macOS
chore: Makefile - add clear congratulations message in the end of 'make all'

The PR has breaking-api-acknowledged because it now has properly regenerated API spec file

Summary by CodeRabbit

  • Improvements
    • OpenAPI specification generation now produces deterministically ordered output, ensuring consistent results across builds and reducing spurious version control diffs.
    • Enhanced build process with improved server startup health checks and automatic process cleanup for greater reliability.

…ke openapi`

The problem was that when one run `make openapi` or `make all`, the server
ramained running after preventing repetitive make targets execution

What was changed:
- Extract server startup and cleanup into reusable start_server_and_wait macro
  with cross-platform support (Linux, macOS, Windows)
- Simplify openapi recipe by using the new macro

Signed-off-by: Artifizer <artifizer@gmail.com>
Refactor `make openapi` target. Rationale: avoids non-deterministic schema
ordering and noisy git diffs; improves build reproducibility and maintainability.

1. Use BTreeMap for OpenAPI components registry to produce stable, alphabetically
   ordered schema output (replace HashMap -> BTreeMap).

2. Add `scripts/sort_openapi_json.py` and invoke it from Makefile to post-process
   the fetched OpenAPI JSON, ensuring deterministic key ordering and stable diffs.

3. Regenerated/sorted `docs/api/api.json`

Signed-off-by: Artifizer <artifizer@gmail.com>
@Artifizer Artifizer requested a review from modcrafter77 April 4, 2026 13:04
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 4, 2026

📝 Walkthrough

Walkthrough

These changes establish deterministic ordering of OpenAPI specifications across the build pipeline: the Rust registry replaces HashMap with BTreeMap for ordered component schema iteration, a new Python script recursively sorts all JSON keys, and the Makefile refactors server startup/cleanup into a reusable macro while integrating the sorting step. Additionally, test files are updated with postponed type annotation evaluation.

Changes

Cohort / File(s) Summary
OpenAPI Deterministic Ordering
libs/modkit/src/api/openapi_registry.rs, scripts/sort_openapi_json.py
Changed components registry from HashMap to BTreeMap for ordered schema iteration; added new Python script to recursively sort all OpenAPI JSON dictionary keys with UTF-8 safe output and trailing newline.
Build Infrastructure Refactoring
Makefile
Added reusable start_server_and_wait macro with background process management, health check polling with exponential backoff, and trap-based cleanup; refactored openapi target to use macro and integrate sorting script post-processing; updated all target completion banner.
Type Annotation Modernization
testing/e2e/modules/mini_chat/test_*.py, testing/e2e/modules/oagw/mock_upstream.py
Added from __future__ import annotations to 8 test files, enabling postponed evaluation of type annotations across modules without functional changes.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related issues

Suggested reviewers

  • MikeFalcon77

Poem

🐰 A macro hops to organize,
BTreeMaps in sorted guise,
JSON keys arranged with care,
Deterministic specs everywhere!
Type hints deferred, the future's bright,

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the two main fixes: server cleanup after make openapi and deterministic ordering of api.json.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Signed-off-by: Artifizer <artifizer@gmail.com>
…'make all' on macOS

Signed-off-by: Artifizer <artifizer@gmail.com>
…ke all'

Signed-off-by: Artifizer <artifizer@gmail.com>
Signed-off-by: Artifizer <artifizer@gmail.com>
@Artifizer Artifizer marked this pull request as ready for review April 4, 2026 19:53
@qodo-code-review
Copy link
Copy Markdown

Review Summary by Qodo

Fix server cleanup in openapi target and ensure deterministic API spec ordering

🐞 Bug fix ✨ Enhancement

Grey Divider

Walkthroughs

Description
• Fix server process cleanup issue in make openapi target
• Ensure deterministic OpenAPI JSON ordering via BTreeMap and sorting script
• Add Python 3.9 compatibility to mini-chat tests with __future__ imports
• Improve user experience with congratulations message in make all
Diagram
flowchart LR
  A["Makefile openapi target"] -->|"Extract macro"| B["start_server_and_wait macro"]
  B -->|"Cross-platform support"| C["Linux/macOS/Windows cleanup"]
  D["HashMap components registry"] -->|"Replace with"| E["BTreeMap"]
  E -->|"Deterministic ordering"| F["sort_openapi_json.py script"]
  F -->|"Post-process"| G["Sorted api.json"]
  H["Mini-chat test files"] -->|"Add import"| I["from __future__ import annotations"]
  I -->|"Python 3.9 compatible"| J["Tests pass on macOS"]
Loading

Grey Divider

File Changes

1. libs/modkit/src/api/openapi_registry.rs ✨ Enhancement +7/-6

Replace HashMap with BTreeMap for deterministic ordering

libs/modkit/src/api/openapi_registry.rs


2. scripts/sort_openapi_json.py ✨ Enhancement +63/-0

New script to recursively sort OpenAPI JSON keys

scripts/sort_openapi_json.py


3. testing/e2e/modules/mini_chat/test_principles.py 🐞 Bug fix +2/-0

Add future annotations import for Python 3.9

testing/e2e/modules/mini_chat/test_principles.py


View more (9)
4. testing/e2e/modules/mini_chat/test_cleanup.py 🐞 Bug fix +2/-0

Add future annotations import for Python 3.9

testing/e2e/modules/mini_chat/test_cleanup.py


5. testing/e2e/modules/mini_chat/test_quota_status.py 🐞 Bug fix +2/-0

Add future annotations import for Python 3.9

testing/e2e/modules/mini_chat/test_quota_status.py


6. testing/e2e/modules/mini_chat/test_quota_enforcement.py 🐞 Bug fix +2/-0

Add future annotations import for Python 3.9

testing/e2e/modules/mini_chat/test_quota_enforcement.py


7. testing/e2e/modules/mini_chat/test_code_interpreter_usage.py 🐞 Bug fix +2/-0

Add future annotations import for Python 3.9

testing/e2e/modules/mini_chat/test_code_interpreter_usage.py


8. testing/e2e/modules/mini_chat/test_web_search_usage.py 🐞 Bug fix +2/-0

Add future annotations import for Python 3.9

testing/e2e/modules/mini_chat/test_web_search_usage.py


9. testing/e2e/modules/mini_chat/test_full_scenario.py 🐞 Bug fix +2/-0

Add future annotations import for Python 3.9

testing/e2e/modules/mini_chat/test_full_scenario.py


10. testing/e2e/modules/oagw/mock_upstream.py 🐞 Bug fix +2/-0

Add future annotations import for Python 3.9

testing/e2e/modules/oagw/mock_upstream.py


11. Makefile 🐞 Bug fix +99/-22

Extract server macro, refactor openapi target, add completion message

Makefile


12. docs/api/api.json ⚙️ Configuration changes +7169/-7168

Regenerated with deterministically sorted keys

docs/api/api.json


Grey Divider

Qodo Logo

@qodo-code-review
Copy link
Copy Markdown

qodo-code-review bot commented Apr 4, 2026

Code Review by Qodo

🐞 Bugs (3) 📘 Rule violations (0) 📎 Requirement gaps (0) 🎨 UX Issues (0)

Grey Divider


Action required

1. Stray @ breaks openapi 🐞 Bug ≡ Correctness
Description
In openapi, the second backslash-continued line starts with @$(call ...), so the @ is passed
to the shell (not treated as a Makefile recipe prefix) and will likely fail as an invalid command.
This can break make openapi (and therefore make all).
Code

Makefile[R328-329]

+	@$(call start_server_and_wait,cargo run --bin hyperspot-server $(E2E_ARGS) -- --config config/quickstart.yaml,$(OPENAPI_URL),300); \
+	@$(call start_server_and_wait,cargo run --bin hyperspot-server $(E2E_ARGS) -- --config config/quickstart.yaml,$(OPENAPI_URL),300); \
Evidence
The openapi recipe uses \ line continuations, making line 329 part of the same shell command
started on line 328; in that context the leading @ is no longer a make modifier and becomes
literal shell input.

Makefile[324-335]
Makefile[38-102]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The `openapi` target has a backslash-continued command sequence where the second continued line begins with `@$(call ...)`. Because it is not the first physical recipe line, `@` is not processed by `make` and is passed to the shell, breaking the command.

### Issue Context
This currently makes `make openapi` unreliable/fail and `make all` depends on `openapi`.

### Fix Focus Areas
- Makefile[324-335]

### Suggested fix
- Remove the second `@` (or remove the entire duplicated `start_server_and_wait` line—see related issue) so continuation lines start with valid shell syntax.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Server started twice 🐞 Bug ☼ Reliability
Description
The openapi target calls start_server_and_wait twice for the same command/URL, which can mask a
failed second start (e.g., port already in use) because readiness is checked only via curl
success. This can leave an unexpected server process running and produce false-positive success.
Code

Makefile[R328-334]

+	@$(call start_server_and_wait,cargo run --bin hyperspot-server $(E2E_ARGS) -- --config config/quickstart.yaml,$(OPENAPI_URL),300); \
+	@$(call start_server_and_wait,cargo run --bin hyperspot-server $(E2E_ARGS) -- --config config/quickstart.yaml,$(OPENAPI_URL),300); \
+	echo "Fetching OpenAPI spec..."; \
	mkdir -p $$(dirname "$(OPENAPI_OUT)"); \
	curl -fsS "$(OPENAPI_URL)" -o "$(OPENAPI_OUT)"; \
-	echo "OpenAPI spec saved to $(OPENAPI_OUT)"; \
-	echo "Stopping hyperspot-server..."; \
-	kill $$SERVER_PID >/dev/null 2>&1 || true; \
-	wait $$SERVER_PID 2>/dev/null || true
+	echo "Sorting OpenAPI JSON for deterministic ordering..."; \
+	python3 scripts/sort_openapi_json.py "$(OPENAPI_OUT)"; \
Evidence
openapi invokes start_server_and_wait twice with identical parameters. In
start_server_and_wait, the is_process_running check happens only inside the while ! curl ...
loop; if curl succeeds immediately (because an earlier instance is already serving the URL), the
loop is skipped and the new SERVER_PID is never validated, while cleanup only tracks the last
SERVER_PID value.

Makefile[324-335]
Makefile[38-102]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`make openapi` starts the server twice, and the readiness check can succeed even when the second process died (e.g., bind failure) because it only checks `curl` success, not that the newly started PID is still alive.

### Issue Context
This can lead to false success and/or leave a stray server process running, defeating the PR's goal of cleaning up after OpenAPI generation.

### Fix Focus Areas
- Makefile[324-335]
- Makefile[38-102]

### Suggested fix
1) Remove the duplicated second `start_server_and_wait` invocation in the `openapi` recipe.
2) In `start_server_and_wait`, add a post-loop check right after `curl` succeeds:
  - If `! is_process_running $SERVER_PID`, print an error referencing the log file and exit non-zero.
  This ensures success implies the process you just started is actually alive.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Advisory comments

3. Misspelled success message 🐞 Bug ⚙ Maintainability
Description
The all target prints "CONTGRATULATIONS" (misspelled), which is user-facing output. This reduces
professionalism of the build output.
Code

Makefile[R681-683]

+	@echo "============================================================="
+	@echo "  CONTGRATULATIONS! All 'make all' tasks have been completed!"
+	@echo ""
Evidence
The echoed completion banner contains the misspelled word in the all recipe output.

Makefile[678-689]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The `make all` completion banner contains a spelling error: "CONTGRATULATIONS".

### Fix Focus Areas
- Makefile[680-689]

### Suggested fix
Change `CONTGRATULATIONS` to `CONGRATULATIONS` in the echoed banner line.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

Makefile Outdated
Comment on lines +328 to +329
@$(call start_server_and_wait,cargo run --bin hyperspot-server $(E2E_ARGS) -- --config config/quickstart.yaml,$(OPENAPI_URL),300); \
@$(call start_server_and_wait,cargo run --bin hyperspot-server $(E2E_ARGS) -- --config config/quickstart.yaml,$(OPENAPI_URL),300); \
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

1. Stray @ breaks openapi 🐞 Bug ≡ Correctness

In openapi, the second backslash-continued line starts with @$(call ...), so the @ is passed
to the shell (not treated as a Makefile recipe prefix) and will likely fail as an invalid command.
This can break make openapi (and therefore make all).
Agent Prompt
### Issue description
The `openapi` target has a backslash-continued command sequence where the second continued line begins with `@$(call ...)`. Because it is not the first physical recipe line, `@` is not processed by `make` and is passed to the shell, breaking the command.

### Issue Context
This currently makes `make openapi` unreliable/fail and `make all` depends on `openapi`.

### Fix Focus Areas
- Makefile[324-335]

### Suggested fix
- Remove the second `@` (or remove the entire duplicated `start_server_and_wait` line—see related issue) so continuation lines start with valid shell syntax.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +328 to +334
@$(call start_server_and_wait,cargo run --bin hyperspot-server $(E2E_ARGS) -- --config config/quickstart.yaml,$(OPENAPI_URL),300); \
@$(call start_server_and_wait,cargo run --bin hyperspot-server $(E2E_ARGS) -- --config config/quickstart.yaml,$(OPENAPI_URL),300); \
echo "Fetching OpenAPI spec..."; \
mkdir -p $$(dirname "$(OPENAPI_OUT)"); \
curl -fsS "$(OPENAPI_URL)" -o "$(OPENAPI_OUT)"; \
echo "OpenAPI spec saved to $(OPENAPI_OUT)"; \
echo "Stopping hyperspot-server..."; \
kill $$SERVER_PID >/dev/null 2>&1 || true; \
wait $$SERVER_PID 2>/dev/null || true
echo "Sorting OpenAPI JSON for deterministic ordering..."; \
python3 scripts/sort_openapi_json.py "$(OPENAPI_OUT)"; \
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

2. Server started twice 🐞 Bug ☼ Reliability

The openapi target calls start_server_and_wait twice for the same command/URL, which can mask a
failed second start (e.g., port already in use) because readiness is checked only via curl
success. This can leave an unexpected server process running and produce false-positive success.
Agent Prompt
### Issue description
`make openapi` starts the server twice, and the readiness check can succeed even when the second process died (e.g., bind failure) because it only checks `curl` success, not that the newly started PID is still alive.

### Issue Context
This can lead to false success and/or leave a stray server process running, defeating the PR's goal of cleaning up after OpenAPI generation.

### Fix Focus Areas
- Makefile[324-335]
- Makefile[38-102]

### Suggested fix
1) Remove the duplicated second `start_server_and_wait` invocation in the `openapi` recipe.
2) In `start_server_and_wait`, add a post-loop check right after `curl` succeeds:
   - If `! is_process_running $SERVER_PID`, print an error referencing the log file and exit non-zero.
   This ensures success implies the process you just started is actually alive.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@Makefile`:
- Around line 328-334: The recipe that fetches and sorts the OpenAPI spec should
fail fast so curl/python errors don't get masked; update the Makefile recipe
that runs start_server_and_wait and the subsequent commands (the block invoking
curl -fsS "$(OPENAPI_URL)" -o "$(OPENAPI_OUT)" and python3
scripts/sort_openapi_json.py "$(OPENAPI_OUT)") to enable errexit (e.g., add set
-e or set -euo pipefail at the start of the shell invocation) or chain commands
with && so any failure aborts the target, ensuring failures in curl or the sort
script surface immediately.

In `@scripts/sort_openapi_json.py`:
- Around line 44-57: Wrap file read and write operations around explicit OSError
handling so filesystem errors don't produce raw tracebacks: when opening/reading
the file_path before json.load and when opening/writing the file_path for
json.dump, catch OSError (or IOError) and print a clear error to stderr
(including the exception message), then sys.exit(1); keep existing
JSONDecodeError handling and continue using sort_dict_recursive and json.dump as
before but ensure both read and write I/O are guarded.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6097bba4-cc28-4406-95d6-a50a101fa563

📥 Commits

Reviewing files that changed from the base of the PR and between 12020ac and 49eacf7.

📒 Files selected for processing (12)
  • Makefile
  • docs/api/api.json
  • libs/modkit/src/api/openapi_registry.rs
  • scripts/sort_openapi_json.py
  • testing/e2e/modules/mini_chat/test_cleanup.py
  • testing/e2e/modules/mini_chat/test_code_interpreter_usage.py
  • testing/e2e/modules/mini_chat/test_full_scenario.py
  • testing/e2e/modules/mini_chat/test_principles.py
  • testing/e2e/modules/mini_chat/test_quota_enforcement.py
  • testing/e2e/modules/mini_chat/test_quota_status.py
  • testing/e2e/modules/mini_chat/test_web_search_usage.py
  • testing/e2e/modules/oagw/mock_upstream.py

Comment on lines +328 to +334
@$(call start_server_and_wait,cargo run --bin hyperspot-server $(E2E_ARGS) -- --config config/quickstart.yaml,$(OPENAPI_URL),300); \
echo "Fetching OpenAPI spec..."; \
mkdir -p $$(dirname "$(OPENAPI_OUT)"); \
curl -fsS "$(OPENAPI_URL)" -o "$(OPENAPI_OUT)"; \
echo "OpenAPI spec saved to $(OPENAPI_OUT)"; \
echo "Stopping hyperspot-server..."; \
kill $$SERVER_PID >/dev/null 2>&1 || true; \
wait $$SERVER_PID 2>/dev/null || true
echo "Sorting OpenAPI JSON for deterministic ordering..."; \
python3 scripts/sort_openapi_json.py "$(OPENAPI_OUT)"; \
echo "OpenAPI spec saved to $(OPENAPI_OUT)"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify whether openapi recipe uses semicolon chaining without fail-fast.
rg -n -A8 -B2 '^openapi:' Makefile
rg -n 'set -e' Makefile

Repository: cyberfabric/cyberfabric-core

Length of output: 718


🏁 Script executed:

# Verify the complete openapi target to confirm all lines and context
rg -n -A10 '^openapi:' Makefile

Repository: cyberfabric/cyberfabric-core

Length of output: 709


Add set -e to fail fast on fetch/sort errors.

This command chain uses semicolons without set -e, so a failed curl or python3 command will still allow subsequent echo statements to execute and mask the failure with a successful exit code. Since openapi is part of the default build, this creates a risk of silently corrupted builds.

Proposed fix
-	@$(call start_server_and_wait,cargo run --bin hyperspot-server $(E2E_ARGS) -- --config config/quickstart.yaml,$(OPENAPI_URL),300); \
+	`@set` -e; \
+	$(call start_server_and_wait,cargo run --bin hyperspot-server $(E2E_ARGS) -- --config config/quickstart.yaml,$(OPENAPI_URL),300); \
 	echo "Fetching OpenAPI spec..."; \
 	mkdir -p $$(dirname "$(OPENAPI_OUT)"); \
 	curl -fsS "$(OPENAPI_URL)" -o "$(OPENAPI_OUT)"; \
 	echo "Sorting OpenAPI JSON for deterministic ordering..."; \
 	python3 scripts/sort_openapi_json.py "$(OPENAPI_OUT)"; \
 	echo "OpenAPI spec saved to $(OPENAPI_OUT)"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@$(call start_server_and_wait,cargo run --bin hyperspot-server $(E2E_ARGS) -- --config config/quickstart.yaml,$(OPENAPI_URL),300); \
echo "Fetching OpenAPI spec..."; \
mkdir -p $$(dirname "$(OPENAPI_OUT)"); \
curl -fsS "$(OPENAPI_URL)" -o "$(OPENAPI_OUT)"; \
echo "OpenAPI spec saved to $(OPENAPI_OUT)"; \
echo "Stopping hyperspot-server..."; \
kill $$SERVER_PID >/dev/null 2>&1 || true; \
wait $$SERVER_PID 2>/dev/null || true
echo "Sorting OpenAPI JSON for deterministic ordering..."; \
python3 scripts/sort_openapi_json.py "$(OPENAPI_OUT)"; \
echo "OpenAPI spec saved to $(OPENAPI_OUT)"
`@set` -e; \
$(call start_server_and_wait,cargo run --bin hyperspot-server $(E2E_ARGS) -- --config config/quickstart.yaml,$(OPENAPI_URL),300); \
echo "Fetching OpenAPI spec..."; \
mkdir -p $$(dirname "$(OPENAPI_OUT)"); \
curl -fsS "$(OPENAPI_URL)" -o "$(OPENAPI_OUT)"; \
echo "Sorting OpenAPI JSON for deterministic ordering..."; \
python3 scripts/sort_openapi_json.py "$(OPENAPI_OUT)"; \
echo "OpenAPI spec saved to $(OPENAPI_OUT)"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Makefile` around lines 328 - 334, The recipe that fetches and sorts the
OpenAPI spec should fail fast so curl/python errors don't get masked; update the
Makefile recipe that runs start_server_and_wait and the subsequent commands (the
block invoking curl -fsS "$(OPENAPI_URL)" -o "$(OPENAPI_OUT)" and python3
scripts/sort_openapi_json.py "$(OPENAPI_OUT)") to enable errexit (e.g., add set
-e or set -euo pipefail at the start of the shell invocation) or chain commands
with && so any failure aborts the target, ensuring failures in curl or the sort
script surface immediately.

Comment on lines +44 to +57
try:
with open(file_path, 'r', encoding='utf-8') as f:
data = json.load(f)
except json.JSONDecodeError as e:
print(f"Error: Failed to parse JSON: {e}", file=sys.stderr)
sys.exit(1)

# Sort all keys recursively
sorted_data = sort_dict_recursive(data)

# Write back with consistent formatting
with open(file_path, 'w', encoding='utf-8') as f:
json.dump(sorted_data, f, indent=2, ensure_ascii=False)
f.write('\n') # Add trailing newline
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Handle file I/O errors explicitly for stable CLI behavior.

The script currently handles JSON parsing errors but not read/write OSError cases, so users can still get raw tracebacks for common failures (e.g., directory path, permission denied).

💡 Proposed fix
-    try:
-        with open(file_path, 'r', encoding='utf-8') as f:
-            data = json.load(f)
-    except json.JSONDecodeError as e:
-        print(f"Error: Failed to parse JSON: {e}", file=sys.stderr)
-        sys.exit(1)
+    try:
+        with open(file_path, 'r', encoding='utf-8') as f:
+            data = json.load(f)
+    except json.JSONDecodeError as e:
+        print(f"Error: Failed to parse JSON: {e}", file=sys.stderr)
+        sys.exit(1)
+    except OSError as e:
+        print(f"Error: Failed to read '{file_path}': {e}", file=sys.stderr)
+        sys.exit(1)
@@
-    with open(file_path, 'w', encoding='utf-8') as f:
-        json.dump(sorted_data, f, indent=2, ensure_ascii=False)
-        f.write('\n')  # Add trailing newline
+    try:
+        with open(file_path, 'w', encoding='utf-8') as f:
+            json.dump(sorted_data, f, indent=2, ensure_ascii=False)
+            f.write('\n')  # Add trailing newline
+    except OSError as e:
+        print(f"Error: Failed to write '{file_path}': {e}", file=sys.stderr)
+        sys.exit(1)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
try:
with open(file_path, 'r', encoding='utf-8') as f:
data = json.load(f)
except json.JSONDecodeError as e:
print(f"Error: Failed to parse JSON: {e}", file=sys.stderr)
sys.exit(1)
# Sort all keys recursively
sorted_data = sort_dict_recursive(data)
# Write back with consistent formatting
with open(file_path, 'w', encoding='utf-8') as f:
json.dump(sorted_data, f, indent=2, ensure_ascii=False)
f.write('\n') # Add trailing newline
try:
with open(file_path, 'r', encoding='utf-8') as f:
data = json.load(f)
except json.JSONDecodeError as e:
print(f"Error: Failed to parse JSON: {e}", file=sys.stderr)
sys.exit(1)
except OSError as e:
print(f"Error: Failed to read '{file_path}': {e}", file=sys.stderr)
sys.exit(1)
# Sort all keys recursively
sorted_data = sort_dict_recursive(data)
# Write back with consistent formatting
try:
with open(file_path, 'w', encoding='utf-8') as f:
json.dump(sorted_data, f, indent=2, ensure_ascii=False)
f.write('\n') # Add trailing newline
except OSError as e:
print(f"Error: Failed to write '{file_path}': {e}", file=sys.stderr)
sys.exit(1)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/sort_openapi_json.py` around lines 44 - 57, Wrap file read and write
operations around explicit OSError handling so filesystem errors don't produce
raw tracebacks: when opening/reading the file_path before json.load and when
opening/writing the file_path for json.dump, catch OSError (or IOError) and
print a clear error to stderr (including the exception message), then
sys.exit(1); keep existing JSONDecodeError handling and continue using
sort_dict_recursive and json.dump as before but ensure both read and write I/O
are guarded.

@MikeFalcon77
Copy link
Copy Markdown
Collaborator

windows test will be fixed at the my PR (real problem of two simulteneous cases for single select! - biased will be used)

@MikeFalcon77
Copy link
Copy Markdown
Collaborator

MikeFalcon77 commented Apr 4, 2026

windows test will be fixed at the my PR (real problem of two simulteneous cases for single select! - biased will be used)

But it will be better to do it in this PR. @Artifizer could you please do the following:

pub fn poker(
    interval: Duration,
    cancel: CancellationToken,
) -> (Arc<Notify>, tokio::task::JoinHandle<()>) {
    let notify = Arc::new(Notify::new());
    let n = notify.clone();
    let handle = tokio::spawn(async move {
        loop {
            tokio::select! {
+              biased;
                () = cancel.cancelled() => break,
                () = tokio::time::sleep(interval) => { n.notify_one(); }
            }
        }
    });
    (notify, handle)
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants