Skip to content

Docfx/context7 chat#54

Merged
gimlichael merged 10 commits intomainfrom
docfx/context7-chat
Feb 18, 2026
Merged

Docfx/context7 chat#54
gimlichael merged 10 commits intomainfrom
docfx/context7-chat

Conversation

@gimlichael
Copy link
Member

@gimlichael gimlichael commented Feb 18, 2026

This pull request introduces a robust automation system for managing dependency updates and downstream notifications across repositories. The main focus is on adding GitHub Actions workflows and supporting scripts to enable automatic service updates when dependencies are released, as well as propagating those updates to downstream repositories. Additionally, it includes some configuration and documentation improvements.

Key changes:

GitHub Actions Workflows and Automation

  • Added .github/workflows/service-update.yml to automate dependency/service updates, including bumping NuGet packages, updating release notes, changelog, Docker tags, and opening a pull request with all changes. This workflow is triggered by repository dispatch events or manual triggers and supports dry runs.
  • Added .github/workflows/trigger-downstream.yml to automatically dispatch service update events to downstream repositories when a new release is published, ensuring dependent repos stay up-to-date.
  • Introduced .github/scripts/bump-nuget.py, a Python script that bumps NuGet package versions in Directory.Packages.props by either using a triggered version or querying the NuGet API for the latest stable version.
  • Added .github/dispatch-targets.json to define the list of downstream repositories that should receive update notifications.

Development and Documentation Configuration

  • Added a comprehensive .editorconfig file to standardize code formatting and analyzer rules across the codebase, with detailed comments and rationale for each rule.
  • Updated .docfx/docfx.json to include a custom template path, likely to support further documentation customization.
  • Added a main.js script under .docfx/templates/modern/public/ to inject a support widget into documentation pages, enhancing user support experience.

Summary by CodeRabbit

  • Documentation

    • Enhanced documentation templates and visualization
    • Added widget integration for improved documentation UI
    • Introduced comprehensive project guidelines
  • Chores

    • Improved code editor and style configuration standards
    • Enhanced CI/CD automation for service updates and dependency management
    • Refined repository infrastructure and dispatch workflows

@gimlichael gimlichael self-assigned this Feb 18, 2026
Copilot AI review requested due to automatic review settings February 18, 2026 19:22
@coderabbitai
Copy link

coderabbitai bot commented Feb 18, 2026

Warning

Rate limit exceeded

@gimlichael has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 21 minutes and 21 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📝 Walkthrough

Walkthrough

This PR introduces automation infrastructure for service updates, including dispatch targets, NuGet version bumping scripts, and GitHub Actions workflows. It also adds DocFX template configuration, editor configuration, Context7 widget integration for documentation, and AI agent guidelines.

Changes

Cohort / File(s) Summary
Configuration & Editor Setup
.editorconfig, .docfx/docfx.json
Adds comprehensive editor config with UTF-8, LF line endings, 2-space indentation, and Roslyn analyzer disables. Updates DocFX to load templates/modern template.
Documentation & Guidelines
AGENTS.md
Adds comprehensive documentation for AI agents working on the Codebelt.Extensions.Xunit project, including project overview, build commands, conventions, testing guidance, and workflow guidelines.
Context7 Widget Integration
.docfx/templates/modern/public/main.js
New JavaScript module that dynamically injects a Context7 widget script into documentation with configured data attributes for library, color, position, and placeholder.
Automation Infrastructure
.github/dispatch-targets.json, .github/scripts/bump-nuget.py
Defines dispatch targets for downstream repositories and introduces Python script to synchronize PackageVersion entries in Directory.Packages.props by querying NuGet V3 API for latest stable versions or using trigger-provided versions.
GitHub Actions Workflows
.github/workflows/trigger-downstream.yml, .github/workflows/service-update.yml
Two new workflows: trigger-downstream reads dispatch targets and sends repository_dispatch events to downstream repos; service-update processes updates to NuGet packages, CHANGELOG, Docker tags, and NGINX versions, then creates a PR.

Sequence Diagram(s)

