better-code-review-graph 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. better_code_review_graph-0.1.0/.agents/skills/build-graph/SKILL.md +38 -0
  2. better_code_review_graph-0.1.0/.agents/skills/review-delta/SKILL.md +46 -0
  3. better_code_review_graph-0.1.0/.agents/skills/review-pr/SKILL.md +66 -0
  4. better_code_review_graph-0.1.0/.claude-plugin/marketplace.json +21 -0
  5. better_code_review_graph-0.1.0/.claude-plugin/plugin.json +20 -0
  6. better_code_review_graph-0.1.0/.dockerignore +32 -0
  7. better_code_review_graph-0.1.0/.github/best_practices.md +25 -0
  8. better_code_review_graph-0.1.0/.github/workflows/cd.yml +232 -0
  9. better_code_review_graph-0.1.0/.github/workflows/ci.yml +247 -0
  10. better_code_review_graph-0.1.0/.gitignore +57 -0
  11. better_code_review_graph-0.1.0/.infisical.json +1 -0
  12. better_code_review_graph-0.1.0/.pre-commit-config.yaml +87 -0
  13. better_code_review_graph-0.1.0/AGENTS.md +96 -0
  14. better_code_review_graph-0.1.0/CHANGELOG.md +149 -0
  15. better_code_review_graph-0.1.0/CLAUDE.md +96 -0
  16. better_code_review_graph-0.1.0/Dockerfile +16 -0
  17. better_code_review_graph-0.1.0/LICENSE +21 -0
  18. better_code_review_graph-0.1.0/PKG-INFO +276 -0
  19. better_code_review_graph-0.1.0/README.md +251 -0
  20. better_code_review_graph-0.1.0/docs/COMMANDS.md +178 -0
  21. better_code_review_graph-0.1.0/docs/FEATURES.md +78 -0
  22. better_code_review_graph-0.1.0/docs/INDEX.md +11 -0
  23. better_code_review_graph-0.1.0/docs/LEGAL.md +13 -0
  24. better_code_review_graph-0.1.0/docs/LLM-OPTIMIZED-REFERENCE.md +72 -0
  25. better_code_review_graph-0.1.0/docs/ROADMAP.md +65 -0
  26. better_code_review_graph-0.1.0/docs/TROUBLESHOOTING.md +38 -0
  27. better_code_review_graph-0.1.0/docs/USAGE.md +93 -0
  28. better_code_review_graph-0.1.0/docs/architecture.md +112 -0
  29. better_code_review_graph-0.1.0/docs/assets/marketing-diagram.png +0 -0
  30. better_code_review_graph-0.1.0/docs/schema.md +177 -0
  31. better_code_review_graph-0.1.0/docs/superpowers/specs/2026-03-16-vscode-extension-design.md +308 -0
  32. better_code_review_graph-0.1.0/hooks/hooks.json +25 -0
  33. better_code_review_graph-0.1.0/hooks/session-start.sh +22 -0
  34. better_code_review_graph-0.1.0/pyproject.toml +76 -0
  35. better_code_review_graph-0.1.0/scripts/enforce-commit.sh +8 -0
  36. better_code_review_graph-0.1.0/semantic-release.toml +11 -0
  37. better_code_review_graph-0.1.0/server.json +25 -0
  38. better_code_review_graph-0.1.0/skills/build-graph/SKILL.md +38 -0
  39. better_code_review_graph-0.1.0/skills/review-delta/SKILL.md +46 -0
  40. better_code_review_graph-0.1.0/skills/review-pr/SKILL.md +66 -0
  41. better_code_review_graph-0.1.0/src/better_code_review_graph/__init__.py +1 -0
  42. better_code_review_graph-0.1.0/src/better_code_review_graph/__main__.py +5 -0
  43. better_code_review_graph-0.1.0/src/better_code_review_graph/cli.py +264 -0
  44. better_code_review_graph-0.1.0/src/better_code_review_graph/embeddings.py +580 -0
  45. better_code_review_graph-0.1.0/src/better_code_review_graph/graph.py +664 -0
  46. better_code_review_graph-0.1.0/src/better_code_review_graph/incremental.py +507 -0
  47. better_code_review_graph-0.1.0/src/better_code_review_graph/parser.py +1098 -0
  48. better_code_review_graph-0.1.0/src/better_code_review_graph/py.typed +0 -0
  49. better_code_review_graph-0.1.0/src/better_code_review_graph/server.py +256 -0
  50. better_code_review_graph-0.1.0/src/better_code_review_graph/tools.py +1077 -0
  51. better_code_review_graph-0.1.0/tests/__init__.py +0 -0
  52. better_code_review_graph-0.1.0/tests/conftest.py +77 -0
  53. better_code_review_graph-0.1.0/tests/fixtures/Sample.cs +48 -0
  54. better_code_review_graph-0.1.0/tests/fixtures/SampleJava.java +59 -0
  55. better_code_review_graph-0.1.0/tests/fixtures/caller_example.py +8 -0
  56. better_code_review_graph-0.1.0/tests/fixtures/multi_call_example.py +13 -0
  57. better_code_review_graph-0.1.0/tests/fixtures/sample.c +25 -0
  58. better_code_review_graph-0.1.0/tests/fixtures/sample.cpp +30 -0
  59. better_code_review_graph-0.1.0/tests/fixtures/sample.kt +27 -0
  60. better_code_review_graph-0.1.0/tests/fixtures/sample.php +43 -0
  61. better_code_review_graph-0.1.0/tests/fixtures/sample.rb +38 -0
  62. better_code_review_graph-0.1.0/tests/fixtures/sample.sol +218 -0
  63. better_code_review_graph-0.1.0/tests/fixtures/sample.swift +31 -0
  64. better_code_review_graph-0.1.0/tests/fixtures/sample_go.go +48 -0
  65. better_code_review_graph-0.1.0/tests/fixtures/sample_python.py +53 -0
  66. better_code_review_graph-0.1.0/tests/fixtures/sample_rust.rs +46 -0
  67. better_code_review_graph-0.1.0/tests/fixtures/sample_typescript.ts +41 -0
  68. better_code_review_graph-0.1.0/tests/fixtures/test_sample.py +19 -0
  69. better_code_review_graph-0.1.0/tests/test_cli.py +310 -0
  70. better_code_review_graph-0.1.0/tests/test_embeddings.py +548 -0
  71. better_code_review_graph-0.1.0/tests/test_embeddings_extra.py +60 -0
  72. better_code_review_graph-0.1.0/tests/test_graph.py +282 -0
  73. better_code_review_graph-0.1.0/tests/test_graph_extra.py +495 -0
  74. better_code_review_graph-0.1.0/tests/test_incremental.py +236 -0
  75. better_code_review_graph-0.1.0/tests/test_incremental_extra.py +555 -0
  76. better_code_review_graph-0.1.0/tests/test_multilang.py +471 -0
  77. better_code_review_graph-0.1.0/tests/test_parser.py +229 -0
  78. better_code_review_graph-0.1.0/tests/test_parser_extra.py +354 -0
  79. better_code_review_graph-0.1.0/tests/test_server.py +180 -0
  80. better_code_review_graph-0.1.0/tests/test_tools.py +211 -0
  81. better_code_review_graph-0.1.0/tests/test_tools_full.py +1303 -0
  82. better_code_review_graph-0.1.0/uv.lock +2121 -0
