Skip to content

Commit 030ab8f

Browse files
committed
Add BC PHP codegen customizations and release workflow
- getExpectedResponseMessages(): maps method names to response message types - getServiceName(): returns the fully qualified gRPC service name - Add workflow to build and attach grpc_php_plugin binaries on release
1 parent f5e2d6e commit 030ab8f

3 files changed

Lines changed: 199 additions & 0 deletions

File tree

.claude/skills/bc-release/SKILL.md

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
---
2+
name: bc-release
3+
description: Create a new BigCommerce patched release of grpc. Use when upgrading to a new upstream grpc version, creating BC release branches/tags, or managing the BC fork.
4+
---
5+
6+
# BC gRPC Release Management
7+
8+
This skill handles creating and managing BigCommerce-patched releases of grpc/grpc.
9+
10+
## Remotes
11+
12+
- `origin` = `grpc/grpc` (upstream)
13+
- `bc` = `bigcommerce/grpc` (BC fork)
14+
15+
## Arguments
16+
17+
`$ARGUMENTS` should be the upstream version to target (e.g., `1.81.0`, `v1.81.x`).
18+
19+
## BC Patch
20+
21+
All BC releases apply a single patch to `src/compiler/php_generator.cc` that adds three PHP codegen customizations:
22+
23+
1. **`getExpectedResponseMessages()`** — maps method names to their response message types
24+
2. **`getServiceName()`** — returns the fully qualified gRPC service name
25+
26+
The patch also includes `.github/workflows/release-php-plugin.yaml` which builds and attaches `grpc_php_plugin` binaries (linux-amd64, darwin-arm64) to the release automatically.
27+
28+
## Steps
29+
30+
### 1. Sync bc/master with upstream
31+
32+
```bash
33+
git fetch origin && git fetch bc
34+
git push bc origin/master:refs/heads/master --force
35+
```
36+
37+
### 2. Push upstream release tags to bc
38+
39+
This is required so the compare link (`vX.YY.0...vX.YY.0-bc`) resolves on the BC fork.
40+
41+
```bash
42+
# List all tags for the version
43+
git tag -l 'vX.YY.*'
44+
# Push ALL upstream tags for this release to bc
45+
git push bc vX.YY.0 vX.YY.0-pre1 # include all tags from the list above
46+
```
47+
48+
**Do not skip this step.** If the upstream tag is missing from bc, the release compare link and GitHub diff will be broken.
49+
50+
### 3. Create the release branch
51+
52+
```bash
53+
git checkout -b X.YY.x-bc origin/vX.YY.x
54+
```
55+
56+
### 4. Apply the BC patch
57+
58+
Read the current state of `src/compiler/php_generator.cc` on the new branch. Then apply these changes:
59+
60+
**In `PrintService()` function:**
61+
- After `out->Indent(); out->Indent();`, before `if (!is_server)`, add:
62+
63+
```cpp
64+
out->Print("public function getExpectedResponseMessages() {\n");
65+
out->Indent();
66+
out->Print("return [\n");
67+
out->Indent();
68+
map<std::string, std::string> response_vars;
69+
for (int i = 0; i < service->method_count(); i++) {
70+
const Descriptor* output_type = service->method(i)->output_type();
71+
response_vars["method_name"] = grpc_generator::LowercaseFirstLetter(std::string(service->method(i)->name()));
72+
response_vars["output_type_id"] = MessageIdentifierName(GeneratedClassName(output_type), output_type->file());
73+
out->Print(response_vars, "'$method_name$' => '\\$output_type_id$',\n");
74+
}
75+
out->Outdent();
76+
out->Print("];\n");
77+
out->Outdent();
78+
out->Print("}\n\n");
79+
80+
// getServiceName() -> string - The name of the gRPC service
81+
map<std::string, std::string> service_vars;
82+
service_vars["service_name"] = service->full_name();
83+
out->Print("public function getServiceName() {\n");
84+
out->Indent();
85+
out->Print(service_vars, "return '$service_name$';\n");
86+
out->Outdent();
87+
out->Print("}\n\n");
88+
```
89+
90+
**Also include the release workflow:**
91+
- Copy `.github/workflows/release-php-plugin.yaml` from `bc/master` or the previous `-bc` branch.
92+
93+
### 5. Commit, tag, and push
94+
95+
```bash
96+
git add src/compiler/php_generator.cc .github/workflows/release-php-plugin.yaml
97+
git commit -m "Add BC PHP codegen customizations and release workflow"
98+
git tag vX.YY.0-bc X.YY.x-bc
99+
git push bc X.YY.x-bc
100+
git push bc vX.YY.0-bc
101+
```
102+
103+
### 6. Create the GitHub release
104+
105+
```bash
106+
gh release create vX.YY.0-bc --repo bigcommerce/grpc \
107+
--title "vX.YY.0-bc" \
108+
--notes "gRPC vX.YY.0 with BigCommerce PHP codegen customizations.
109+
110+
Based on upstream [vX.YY.0](https://github.com/grpc/grpc/releases/tag/vX.YY.0). See [diff](https://github.com/bigcommerce/grpc/compare/vX.YY.0...vX.YY.0-bc)."
111+
```
112+
113+
The `release-php-plugin.yaml` workflow will automatically build and attach `grpc_php_plugin` binaries.
114+
115+
### 7. Verify
116+
117+
- Compare link shows only the BC patch: `https://github.com/bigcommerce/grpc/compare/vX.YY.0...vX.YY.0-bc`
118+
- Release workflow builds and attaches binaries: check GitHub Actions
119+
- Release has `grpc_php_plugin-linux-amd64.zip` and `grpc_php_plugin-darwin-arm64.zip` assets
120+
121+
## Important Notes
122+
123+
- The patch modifies ONLY `src/compiler/php_generator.cc` — if upstream changes this file significantly, the patch may need manual adaptation (watch for type changes like `grpc::string``std::string`).
124+
- Always read the current file before patching — don't blindly apply line numbers from previous versions.
125+
- The release workflow lives on `bc/master`. If bc/master is synced (force-pushed) from upstream, the workflow file will be lost and needs to be re-added.
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
name: Release PHP Plugin
2+
3+
on:
4+
release:
5+
types: [published]
6+
7+
permissions:
8+
contents: write
9+
10+
jobs:
11+
build:
12+
strategy:
13+
matrix:
14+
include:
15+
- os: ubuntu-22.04
16+
artifact: grpc_php_plugin-linux-amd64
17+
- os: macos-latest
18+
artifact: grpc_php_plugin-darwin-arm64
19+
runs-on: ${{ matrix.os }}
20+
steps:
21+
- name: Check out repository
22+
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
23+
with:
24+
submodules: true
25+
26+
- name: Build grpc_php_plugin
27+
run: |
28+
mkdir -p cmake/build
29+
cd cmake/build
30+
cmake ../.. \
31+
-DgRPC_BUILD_TESTS=OFF \
32+
-DgRPC_BUILD_GRPC_PHP_PLUGIN=ON \
33+
-DCMAKE_BUILD_TYPE=Release
34+
make -j$(nproc 2>/dev/null || sysctl -n hw.logicalcpu) grpc_php_plugin
35+
36+
- name: Package binary
37+
run: |
38+
cd cmake/build
39+
zip ${{ matrix.artifact }}.zip grpc_php_plugin
40+
41+
- name: Upload release asset
42+
env:
43+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
44+
run: |
45+
gh release upload "${{ github.event.release.tag_name }}" \
46+
cmake/build/${{ matrix.artifact }}.zip \
47+
--repo ${{ github.repository }} \
48+
--clobber