sequenceDiagram
    participant Release as Release Event
    participant Trigger as trigger-downstream
    participant DispatchAPI as GitHub API
    participant ServiceUpdate as Service Update Workflow
    participant NuGet as NuGet API
    participant Props as Directory.Packages.props
    participant CHANGELOG as CHANGELOG.md
    participant PR as Pull Request

    Release->>Trigger: Triggered on release publication
    Trigger->>Trigger: Read dispatch-targets.json
    Trigger->>DispatchAPI: POST repository_dispatch to each target
    DispatchAPI->>ServiceUpdate: Trigger workflow_dispatch event

    ServiceUpdate->>ServiceUpdate: Read trigger inputs (source_repo, version)
    ServiceUpdate->>NuGet: Query latest versions for packages
    ServiceUpdate->>Props: Bump PackageVersion entries
    ServiceUpdate->>CHANGELOG: Update with new version entry
    ServiceUpdate->>ServiceUpdate: Update Docker/NGINX versions if applicable
    ServiceUpdate->>PR: Create PR with changes and assign reviewer
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related PRs

  • V10.0.7/service update #44: Introduces the same CI workflows, bump-nuget script, and dispatch targets infrastructure that form the core of this automation system.
  • Add context7.json with URL and public key #51: Integrates the Context7 external service configuration that pairs with the Context7 widget script injection added in this PR.
  • V10.0.6/service update #43: Demonstrates the actual service-update execution (package version bumps, changelog updates, Docker image changes) that the workflows and scripts in this PR automate.

Suggested labels

codex

Poem

🐰 A rabbit hops through workflows new,
Dispatch targets and bumps coming through,
From NuGet to downstream flows so bright,
Context7 widgets, configured just right,
Automation magic—what a delight! ✨

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'Docfx/context7 chat' is vague and does not clearly summarize the main changes in this substantial pull request. Revise the title to better reflect the primary objectives, such as 'Add service update automation and downstream notification workflows' or 'Automate dependency updates and downstream service notifications'.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch docfx/context7-chat

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.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This pull request establishes a comprehensive automation framework for managing dependency updates across the Codebelt repository ecosystem. The changes introduce GitHub Actions workflows that automatically update NuGet packages when upstream dependencies are released, propagate those updates to downstream repositories, and handle related documentation and configuration updates.

Changes:

  • Added automated service update workflow that bumps NuGet packages, updates release notes, CHANGELOG, and Docker tags when triggered by upstream releases or manually
  • Added downstream notification workflow that dispatches update events to dependent repositories when a new release is published
  • Added Python script to intelligently bump NuGet package versions by querying the NuGet API or using triggered version information
  • Added comprehensive .editorconfig for code style enforcement and analyzer configuration
  • Added Context7 chat widget integration to documentation pages
  • Added AGENTS.md guide for AI agents working on the codebase

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 13 comments.

Show a summary per file
File Description
.github/workflows/service-update.yml Workflow that orchestrates dependency updates, version bumping, and PR creation
.github/workflows/trigger-downstream.yml Workflow that notifies downstream repositories of new releases
.github/scripts/bump-nuget.py Python script that updates package versions in Directory.Packages.props
.github/dispatch-targets.json Configuration defining downstream repositories to notify
.editorconfig Code style rules and analyzer configuration for consistent formatting
.docfx/docfx.json Updated to include custom template for documentation
.docfx/templates/modern/public/main.js JavaScript to inject Context7 support widget
AGENTS.md Comprehensive guide for AI agents with project conventions and workflows

.editorconfig Outdated
Comment on lines 179 to 185
# Excluded becuase of inconsistency with other analyzers
[*.{cs,vb}]
dotnet_diagnostic.IDE0036.severity = none

# Order modifiers
# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0036
# Excluded becuase of inconsistency with other analyzers
Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

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

Spelling error: "becuase" should be "because"

Suggested change
# Excluded becuase of inconsistency with other analyzers
[*.{cs,vb}]
dotnet_diagnostic.IDE0036.severity = none
# Order modifiers
# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0036
# Excluded becuase of inconsistency with other analyzers
# Excluded because of inconsistency with other analyzers
[*.{cs,vb}]
dotnet_diagnostic.IDE0036.severity = none
# Order modifiers
# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0036
# Excluded because of inconsistency with other analyzers