@@ -0,0 +1,38 @@
1
+ ---
2
+ name: build-graph
3
+ description: Build or update the code review knowledge graph. Run this first to initialize, or let hooks keep it updated automatically.
4
+ argument-hint: "[full]"
5
+ ---
6
+
7
+ # Build Graph
8
+
9
+ Build or incrementally update the persistent code knowledge graph for this repository.
10
+
11
+ ## Steps
12
+
13
+ 1. **Check graph status** by calling the `list_graph_stats_tool` MCP tool.
14
+ - If the graph has never been built (last_updated is null), proceed with a full build.
15
+ - If the graph exists, proceed with an incremental update.
16
+
17
+ 2. **Build the graph** by calling the `build_or_update_graph_tool` MCP tool:
18
+ - For first-time setup: `build_or_update_graph_tool(full_rebuild=True)`
19
+ - For updates: `build_or_update_graph_tool()` (incremental by default)
20
+
21
+ 3. **Verify** by calling `list_graph_stats_tool` again and report the results:
22
+ - Number of files parsed
23
+ - Number of nodes and edges created
24
+ - Languages detected
25
+ - Any errors encountered
26
+
27
+ ## When to Use
28
+
29
+ - First time setting up the graph for a repository
30
+ - After major refactoring or branch switches
31
+ - If the graph seems stale or out of sync
32
+ - The graph auto-updates via hooks on edit/commit, so manual builds are rarely needed
33
+
34
+ ## Notes
35
+
36
+ - The graph is stored as a SQLite database (`.code-review-graph/graph.db`) in the repo root
37
+ - Binary files, generated files, and patterns in `.code-review-graphignore` are skipped
38
+ - Supported languages: Python, TypeScript/JavaScript, Go, Rust, Java, C#, Ruby, Kotlin, Swift, PHP, C/C++
@@ -0,0 +1,46 @@
1
+ ---
2
+ name: review-delta
3
+ description: Review only changes since last commit using impact analysis. Token-efficient delta review with automatic blast-radius detection.
4
+ argument-hint: "[file or function name]"
5
+ ---
6
+
7
+ # Review Delta
8
+
9
+ Perform a focused, token-efficient code review of only the changed code and its blast radius.
10
+
11
+ **Token optimization:** Before starting, call `get_docs_section_tool(section_name="review-delta")` for the optimized workflow. Use ONLY changed nodes + 2-hop neighbors in context.
12
+
13
+ ## Steps
14
+
15
+ 1. **Ensure the graph is current** by calling `build_or_update_graph_tool()` (incremental update).
16
+
17
+ 2. **Get review context** by calling `get_review_context_tool()`. This returns:
18
+ - Changed files (auto-detected from git diff)
19
+ - Impacted nodes and files (blast radius)
20
+ - Source code snippets for changed areas
21
+ - Review guidance (test coverage gaps, wide impact warnings, inheritance concerns)
22
+
23
+ 3. **Analyze the blast radius** by reviewing the `impacted_nodes` and `impacted_files` in the context. Focus on:
24
+ - Functions whose callers changed (may need signature/behavior verification)
25
+ - Classes with inheritance changes (Liskov substitution concerns)
26
+ - Files with many dependents (high-risk changes)
27
+
28
+ 4. **Perform the review** using the context. For each changed file:
29
+ - Review the source snippet for correctness, style, and potential bugs
30
+ - Check if impacted callers/dependents need updates
31
+ - Verify test coverage using `query_graph_tool(pattern="tests_for", target=<function_name>)`
32
+ - Flag any untested changed functions
33
+
34
+ 5. **Report findings** in a structured format:
35
+ - **Summary**: One-line overview of the changes
36
+ - **Risk level**: Low / Medium / High (based on blast radius)
37
+ - **Issues found**: Bugs, style issues, missing tests
38
+ - **Blast radius**: List of impacted files/functions
39
+ - **Recommendations**: Actionable suggestions
40
+
41
+ ## Advantages Over Full-Repo Review
42
+
43
+ - Only sends changed + impacted code to the model (5-10x fewer tokens)
44
+ - Automatically identifies blast radius without manual file searching
45
+ - Provides structural context (who calls what, inheritance chains)
46
+ - Flags untested functions automatically
@@ -0,0 +1,66 @@
1
+ ---
2
+ name: review-pr
3
+ description: Review a PR or branch diff using the knowledge graph for full structural context. Outputs a structured review with blast-radius analysis.
4
+ argument-hint: "[PR number or branch name]"
5
+ ---
6
+
7
+ # Review PR
8
+
9
+ Perform a comprehensive code review of a pull request or branch diff using the knowledge graph.
10
+
11
+ **Token optimization:** Before starting, call `get_docs_section_tool(section_name="review-pr")` for the optimized workflow. Never include full files unless explicitly asked.
12
+
13
+ ## Steps
14
+
15
+ 1. **Identify the changes** for the PR:
16
+ - If a PR number or branch is provided, use `git diff main...<branch>` to get changed files
17
+ - Otherwise auto-detect from the current branch vs main/master
18
+
19
+ 2. **Update the graph** by calling `build_or_update_graph_tool(base="main")` to ensure the graph reflects the current state.
20
+
21
+ 3. **Get the full review context** by calling `get_review_context_tool(base="main")`:
22
+ - This uses `main` (or the specified base branch) as the diff base
23
+ - Returns all changed files across all commits in the PR
24
+
25
+ 4. **Analyze impact** by calling `get_impact_radius_tool(base="main")`:
26
+ - Review the blast radius across the entire PR
27
+ - Identify high-risk areas (widely depended-upon code)
28
+
29
+ 5. **Deep-dive each changed file**:
30
+ - Read the full source of files with significant changes
31
+ - Use `query_graph_tool(pattern="callers_of", target=<func>)` for high-risk functions
32
+ - Use `query_graph_tool(pattern="tests_for", target=<func>)` to verify test coverage
33
+ - Check for breaking changes in public APIs
34
+
35
+ 6. **Generate structured review output**:
36
+
37
+ ```
38
+ ## PR Review: <title>
39
+
40
+ ### Summary
41
+ <1-3 sentence overview>
42
+
43
+ ### Risk Assessment
44
+ - **Overall risk**: Low / Medium / High
45
+ - **Blast radius**: X files, Y functions impacted
46
+ - **Test coverage**: N changed functions covered / M total
47
+
48
+ ### File-by-File Review
49
+ #### <file_path>
50
+ - Changes: <description>
51
+ - Impact: <who depends on this>
52
+ - Issues: <bugs, style, concerns>
53
+
54
+ ### Missing Tests
55
+ - <function_name> in <file> - no test coverage found
56
+
57
+ ### Recommendations
58
+ 1. <actionable suggestion>
59
+ 2. <actionable suggestion>
60
+ ```
61
+
62
+ ## Tips
63
+
64
+ - For large PRs, focus on the highest-impact files first (most dependents)
65
+ - Use `semantic_search_nodes_tool` to find related code the PR might have missed
66
+ - Check if renamed/moved functions have updated all callers
@@ -0,0 +1,21 @@
1
+ {
2
+ "name": "better-code-review-graph",
3
+ "owner": {
4
+ "name": "n24q02m",
5
+ "url": "https://github.com/n24q02m"
6
+ },
7
+ "metadata": {
8
+ "description": "Persistent incremental knowledge graph for token-efficient, context-aware code reviews with Claude Code",
9
+ "version": "0.1.0"
10
+ },
11
+ "plugins": [
12
+ {
13
+ "name": "better-code-review-graph",
14
+ "source": "./",
15
+ "description": "Persistent incremental knowledge graph for token-efficient, context-aware code reviews with Claude Code",
16
+ "version": "0.1.0",
17
+ "category": "development",
18
+ "keywords": ["code-review", "knowledge-graph", "incremental", "tree-sitter", "mcp", "claude-code"]
19
+ }
20
+ ]
21
+ }
@@ -0,0 +1,20 @@
1
+ {
2
+ "name": "better-code-review-graph",
3
+ "description": "Persistent incremental knowledge graph for token-efficient, context-aware code reviews with Claude Code",
4
+ "version": "0.1.0",
5
+ "author": {
6
+ "name": "n24q02m",
7
+ "url": "https://github.com/n24q02m"
8
+ },
9
+ "homepage": "https://github.com/n24q02m/better-code-review-graph",
10
+ "repository": "https://github.com/n24q02m/better-code-review-graph",
11
+ "license": "MIT",
12
+ "keywords": ["code-review", "knowledge-graph", "incremental", "tree-sitter", "mcp", "claude-code"],
13
+ "mcpServers": {
14
+ "better-code-review-graph": {
15
+ "command": "uvx",
16
+ "args": ["--python", "3.13", "better-code-review-graph", "serve"]
17
+ }
18
+ },
19
+ "skills": "./skills/"
20
+ }
@@ -0,0 +1,32 @@
1
+ # Git
2
+ .git
3
+ .github
4
+
5
+ # IDE
6
+ .vscode
7
+
8
+ # Cache
9
+ .ruff_cache
10
+ .pytest_cache
11
+ __pycache__
12
+
13
+ # Development
14
+ tests/
15
+ temp/
16
+ docs/
17
+ *.md
18
+ !README.md
19
+
20
+ # Docker
21
+ Dockerfile
22
+ docker-compose.yml
23
+
24
+ # Config
25
+ .pre-commit-config.yaml
26
+ .editorconfig
27
+ .python-version
28
+ CODE_OF_CONDUCT.md
29
+ CONTRIBUTING.md
30
+ SECURITY.md
31
+ LICENSE
32
+ CHANGELOG.md
@@ -0,0 +1,25 @@
1
+ # Style Guide - better-code-review-graph
2
+
3
+ ## Architecture
4
+ Knowledge graph MCP server for token-efficient code reviews. Python, single-package repo.
5
+
6
+ ## Python
7
+ - Formatter/Linter: Ruff (default config)
8
+ - Type checker: ty
9
+ - Test: pytest + pytest-asyncio
10
+ - Package manager: uv
11
+ - SDK: fastmcp
12
+ - Core deps: tree-sitter, networkx, SQLite, qwen3-embed (ONNX), litellm
13
+
14
+ ## Code Patterns
15
+ - Tree-sitter parsing for 12 languages
16
+ - SQLite graph storage with NetworkX BFS for impact analysis
17
+ - Dual-mode embedding: local ONNX (qwen3-embed) + LiteLLM cloud
18
+ - Incremental updates via git diff and file watching
19
+ - Call target resolution: bare names resolved to qualified names
20
+
21
+ ## Commits
22
+ Conventional Commits (feat:, fix:, chore:, docs:, refactor:, test:).
23
+
24
+ ## Security
25
+ Validate file paths. Bound graph traversal depth. Prevent unbounded output via pagination.
@@ -0,0 +1,232 @@
1
+ name: CD
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ inputs:
6
+ release_type:
7
+ description: "Release type"
8
+ required: true
9
+ type: choice
10
+ options:
11
+ - beta
12
+ - stable
13
+
14
+ permissions:
15
+ contents: write
16
+ packages: write
17
+ id-token: write
18
+
19
+ env:
20
+ DOCKERHUB_IMAGE: ${{ secrets.DOCKERHUB_USERNAME }}/better-code-review-graph
21
+ GHCR_IMAGE: ghcr.io/${{ github.repository }}
22
+
23
+ concurrency:
24
+ group: release
25
+ cancel-in-progress: false
26
+
27
+ jobs:
28
+ # =================== Release ===================
29
+ release:
30
+ name: Semantic Release
31
+ runs-on: ubuntu-latest
32
+ outputs:
33
+ released: ${{ steps.release.outputs.released }}
34
+ tag: ${{ steps.release.outputs.tag }}
35
+ version: ${{ steps.release.outputs.version }}
36
+ is_prerelease: ${{ steps.release.outputs.is_prerelease }}
37
+ steps:
38
+ - name: Harden Runner
39
+ uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2
40
+ with:
41
+ egress-policy: audit
42
+
43
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
44
+ with:
45
+ token: ${{ secrets.GH_PAT }}
46
+ fetch-depth: 0
47
+
48
+ - uses: python-semantic-release/python-semantic-release@350c48fcb3ffcdfd2e0a235206bc2ecea6b69df0 # v10
49
+ id: release
50
+ with:
51
+ github_token: ${{ secrets.GH_PAT }}
52
+ prerelease: ${{ inputs.release_type == 'beta' }}
53
+ prerelease_token: beta
54
+
55
+ - uses: python-semantic-release/publish-action@310a9983a0ae878b29f3aac778d7c77c1db27378 # v10
56
+ if: steps.release.outputs.released == 'true'
57
+ with:
58
+ github_token: ${{ secrets.GH_PAT }}
59
+ tag: ${{ steps.release.outputs.tag }}
60
+
61
+ # =================== Publish to PyPI ===================
62
+ publish-pypi:
63
+ name: Publish to PyPI
64
+ needs: release
65
+ if: needs.release.outputs.released == 'true'
66
+ runs-on: ubuntu-latest
67
+ steps:
68
+ - name: Harden Runner
69
+ uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2
70
+ with:
71
+ egress-policy: audit
72
+
73
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
74
+ with:
75
+ ref: ${{ needs.release.outputs.tag }}
76
+ - uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7
77
+ - run: uv build
78
+ - name: Publish to PyPI
79
+ run: uv publish
80
+ env:
81
+ UV_PUBLISH_TOKEN: ${{ secrets.PYPI_TOKEN }}
82
+
83
+ # =================== Build Docker ===================
84
+ build-docker:
85
+ name: Build Docker (${{ matrix.platform }})
86
+ needs: release
87
+ if: needs.release.outputs.released == 'true'
88
+ strategy:
89
+ fail-fast: false
90
+ matrix:
91
+ include:
92
+ - platform: linux/amd64
93
+ runner: ubuntu-latest
94
+ artifact: linux-amd64
95
+ - platform: linux/arm64
96
+ runner: ubuntu-24.04-arm
97
+ artifact: linux-arm64
98
+ runs-on: ${{ matrix.runner }}
99
+ steps:
100
+ - name: Harden Runner
101
+ uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2
102
+ with:
103
+ egress-policy: audit
104
+
105
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
106
+ with:
107
+ ref: ${{ needs.release.outputs.tag }}
108
+ - uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4
109
+ - uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4
110
+ with:
111
+ username: ${{ secrets.DOCKERHUB_USERNAME }}
112
+ password: ${{ secrets.DOCKERHUB_TOKEN }}
113
+ - uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4
114
+ with:
115
+ registry: ghcr.io
116
+ username: ${{ github.actor }}
117
+ password: ${{ secrets.GITHUB_TOKEN }}
118
+ - uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7
119
+ id: build
120
+ with:
121
+ context: .
122
+ platforms: ${{ matrix.platform }}
123
+ outputs: type=image,"name=${{ env.DOCKERHUB_IMAGE }},${{ env.GHCR_IMAGE }}",push-by-digest=true,name-canonical=true,push=true
124
+ cache-from: type=gha,scope=${{ github.ref_name }}-${{ matrix.artifact }}
125
+ cache-to: type=gha,mode=max,scope=${{ github.ref_name }}-${{ matrix.artifact }}
126
+ - run: |
127
+ mkdir -p ${{ runner.temp }}/digests
128
+ echo "${{ steps.build.outputs.digest }}" > "${{ runner.temp }}/digests/${{ matrix.artifact }}"
129
+ - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7
130
+ with:
131
+ name: digest-${{ matrix.artifact }}
132
+ path: ${{ runner.temp }}/digests/*
133
+ retention-days: 1
134
+
135
+ # =================== Merge Docker Manifests ===================
136
+ merge-docker:
137
+ name: Merge Docker Manifests
138
+ needs: [release, build-docker]
139
+ runs-on: ubuntu-latest
140
+ steps:
141
+ - name: Harden Runner
142
+ uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2
143
+ with:
144
+ egress-policy: audit
145
+
146
+ - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
147
+ with:
148
+ pattern: digest-*
149
+ path: ${{ runner.temp }}/digests
150
+ merge-multiple: true
151
+ - uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4
152
+ with:
153
+ username: ${{ secrets.DOCKERHUB_USERNAME }}
154
+ password: ${{ secrets.DOCKERHUB_TOKEN }}
155
+ - uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4
156
+ with:
157
+ registry: ghcr.io
158
+ username: ${{ github.actor }}
159
+ password: ${{ secrets.GITHUB_TOKEN }}
160
+ - name: Create and push manifests
161
+ env:
162
+ VERSION: ${{ needs.release.outputs.version }}
163
+ IS_PRERELEASE: ${{ needs.release.outputs.is_prerelease }}
164
+ run: |
165
+ # Build tag lists based on release type
166
+ if [ "$IS_PRERELEASE" = "true" ]; then
167
+ TAGS="beta ${VERSION}"
168
+ else
169
+ MAJOR=$(echo "$VERSION" | cut -d. -f1)
170
+ MINOR=$(echo "$VERSION" | cut -d. -f1-2)
171
+ TAGS="latest ${VERSION} ${MINOR} ${MAJOR}"
172
+ fi
173
+
174
+ DIGESTS=$(cat ${{ runner.temp }}/digests/*)
175
+
176
+ for IMAGE in "$DOCKERHUB_IMAGE" "$GHCR_IMAGE"; do
177
+ TAG_ARGS=""
178
+ for TAG in $TAGS; do
179
+ TAG_ARGS="$TAG_ARGS -t ${IMAGE}:${TAG}"
180
+ done
181
+ docker buildx imagetools create $TAG_ARGS \
182
+ $(echo "$DIGESTS" | xargs -I{} echo "${IMAGE}@{}")
183
+ done
184
+
185
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
186
+ with:
187
+ sparse-checkout: README.md
188
+ - uses: peter-evans/dockerhub-description@1b9a80c056b620d92cedb9d9b5a223409c68ddfa # v5
189
+ with:
190
+ username: ${{ secrets.DOCKERHUB_USERNAME }}
191
+ password: ${{ secrets.DOCKERHUB_TOKEN }}
192
+ repository: ${{ secrets.DOCKERHUB_USERNAME }}/better-code-review-graph
193
+ short-description: ${{ github.event.repository.description }}
194
+ readme-filepath: ./README.md
195
+
196
+ # =================== Publish to MCP Registry ===================
197
+ publish-mcp-registry:
198
+ name: Publish to MCP Registry
199
+ needs: [release, publish-pypi, merge-docker]
200
+ if: needs.release.outputs.released == 'true' && needs.release.outputs.is_prerelease != 'true'
201
+ runs-on: ubuntu-latest
202
+ steps:
203
+ - name: Harden Runner
204
+ uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2
205
+ with:
206
+ egress-policy: audit
207
+
208
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
209
+ with:
210
+ ref: ${{ needs.release.outputs.tag }}
211
+
212
+ - name: Update server.json version
213
+ run: |
214
+ VERSION="${{ needs.release.outputs.version }}"
215
+ jq --arg v "$VERSION" '
216
+ .version = $v |
217
+ .packages = [.packages[] |
218
+ if .registryType == "oci" then del(.version)
219
+ else .version = $v
220
+ end
221
+ ]
222
+ ' server.json > server.json.tmp && mv server.json.tmp server.json
223
+
224
+ - name: Install MCP Publisher
225
+ run: |
226
+ curl -L "https://github.com/modelcontextprotocol/registry/releases/latest/download/mcp-publisher_$(uname -s | tr '[:upper:]' '[:lower:]')_$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/').tar.gz" | tar xz mcp-publisher
227
+
228
+ - name: Login to MCP Registry
229
+ run: ./mcp-publisher login github-oidc
230
+
231
+ - name: Publish to MCP Registry
232
+ run: ./mcp-publisher publish