src/compiler/php_generator.cc

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,32 @@ void PrintService(const ServiceDescriptor* service,
292292
out->Print(vars, "class $name$ $extends${\n\n");
293293
out->Indent();
294294
out->Indent();
295+
296+
out->Print("public function getExpectedResponseMessages() {\n");
297+
out->Indent();
298+
out->Print("return [\n");
299+
out->Indent();
300+
map<std::string, std::string> response_vars;
301+
for (int i = 0; i < service->method_count(); i++) {
302+
const Descriptor* output_type = service->method(i)->output_type();
303+
response_vars["method_name"] = grpc_generator::LowercaseFirstLetter(std::string(service->method(i)->name()));
304+
response_vars["output_type_id"] = MessageIdentifierName(GeneratedClassName(output_type), output_type->file());
305+
out->Print(response_vars, "'$method_name$' => '\\$output_type_id$',\n");
306+
}
307+
out->Outdent();
308+
out->Print("];\n");
309+
out->Outdent();
310+
out->Print("}\n\n");
311+
312+
// getServiceName() -> string - The name of the gRPC service
313+
map<std::string, std::string> service_vars;
314+
service_vars["service_name"] = service->full_name();
315+
out->Print("public function getServiceName() {\n");
316+
out->Indent();
317+
out->Print(service_vars, "return '$service_name$';\n");
318+
out->Outdent();
319+
out->Print("}\n\n");
320+
295321
if (!is_server) {
296322
out->Print(
297323
"/**\n * @param string $$hostname hostname\n"

0 commit comments

Comments
 (0)