Copilot uses AI. Check for mistakes.
Comment on lines +57 to +73
for repo in targets:
url = f'https://api.github.com/repos/codebeltnet/{repo}/dispatches'
payload = json.dumps({
'event_type': 'codebelt-service-update',
'client_payload': {
'source_repo': source,
'source_version': version
}
}).encode()
req = urllib.request.Request(url, data=payload, method='POST', headers={
'Authorization': f'Bearer {token}',
'Accept': 'application/vnd.github+json',
'Content-Type': 'application/json',
'X-GitHub-Api-Version': '2022-11-28'
})
with urllib.request.urlopen(req) as r:
print(f'✓ Dispatched to {repo}: HTTP {r.status}')
Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

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

Missing error handling for HTTP request failures. If the urlopen call fails (network error, HTTP error, or invalid JSON response), the entire workflow will fail without attempting to dispatch to remaining repositories. Consider wrapping the dispatch loop in a try-except block to handle errors gracefully and continue processing other repositories.

Copilot uses AI. Check for mistakes.
Comment on lines +43 to +51
- name: Determine new version for this repo
id: newver
run: |
CURRENT=$(grep -oP '(?<=## \[)[\d.]+(?=\])' CHANGELOG.md | head -1)
NEW=$(echo "$CURRENT" | awk -F. '{printf "%s.%s.%d", $1, $2, $3+1}')
BRANCH="v${NEW}/service-update"
echo "current=$CURRENT" >> $GITHUB_OUTPUT
echo "new=$NEW" >> $GITHUB_OUTPUT
echo "branch=$BRANCH" >> $GITHUB_OUTPUT
Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

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

The version extraction regex may fail if the CHANGELOG.md format deviates. The pattern '(?&lt;=## \[)[\d.]+(?=\])' assumes a specific format with no spaces between brackets and version numbers. If the CHANGELOG.md ever contains entries like ## [ 11.0.5 ] with spaces, the extraction will fail silently and the awk command will receive empty input, potentially causing the version bump to fail with an unclear error. Consider adding validation to check if CURRENT is empty after extraction.

Copilot uses AI. Check for mistakes.
@codecov
Copy link

codecov bot commented Feb 18, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 94.37%. Comparing base (9411602) to head (9fbd7fc).
⚠️ Report is 2 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main      #54      +/-   ##
==========================================
- Coverage   94.69%   94.37%   -0.32%     
==========================================
  Files          46       46              
  Lines         942      942              
  Branches      124      124              
==========================================
- Hits          892      889       -3     
- Misses         41       44       +3     
  Partials        9        9              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link

@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: 6

🧹 Nitpick comments (3)
.docfx/templates/modern/public/main.js (1)

2-11: start() is not idempotent — duplicate script injection on repeated calls

DocFX may call the start() hook more than once during hot-reload/navigation. Without a guard, each invocation appends another <script> element, loading the widget multiple times. Add a simple sentinel:

♻️ Proposed fix
  start: () => {
+   if (document.querySelector('script[data-library="/codebeltnet/xunit"]')) return;
    const script = document.createElement('script');
    script.src = 'https://context7.com/widget.js';
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.docfx/templates/modern/public/main.js around lines 2 - 11, The start()
function currently appends the widget <script> every time it's called, causing
duplicate injections; modify start() to first check for an existing script
element (e.g., using document.querySelector for
script[src="https://context7.com/widget.js"] or
script[data-library="/codebeltnet/xunit"]) and return early if found, otherwise
proceed to create and append the new script with the same attributes
(data-library, data-color, data-position, data-placeholder, async) so the widget
is only injected once even if start() is invoked multiple times.
AGENTS.md (1)

188-193: Duplicate benchmark attribute guidance

Lines 188–189 and 191–193 repeat the same [MemoryDiagnoser], [GroupBenchmarksBy], [GlobalSetup], and [Params] recommendations. The second block adds BenchmarkLogicalGroupRule.ByCategory and extra guidance, but the duplication is confusing. Consider merging into a single list with the fuller detail.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@AGENTS.md` around lines 188 - 193, The document repeats benchmark attribute
guidance twice; merge the two blocks into one consolidated bullet list that
includes the fuller details: keep a single entry for [MemoryDiagnoser], a single
entry for [GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)], and unified
guidance for [GlobalSetup] (use for initialization and expensive prep) and
[Params] (use for input variations, deterministic data, avoid external systems);
remove the duplicate lines so the attributes [MemoryDiagnoser],
[GroupBenchmarksBy(...)], [GlobalSetup], and [Params] appear once with the
complete guidance.
.github/scripts/bump-nuget.py (1)

67-69: Broad except Exception swallows unexpected errors silently

except Exception catches everything including KeyError (if the NuGet API response has an unexpected schema), json.JSONDecodeError, and network-level errors equally, losing diagnostic information. Be more specific:

♻️ Proposed fix
-    except Exception as e:
-        print(f"  SKIP {pkg}: {e}", file=sys.stderr)
-        return None
+    except (urllib.error.URLError, json.JSONDecodeError, KeyError) as e:
+        print(f"  SKIP {pkg}: {type(e).__name__}: {e}", file=sys.stderr)
+        return None
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/scripts/bump-nuget.py around lines 67 - 69, The broad "except
Exception as e" in bump-nuget.py hides important failures; replace it with
specific handlers (e.g., except requests.exceptions.RequestException as e,
except json.JSONDecodeError as e, except KeyError as e) that print meaningful
error messages for those known cases and only catch expected errors, and add a
final bare "except Exception" that re-raises (or logs full traceback using
traceback.format_exc()) so truly unexpected errors aren't silently swallowed;
target the block handling "pkg" where the current except resides.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.editorconfig:
- Around line 105-108: Update the misleading comment rule IDs to match the
suppressed rules: replace occurrences of "IDE0039" with "IDE0300" in the comment
that precedes the IDE0300 suppression (the block that currently says "Use
collection expression for array") and replace "IDE0031" with "IDE0301" in the
comment that precedes the IDE0301 suppression (the block that currently says
"Use collection expression for empty"); ensure the comment text and IDs align
with the dotnet_diagnostic entries (IDE0300 and IDE0301) so the comments
accurately describe the suppressed rules.
- Around line 183-187: Remove the redundant duplicate suppression block for
IDE0036: find the repeated "[*.{cs,vb}]" section that contains
"dotnet_diagnostic.IDE0036.severity = none" (the second "Order modifiers" block)
and delete it so only a single suppression entry for IDE0036 remains in the
.editorconfig.

In @.github/workflows/service-update.yml:
- Around line 43-51: The step that computes CURRENT/NEW/BRANCH must guard
against an empty or non-matching CURRENT (from grep) to avoid creating malformed
versions like "..1"; update the shell logic in the "Determine new version for
this repo" step to validate CURRENT (e.g., test it against a regex like
'^[0-9]+\.[0-9]+\.[0-9]+$') and if it fails set a safe default such as "0.0.0"
(or directly set NEW="0.0.1"), then compute NEW from that validated CURRENT and
build BRANCH="v${NEW}/service-update" so the branch name is always well-formed;
ensure the variables CURRENT, NEW and BRANCH are the ones used and exported to
GITHUB_OUTPUT as before.
- Around line 96-122: The shell compound that updates files uses the LATEST
variable and a short-circuiting conditional ([ -n "$LATEST" ] && sed ... && echo
...) which returns exit code 1 when LATEST is empty and fails the step under set
-e; update both steps named "Bump test runner Docker tag" and "Bump NGINX Alpine
version" to make the skip explicit by either replacing the short-circuit with an
if ... fi or appending a no-op fallback (e.g., add "|| true" to the end of the
compound) so that when LATEST is empty the step succeeds instead of failing;
locate the lines referencing the LATEST variable and the sed && echo sequence
and apply the change in both places.
- Around line 38-41: This step dangerously interpolates user-controlled
github.event.client_payload.source_repo and source_version directly into the run
block; move those values into the job/step env (e.g., set SOURCE and VERSION via
env: using the ${{ ... }} expressions) and then inside the run block read them
from the environment with properly quoted shell expansion (referencing SOURCE
and VERSION), then write them to GITHUB_OUTPUT; update the lines that currently
set SOURCE and VERSION and the echo "source=..." / echo "version=..." usages to
use the env-provided variables to avoid shell evaluation of client_payload
content.

In @.github/workflows/trigger-downstream.yml:
- Around line 72-73: The current loop calls urllib.request.urlopen(req) which
raises urllib.error.HTTPError on 4xx/5xx and aborts the whole dispatch; wrap
each per-repo dispatch (the block calling urllib.request.urlopen(req) and the
print f'✓ Dispatched to {repo}: HTTP {r.status}') in a try/except that catches
urllib.error.HTTPError and Exception, log the error (including repo and error
details) and continue the loop so remaining repos are attempted, and ensure sys
is imported at the top of the heredoc as requested.

---

Nitpick comments:
In @.docfx/templates/modern/public/main.js:
- Around line 2-11: The start() function currently appends the widget <script>
every time it's called, causing duplicate injections; modify start() to first
check for an existing script element (e.g., using document.querySelector for
script[src="https://context7.com/widget.js"] or
script[data-library="/codebeltnet/xunit"]) and return early if found, otherwise
proceed to create and append the new script with the same attributes
(data-library, data-color, data-position, data-placeholder, async) so the widget
is only injected once even if start() is invoked multiple times.

In @.github/scripts/bump-nuget.py:
- Around line 67-69: The broad "except Exception as e" in bump-nuget.py hides
important failures; replace it with specific handlers (e.g., except
requests.exceptions.RequestException as e, except json.JSONDecodeError as e,
except KeyError as e) that print meaningful error messages for those known cases
and only catch expected errors, and add a final bare "except Exception" that
re-raises (or logs full traceback using traceback.format_exc()) so truly
unexpected errors aren't silently swallowed; target the block handling "pkg"
where the current except resides.

In `@AGENTS.md`:
- Around line 188-193: The document repeats benchmark attribute guidance twice;
merge the two blocks into one consolidated bullet list that includes the fuller
details: keep a single entry for [MemoryDiagnoser], a single entry for
[GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)], and unified guidance
for [GlobalSetup] (use for initialization and expensive prep) and [Params] (use
for input variations, deterministic data, avoid external systems); remove the
duplicate lines so the attributes [MemoryDiagnoser], [GroupBenchmarksBy(...)],
[GlobalSetup], and [Params] appear once with the complete guidance.

Comment on lines +105 to +108
# IDE0039: Use collection expression for array
# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0300
[*.{cs,vb}]
dotnet_diagnostic.IDE0300.severity = none
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Misleading rule IDs in comments — "IDE0039" and "IDE0031" should be "IDE0300" and "IDE0301"

Both comment lines reference old, unrelated rule IDs:

  • Line 105: # IDE0039: Use collection expression for array — IDE0039 is "Use local function"; the suppressed rule and linked URL are for IDE0300.
  • Line 110: # IDE0031: Use collection expression for empty — IDE0031 is "Use null propagation"; the suppressed rule and linked URL are for IDE0301.
📝 Proposed fix
-# IDE0039: Use collection expression for array
-# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0300
+# IDE0300: Use collection expression for array
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0300
 [*.{cs,vb}]
 dotnet_diagnostic.IDE0300.severity = none

-# IDE0031: Use collection expression for empty
-# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0301
+# IDE0301: Use collection expression for empty
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0301
 [*.{cs,vb}]
 dotnet_diagnostic.IDE0301.severity = none

Also applies to: 110-113

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.editorconfig around lines 105 - 108, Update the misleading comment rule IDs
to match the suppressed rules: replace occurrences of "IDE0039" with "IDE0300"
in the comment that precedes the IDE0300 suppression (the block that currently
says "Use collection expression for array") and replace "IDE0031" with "IDE0301"
in the comment that precedes the IDE0301 suppression (the block that currently
says "Use collection expression for empty"); ensure the comment text and IDs
align with the dotnet_diagnostic entries (IDE0300 and IDE0301) so the comments
accurately describe the suppressed rules.

Comment on lines +43 to +51
- name: Determine new version for this repo
id: newver
run: |
CURRENT=$(grep -oP '(?<=## \[)[\d.]+(?=\])' CHANGELOG.md | head -1)
NEW=$(echo "$CURRENT" | awk -F. '{printf "%s.%s.%d", $1, $2, $3+1}')
BRANCH="v${NEW}/service-update"
echo "current=$CURRENT" >> $GITHUB_OUTPUT
echo "new=$NEW" >> $GITHUB_OUTPUT
echo "branch=$BRANCH" >> $GITHUB_OUTPUT
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Malformed version and branch name if CHANGELOG has no ## [x.y.z] entry

If CHANGELOG.md is missing, empty, or doesn't yet contain a ## [x.y.z] header (e.g., first run on a fresh repo), CURRENT will be an empty string. The awk pipeline then produces ..1 as the version, and the branch name becomes v..1/service-update. This will likely cause git checkout -b to fail or produce an unusable PR, silently breaking the entire workflow.

Add a guard:

🛡️ Proposed fix
         CURRENT=$(grep -oP '(?<=## \[)[\d.]+(?=\])' CHANGELOG.md | head -1)
+        if [ -z "$CURRENT" ]; then
+          echo "::error::Could not determine current version from CHANGELOG.md"
+          exit 1
+        fi
         NEW=$(echo "$CURRENT" | awk -F. '{printf "%s.%s.%d", $1, $2, $3+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
- name: Determine new version for this repo
id: newver
run: |
CURRENT=$(grep -oP '(?<=## \[)[\d.]+(?=\])' CHANGELOG.md | head -1)
NEW=$(echo "$CURRENT" | awk -F. '{printf "%s.%s.%d", $1, $2, $3+1}')
BRANCH="v${NEW}/service-update"
echo "current=$CURRENT" >> $GITHUB_OUTPUT
echo "new=$NEW" >> $GITHUB_OUTPUT
echo "branch=$BRANCH" >> $GITHUB_OUTPUT
- name: Determine new version for this repo
id: newver
run: |
CURRENT=$(grep -oP '(?<=## \[)[\d.]+(?=\])' CHANGELOG.md | head -1)
if [ -z "$CURRENT" ]; then
echo "::error::Could not determine current version from CHANGELOG.md"
exit 1
fi
NEW=$(echo "$CURRENT" | awk -F. '{printf "%s.%s.%d", $1, $2, $3+1}')
BRANCH="v${NEW}/service-update"
echo "current=$CURRENT" >> $GITHUB_OUTPUT
echo "new=$NEW" >> $GITHUB_OUTPUT
echo "branch=$BRANCH" >> $GITHUB_OUTPUT
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/service-update.yml around lines 43 - 51, The step that
computes CURRENT/NEW/BRANCH must guard against an empty or non-matching CURRENT
(from grep) to avoid creating malformed versions like "..1"; update the shell
logic in the "Determine new version for this repo" step to validate CURRENT
(e.g., test it against a regex like '^[0-9]+\.[0-9]+\.[0-9]+$') and if it fails
set a safe default such as "0.0.0" (or directly set NEW="0.0.1"), then compute
NEW from that validated CURRENT and build BRANCH="v${NEW}/service-update" so the
branch name is always well-formed; ensure the variables CURRENT, NEW and BRANCH
are the ones used and exported to GITHUB_OUTPUT as before.

Comment on lines +96 to +122
- name: Bump test runner Docker tag
run: |
[ -f testenvironments.json ] || exit 0
LATEST=$(curl -sf "https://hub.docker.com/v2/repositories/codebeltnet/ubuntu-testrunner/tags/?page_size=10&ordering=last_updated" \
| python3 -c "
import sys, json
tags = [t['name'] for t in json.load(sys.stdin)['results'] if 'latest' not in t['name']]
print(tags[0] if tags else '')
")
[ -n "$LATEST" ] && \
sed -i "s|codebeltnet/ubuntu-testrunner:[^\"]*|codebeltnet/ubuntu-testrunner:${LATEST}|g" \
testenvironments.json && echo "Bumped to $LATEST"

- name: Bump NGINX Alpine version
run: |
[ -f .docfx/Dockerfile.docfx ] || exit 0
LATEST=$(curl -sf "https://hub.docker.com/v2/repositories/library/nginx/tags/?page_size=50&name=alpine&ordering=last_updated" \
| python3 -c "
import sys, json, re
data = json.load(sys.stdin)
tags = [t['name'] for t in data['results'] if re.match(r'^\d+\.\d+\.\d+-alpine$', t['name'])]
if tags:
print(sorted(tags, key=lambda v: list(map(int, v.replace('-alpine','').split('.'))))[-1])
")
[ -n "$LATEST" ] && \
sed -i "s|NGINX_VERSION=.*|NGINX_VERSION=${LATEST}|g" \
.docfx/Dockerfile.docfx && echo "Bumped NGINX to $LATEST"
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Steps fail with exit code 1 when LATEST is empty, under GitHub Actions' default set -eo pipefail shell

GitHub Actions runs run: blocks with /bin/bash --noprofile --norc -eo pipefail. When LATEST is empty (Docker Hub API unavailable, rate-limited, or returns no matching tags), the compound expression [ -n "$LATEST" ] && sed ... && echo "..." short-circuits after [ -n "$LATEST" ] exits 1. The overall compound command exits 1, which under set -e fails the step — even though the intent is clearly "skip if nothing to update."

This affects both the Docker test runner step (lines 105–107) and the NGINX Alpine step (lines 120–122).

🐛 Proposed fix — append `|| true` to make the skip explicit
       [ -n "$LATEST" ] && \
         sed -i "s|codebeltnet/ubuntu-testrunner:[^\"]*|codebeltnet/ubuntu-testrunner:${LATEST}|g" \
-        testenvironments.json && echo "Bumped to $LATEST"
+        testenvironments.json && echo "Bumped to $LATEST" || true
       [ -n "$LATEST" ] && \
         sed -i "s|NGINX_VERSION=.*|NGINX_VERSION=${LATEST}|g" \
-        .docfx/Dockerfile.docfx && echo "Bumped NGINX to $LATEST"
+        .docfx/Dockerfile.docfx && echo "Bumped NGINX to $LATEST" || true
📝 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
- name: Bump test runner Docker tag
run: |
[ -f testenvironments.json ] || exit 0
LATEST=$(curl -sf "https://hub.docker.com/v2/repositories/codebeltnet/ubuntu-testrunner/tags/?page_size=10&ordering=last_updated" \
| python3 -c "
import sys, json
tags = [t['name'] for t in json.load(sys.stdin)['results'] if 'latest' not in t['name']]
print(tags[0] if tags else '')
")
[ -n "$LATEST" ] && \
sed -i "s|codebeltnet/ubuntu-testrunner:[^\"]*|codebeltnet/ubuntu-testrunner:${LATEST}|g" \
testenvironments.json && echo "Bumped to $LATEST"
- name: Bump NGINX Alpine version
run: |
[ -f .docfx/Dockerfile.docfx ] || exit 0
LATEST=$(curl -sf "https://hub.docker.com/v2/repositories/library/nginx/tags/?page_size=50&name=alpine&ordering=last_updated" \
| python3 -c "
import sys, json, re
data = json.load(sys.stdin)
tags = [t['name'] for t in data['results'] if re.match(r'^\d+\.\d+\.\d+-alpine$', t['name'])]
if tags:
print(sorted(tags, key=lambda v: list(map(int, v.replace('-alpine','').split('.'))))[-1])
")
[ -n "$LATEST" ] && \
sed -i "s|NGINX_VERSION=.*|NGINX_VERSION=${LATEST}|g" \
.docfx/Dockerfile.docfx && echo "Bumped NGINX to $LATEST"
- name: Bump test runner Docker tag
run: |
[ -f testenvironments.json ] || exit 0
LATEST=$(curl -sf "https://hub.docker.com/v2/repositories/codebeltnet/ubuntu-testrunner/tags/?page_size=10&ordering=last_updated" \
| python3 -c "
import sys, json
tags = [t['name'] for t in json.load(sys.stdin)['results'] if 'latest' not in t['name']]
print(tags[0] if tags else '')
")
[ -n "$LATEST" ] && \
sed -i "s|codebeltnet/ubuntu-testrunner:[^\"]*|codebeltnet/ubuntu-testrunner:${LATEST}|g" \
testenvironments.json && echo "Bumped to $LATEST" || true
- name: Bump NGINX Alpine version
run: |
[ -f .docfx/Dockerfile.docfx ] || exit 0
LATEST=$(curl -sf "https://hub.docker.com/v2/repositories/library/nginx/tags/?page_size=50&name=alpine&ordering=last_updated" \
| python3 -c "
import sys, json, re
data = json.load(sys.stdin)
tags = [t['name'] for t in data['results'] if re.match(r'^\d+\.\d+\.\d+-alpine$', t['name'])]
if tags:
print(sorted(tags, key=lambda v: list(map(int, v.replace('-alpine','').split('.'))))[-1])
")
[ -n "$LATEST" ] && \
sed -i "s|NGINX_VERSION=.*|NGINX_VERSION=${LATEST}|g" \
.docfx/Dockerfile.docfx && echo "Bumped NGINX to $LATEST" || true
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/service-update.yml around lines 96 - 122, The shell
compound that updates files uses the LATEST variable and a short-circuiting
conditional ([ -n "$LATEST" ] && sed ... && echo ...) which returns exit code 1
when LATEST is empty and fails the step under set -e; update both steps named
"Bump test runner Docker tag" and "Bump NGINX Alpine version" to make the skip
explicit by either replacing the short-circuit with an if ... fi or appending a
no-op fallback (e.g., add "|| true" to the end of the compound) so that when
LATEST is empty the step succeeds instead of failing; locate the lines
referencing the LATEST variable and the sed && echo sequence and apply the
change in both places.

Comment on lines +72 to +73
with urllib.request.urlopen(req) as r:
print(f'✓ Dispatched to {repo}: HTTP {r.status}')
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

urlopen raises on HTTP errors — single failure aborts all remaining dispatches

urllib.request.urlopen raises urllib.error.HTTPError for any 4xx/5xx response (e.g., 404 for a repo that doesn't exist yet, 403 if app permissions are missing on a target, 422 for a bad payload). Because the exception propagates out of the for loop, any subsequent repos in the list never receive their dispatch event.

Wrap each dispatch in a try/except so failures are logged but the loop continues:

🛡️ Proposed fix
-              with urllib.request.urlopen(req) as r:
-                  print(f'✓ Dispatched to {repo}: HTTP {r.status}')
+              try:
+                  with urllib.request.urlopen(req) as r:
+                      print(f'✓ Dispatched to {repo}: HTTP {r.status}')
+              except urllib.error.HTTPError as e:
+                  print(f'✗ Failed to dispatch to {repo}: HTTP {e.code} {e.reason}', file=sys.stderr)
+              except urllib.error.URLError as e:
+                  print(f'✗ Failed to dispatch to {repo}: {e.reason}', file=sys.stderr)

Also import sys at the top of the heredoc:

-          import json, urllib.request, os, sys
+          import json, urllib.request, urllib.error, os, sys
📝 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
with urllib.request.urlopen(req) as r:
print(f'✓ Dispatched to {repo}: HTTP {r.status}')
try:
with urllib.request.urlopen(req) as r:
print(f'✓ Dispatched to {repo}: HTTP {r.status}')
except urllib.error.HTTPError as e:
print(f'✗ Failed to dispatch to {repo}: HTTP {e.code} {e.reason}', file=sys.stderr)
except urllib.error.URLError as e:
print(f'✗ Failed to dispatch to {repo}: {e.reason}', file=sys.stderr)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/trigger-downstream.yml around lines 72 - 73, The current
loop calls urllib.request.urlopen(req) which raises urllib.error.HTTPError on
4xx/5xx and aborts the whole dispatch; wrap each per-repo dispatch (the block
calling urllib.request.urlopen(req) and the print f'✓ Dispatched to {repo}: HTTP
{r.status}') in a try/except that catches urllib.error.HTTPError and Exception,
log the error (including repo and error details) and continue the loop so
remaining repos are attempted, and ensure sys is imported at the top of the
heredoc as requested.

gimlichael and others added 6 commits February 18, 2026 21:07
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@gimlichael gimlichael merged commit 3806cf0 into main Feb 18, 2026
20 checks passed
@gimlichael gimlichael deleted the docfx/context7-chat branch February 18, 2026 20:21
@sonarqubecloud
Copy link

@coderabbitai coderabbitai bot mentioned this pull request Feb 18, 2026
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.

1 participant

Comments