Skip to content

feat: Contributor Rewards Config v3 - Bounty #47 ($300)#90

Open
zhaog100 wants to merge 4 commits into
ubiquity-os:mainfrom
zhaog100:feat/contributor-rewards-config
Open

feat: Contributor Rewards Config v3 - Bounty #47 ($300)#90
zhaog100 wants to merge 4 commits into
ubiquity-os:mainfrom
zhaog100:feat/contributor-rewards-config

Conversation

@zhaog100
Copy link
Copy Markdown

Contributor Rewards With Config v3

Implements #47 — the third stage of the Contributor Role series ($300 bounty).

Series Overview

What it does

  • Configurable reward values per webhook event type (pull_request, issues, issue_comment, pull_request_review, etc.)
  • Contributor class detection: ISSUER, ASSIGNEE, COLLABORATOR, CONTRIBUTOR
  • Target roles for reward recipients: ISSUER, ASSIGNEE, COLLABORATOR, CONTRIBUTOR, REVIEWERS, COMMENTERS, COMMITTERS
  • Pull/Issue context separation: Different reward values for pull vs issue context within the same event
  • Label-specific overrides: Additional reward modifiers based on issue/PR labels
  • Negative values: Support for event negation (e.g., review_request_removed gives -1)

Configuration Example

pull_request:
  opened:
    pull:
      targets: [CONTRIBUTOR]
      value: 5
    issue:
      targets: [CONTRIBUTOR]
      value: 2
  closed:
    pull:
      targets: [ASSIGNEE]
      value: 10

pull_request_review:
  submitted:
    pull:
      targets: [REVIEWERS]
      value: 3

issue_comment:
  created:
    issue:
      targets: [COMMENTERS]
      value: 1

labelOverrides:
  bug:
    value: 5
  "good-first-issue":
    value: 3

Architecture

File Purpose
src/types/plugin-input.ts TypeBox schema definitions for all configuration
src/handlers/rewards.ts Core reward calculation logic (pure functions)
src/index.ts Main plugin entry point
src/worker.ts Cloudflare Workers entry point
src/action.ts GitHub Actions entry point
manifest.json Plugin manifest with all supported event listeners
tests/main.test.ts 30 comprehensive tests

How it works

  1. Receives a configured webhook event
  2. Parses event name into category + action (e.g., pull_request.opened)
  3. Looks up reward configuration for the event
  4. Determines contributor class for each involved user
  5. Checks if user matches any target role
  6. Calculates base reward + label overrides
  7. Returns aggregated reward totals

Test Results

All 30 tests pass:

  • Event name parsing
  • Contributor class detection (with priority: ISSUER > ASSIGNEE > COLLABORATOR > CONTRIBUTOR)
  • Target role matching (including REVIEWERS, COMMENTERS, COMMITTERS)
  • Reward calculation (positive, negative, zero cases)
  • Label overrides (additive, negative, multiple labels)
  • Full integration lifecycle test (open → review request → submit → close)

Tech Stack

  • TypeScript + TypeBox for schema validation
  • UbiquityOS Plugin SDK v3
  • Cloudflare Workers compatible
  • Jest/Bun test runner

Standalone Repository

Also available as a standalone repo: https://github.com/zhaog100/contributor-rewards-with-config

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 12, 2026

Warning

Rate limit exceeded

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

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 55 minutes and 31 seconds.

⌛ 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.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c21a2c62-9f23-4689-b7da-2136f465663c

📥 Commits

Reviewing files that changed from the base of the PR and between 1ad0de4 and adac3f7.

📒 Files selected for processing (4)
  • contributor-rewards-with-config/.github/workflows/compute.yml
  • contributor-rewards-with-config/.github/workflows/knip-reporter.yml
  • contributor-rewards-with-config/src/index.ts
  • contributor-rewards-with-config/tests/__mocks__/handlers.ts
📝 Walkthrough

Walkthrough

This PR adds a complete new UbiquityOS plugin called contributor-rewards-with-config that computes contributor rewards from webhook events. It includes type schemas for plugin configuration (event rewards, contributor roles, target categories), core reward-calculation logic (contributor classification, reward computation, label overrides), plugin entry points compatible with worker and action runtimes, comprehensive test coverage with mock handlers, and configuration files for development tooling (ESLint, Prettier, Jest, TypeScript, Husky) and CI/CD workflows (linting, testing, deployment).

Possibly related issues

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 76.92% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed Title accurately captures the main change: implementing configurable contributor rewards system (v3) with event-specific and multiplier support.
Description check ✅ Passed Description is directly related to the changeset, providing clear context on the feature implementation, architecture, and testing approach.

✏️ 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.

Copy link
Copy Markdown

@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

Note

Due to the large number of review comments, Critical severity comments were prioritized as inline comments.

🟠 Major comments (16)
contributor-rewards-with-config/.gitattributes-2-3 (1)

2-3: ⚠️ Potential issue | 🟠 Major

Don’t mark lockfiles as generated.

Lines 2–3 hide dependency-lock diffs in PRs, which weakens dependency review and security auditing.

Suggested fix
 dist/** linguist-generated
-*.lockb linguist-generated
-*.lock linguist-generated
contributor-rewards-with-config/.github/workflows/release-please.yml-17-17 (1)

17-17: ⚠️ Potential issue | 🟠 Major

Pin the action to a commit SHA.

The workflow has write permissions to contents and pull-requests. Line 17 uses a movable tag (@v4) instead of a commit SHA, creating a supply-chain risk.

Suggested fix
-      - uses: googleapis/release-please-action@v4
+      - uses: googleapis/release-please-action@<FULL_COMMIT_SHA> # release-please-action v4
contributor-rewards-with-config/.gitignore-20-20 (1)

20-20: ⚠️ Potential issue | 🟠 Major

Do not ignore manifest.json if it is a source-of-truth config file.

Line 20 can hide critical listener/config changes from version control and review.

Suggested fix
-manifest.json
contributor-rewards-with-config/.github/workflows/conventional-commits.yml-12-12 (1)

12-12: ⚠️ Potential issue | 🟠 Major

Pin third-party action to a commit SHA. Using @master is mutable and weakens workflow integrity.

Proposed hardening
-      - uses: ubiquity/action-conventional-commits@master
+      - uses: ubiquity/action-conventional-commits@<commit_sha>
contributor-rewards-with-config/.github/workflows/knip.yml-3-5 (1)

3-5: ⚠️ Potential issue | 🟠 Major

Handle non-PR runs before writing pr-number.txt.

Lines 20-21 assume a PR context; this is not true for workflow_dispatch. That can cascade into reporter failures.

Proposed fix
-      - name: Store PR number
-        run: echo ${{ github.event.number }} > pr-number.txt
+      - name: Store PR number
+        if: ${{ github.event_name == 'pull_request' }}
+        run: echo ${{ github.event.pull_request.number }} > pr-number.txt

Also applies to: 20-21

contributor-rewards-with-config/.github/workflows/jest-testing.yml-11-11 (1)

11-11: ⚠️ Potential issue | 🟠 Major

Scope workflow token permissions down.

Line 11 grants write-all for a test-only job. Prefer least privilege.

Proposed fix
-    permissions: write-all
+    permissions:
+      contents: read
contributor-rewards-with-config/tsconfig.json-32-32 (1)

32-32: ⚠️ Potential issue | 🟠 Major

Add Node types to the types array.

The "types": ["jest"] setting excludes @types/node, which causes incomplete typing for Node globals used in source files. Properties like process.env.NODE_ENV are accessed in src/action.ts and src/worker.ts but lack proper typing. The custom process-env.d.ts attempts to extend NodeJS.ProcessEnv, but without @types/node in the ambient types, it cannot resolve the base types.

Fix
-    "types": ["jest"] /* Specify type package names to be included without being referenced in a source file. */,
+    "types": ["node", "jest"] /* Include Node globals for src and Jest globals for tests. */,
contributor-rewards-with-config/src/types/env.ts-2-2 (1)

2-2: ⚠️ Potential issue | 🟠 Major

Move dotenv/config loading to Node-only entrypoint.

The dotenv/config import at line 2 causes Node-specific side effects when worker.ts (Cloudflare Worker) imports from ./types. Cloudflare Workers don't support Node's dotenv module, causing bundling/runtime errors.

Move the import to action.ts (GitHub Actions entrypoint) where it belongs, leaving env.ts as pure type definitions.

contributor-rewards-with-config/.github/workflows/compute.yml-25-29 (1)

25-29: ⚠️ Potential issue | 🟠 Major

Reduce permissions from write-all.

Line 28 grants far more than this job shows it needs. Please scope the token to the exact repo permissions required by the plugin execution path.

contributor-rewards-with-config/tests/__mocks__/helpers.ts-14-40 (1)

14-40: ⚠️ Potential issue | 🟠 Major

Make setupTests() safe to call more than once.

This helper recreates the same repo and issue IDs on every call without resetting the in-memory DB first. Reusing it from beforeEach or multiple suites will leak state or hit primary-key conflicts.

contributor-rewards-with-config/src/worker.ts-33-35 (1)

33-35: ⚠️ Potential issue | 🟠 Major

Move NODE_ENV to the env schema.

Line 35 reads process.env.NODE_ENV, but environment variables in Cloudflare Workers should be declared in envSchema and passed through the env parameter. Add NODE_ENV to the schema in env.ts and read it from env.NODE_ENV instead.

contributor-rewards-with-config/.github/workflows/update-configuration.yml-134-134 (1)

134-134: ⚠️ Potential issue | 🟠 Major

Avoid write-all; scope job permissions minimally.

Line 134 and Line 156 grant full write permissions. That is broader than necessary for deploy workflows.

Proposed tightening
-    permissions: write-all
+    permissions:
+      contents: write
+      actions: read
+      id-token: none

Also applies to: 156-156

contributor-rewards-with-config/src/handlers/rewards.ts-172-174 (1)

172-174: ⚠️ Potential issue | 🟠 Major

Label overrides currently reward non-target contributors.

Line 173 applies label overrides even when Line 172 computed baseReward = 0.
That can create rewards for users who did not match any target role.

Proposed fix
-      const finalReward = applyLabelOverrides(baseReward, labels, labelOverrideConfig);
+      const finalReward = baseReward === 0 ? 0 : applyLabelOverrides(baseReward, labels, labelOverrideConfig);
contributor-rewards-with-config/tests/__mocks__/handlers.ts-59-72 (1)

59-72: ⚠️ Potential issue | 🟠 Major

getValue can truncate payloads and return undefined unexpectedly.

Line 62 reads a single stream chunk only.
Lines 43/51 destructure the result; parse/read failure here can throw at runtime.

Proposed fix
-async function getValue(body: ReadableStream<Uint8Array> | null) {
-  if (body) {
-    const reader = body.getReader();
-    const streamResult = await reader.read();
-    if (!streamResult.done) {
-      const text = new TextDecoder().decode(streamResult.value);
-      try {
-        return JSON.parse(text);
-      } catch (error) {
-        console.error("Failed to parse body as JSON", error);
-      }
-    }
-  }
+async function getValue(body: ReadableStream<Uint8Array> | null): Promise<Record<string, unknown> | undefined> {
+  if (!body) return undefined;
+  const reader = body.getReader();
+  const chunks: Uint8Array[] = [];
+  while (true) {
+    const { done, value } = await reader.read();
+    if (done) break;
+    if (value) chunks.push(value);
+  }
+  if (chunks.length === 0) return undefined;
+  const total = chunks.reduce((n, c) => n + c.length, 0);
+  const merged = new Uint8Array(total);
+  let offset = 0;
+  for (const c of chunks) {
+    merged.set(c, offset);
+    offset += c.length;
+  }
+  try {
+    return JSON.parse(new TextDecoder().decode(merged));
+  } catch (error) {
+    console.error("Failed to parse body as JSON", error);
+    return undefined;
+  }
 }
contributor-rewards-with-config/src/handlers/rewards.ts-71-78 (1)

71-78: ⚠️ Potential issue | 🟠 Major

Actionless events cannot resolve reward config.

Line 77 always indexes by action. For events like push (parsed with action: ""), this returns undefined, so configured push rewards never apply.

Proposed fix
 export function getEventRewardConfig(settings: PluginSettings, eventName: string): EventRewardType | undefined {
   const { category, action } = parseEventName(eventName);
   const categoryConfig = settings[category as keyof PluginSettings];
   if (!categoryConfig || typeof categoryConfig !== "object") {
     return undefined;
   }
+  if (action === "" && ("pull" in (categoryConfig as object) || "issue" in (categoryConfig as object))) {
+    return categoryConfig as EventRewardType;
+  }
   return (categoryConfig as Record<string, EventRewardType | undefined>)[action];
 }
contributor-rewards-with-config/.github/workflows/update-configuration.yml-139-140 (1)

139-140: ⚠️ Potential issue | 🟠 Major

Pin action refs to commit SHAs instead of mutable tags.

Lines 139 and 163 use mutable @main refs, breaking reproducibility and increasing supply-chain risk. actions/checkout@v6 (line 160) is stable and available, but pinning to a specific commit SHA (e.g., @afaa513f0354a1e1ddde9e0f38cd2191a9b3dd7c # v6.0.2) is the recommended best practice for production workflows per GitHub security guidelines.

Current state
139:        uses: ubiquity-os/action-deploy-plugin@main
160:      - uses: actions/checkout@v6
163:      - uses: ubiquity-os/deno-deploy@main
🟡 Minor comments (4)
contributor-rewards-with-config/.dev.vars.example-1-1 (1)

1-1: ⚠️ Potential issue | 🟡 Minor

Align example vars with actual plugin env keys.

Line 1 uses MY_SECRET, but runtime config appears to rely on LOG_LEVEL and KERNEL_PUBLIC_KEY. This can confuse local setup.

Suggested update
-MY_SECRET="MY_SECRET"
+LOG_LEVEL="INFO"
+KERNEL_PUBLIC_KEY=""
contributor-rewards-with-config/tests/__mocks__/users-get.json-8-10 (1)

8-10: ⚠️ Potential issue | 🟡 Minor

Duplicate login value can make tests ambiguous.

Line 10 repeats login: "user1" for a different user. With current seeding, this can produce nondeterministic expectations in login-based lookups.

Suggested fix
   {
     "id": 2,
     "name": "user2",
-    "login": "user1"
+    "login": "user2"
   }
contributor-rewards-with-config/src/types/process-env.d.ts-3-5 (1)

3-5: ⚠️ Potential issue | 🟡 Minor

Make GITHUB_TOKEN optional or remove it entirely.

GITHUB_TOKEN is declared as required but is unused and not included in envSchema. Either remove it or change to GITHUB_TOKEN?: string; to match the codebase pattern for optional environment variables (e.g., KERNEL_PUBLIC_KEY).

contributor-rewards-with-config/.github/workflows/jest-testing.yml-27-29 (1)

27-29: ⚠️ Potential issue | 🟡 Minor

Guard summary append when report file is missing.

Line 29 will fail if test-dashboard.md was not generated.

Proposed fix
-      - name: Add Jest Report to Summary
-        if: always()
-        run: echo "$(cat test-dashboard.md)" >> $GITHUB_STEP_SUMMARY
+      - name: Add Jest Report to Summary
+        if: always()
+        run: |
+          if [ -f test-dashboard.md ]; then
+            cat test-dashboard.md >> "$GITHUB_STEP_SUMMARY"
+          fi
🧹 Nitpick comments (8)
contributor-rewards-with-config/.github/CODEOWNERS (1)

1-1: Add a default CODEOWNERS rule.

This file is currently a no-op. Add at least a catch-all mapping (for example, * @org/team``) so ownership and review routing are actually enforced.

contributor-rewards-with-config/.env.example (1)

1-1: Make .env.example self-contained with required keys.

Line 1 is useful, but adding explicit required variable placeholders here will reduce setup friction.

contributor-rewards-with-config/tests/__mocks__/issue-template.ts (1)

10-10: Prefer fixed timestamps in fixtures. new Date() in test data can make failures harder to reproduce.

Proposed tweak
-  created_at: new Date().toISOString(),
+  created_at: "2026-01-01T00:00:00.000Z",
...
-  updated_at: "",
+  updated_at: "2026-01-01T00:00:00.000Z",

Also applies to: 23-23

contributor-rewards-with-config/.github/workflows/formatting-checks.yml (1)

19-24: Use the repo script to avoid CI drift. Reusing check-formatting keeps local and CI behavior aligned.

Proposed simplification
       - name: Run formatting checks
         run: |
           bun install
-          bun eslint --fix-dry-run --ignore-pattern dist/
-          bun format:cspell
-          bun prettier --check .
+          bun run check-formatting
contributor-rewards-with-config/.cspell.json (1)

4-4: ignorePaths is too broad. Ignoring **/*.json disables spellcheck for most config files.

Proposed change
-  "ignorePaths": ["**/*.json", "**/*.css", "node_modules", "**/*.log", "./src/adapters/supabase/**/**.ts", "dist"],
+  "ignorePaths": ["**/*.css", "node_modules", "**/*.log", "./src/adapters/supabase/**/**.ts", "dist"],
contributor-rewards-with-config/.github/knip.ts (1)

4-4: Include worker entry in Knip scope. This avoids false positives/negatives for worker-only imports.

Proposed update
-  entry: ["src/action.ts"],
+  entry: ["src/action.ts", "src/worker.ts"],
contributor-rewards-with-config/package.json (1)

27-29: Pin the manifest tool version.

Using @latest here makes installs and builds non-reproducible. A new upstream release can break CI or generate a different manifest without any code change in this repo.

contributor-rewards-with-config/tests/main.test.ts (1)

194-200: Add a regression test for non-target + label override behavior.

Current tests verify override math, but not whether overrides should apply when base reward is 0 for a non-target contributor.

Suggested test addition
+    it("should not grant label override to non-target contributors", () => {
+      const localSettings: PluginSettings = {
+        pull_request: {
+          opened: { pull: { targets: [TargetRole.ISSUER], value: 5 } },
+        },
+        labelOverrides: {
+          bug: { value: 3 },
+        },
+      };
+      const rewards = calculateRewards(
+        localSettings,
+        "pull_request.opened",
+        [{ login: "bob", issueAuthor: "alice", isOrgMember: false }],
+        "pull",
+        [{ name: "bug" }]
+      );
+      expect(rewards).toHaveLength(0);
+    });

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 7973e93a-9aaa-45ea-95b9-f7699204c4da

📥 Commits

Reviewing files that changed from the base of the PR and between edb3383 and 1ad0de4.

📒 Files selected for processing (47)
  • contributor-rewards-with-config/.cspell.json
  • contributor-rewards-with-config/.dev.vars.example
  • contributor-rewards-with-config/.env.example
  • contributor-rewards-with-config/.gitattributes
  • contributor-rewards-with-config/.github/CODEOWNERS
  • contributor-rewards-with-config/.github/knip.ts
  • contributor-rewards-with-config/.github/pull_request_template.md
  • contributor-rewards-with-config/.github/workflows/compute.yml
  • contributor-rewards-with-config/.github/workflows/conventional-commits.yml
  • contributor-rewards-with-config/.github/workflows/formatting-checks.yml
  • contributor-rewards-with-config/.github/workflows/jest-testing.yml
  • contributor-rewards-with-config/.github/workflows/knip-reporter.yml
  • contributor-rewards-with-config/.github/workflows/knip.yml
  • contributor-rewards-with-config/.github/workflows/release-please.yml
  • contributor-rewards-with-config/.github/workflows/update-configuration.yml
  • contributor-rewards-with-config/.gitignore
  • contributor-rewards-with-config/.husky/commit-msg
  • contributor-rewards-with-config/.husky/pre-commit
  • contributor-rewards-with-config/.nvmrc
  • contributor-rewards-with-config/.prettierignore
  • contributor-rewards-with-config/.prettierrc
  • contributor-rewards-with-config/.yarnrc.yml
  • contributor-rewards-with-config/README.md
  • contributor-rewards-with-config/eslint.config.mjs
  • contributor-rewards-with-config/jest.config.ts
  • contributor-rewards-with-config/package.json
  • contributor-rewards-with-config/src/action.ts
  • contributor-rewards-with-config/src/handlers/rewards.ts
  • contributor-rewards-with-config/src/index.ts
  • contributor-rewards-with-config/src/types.ts
  • contributor-rewards-with-config/src/types/context.ts
  • contributor-rewards-with-config/src/types/env.ts
  • contributor-rewards-with-config/src/types/index.ts
  • contributor-rewards-with-config/src/types/plugin-input.ts
  • contributor-rewards-with-config/src/types/process-env.d.ts
  • contributor-rewards-with-config/src/worker.ts
  • contributor-rewards-with-config/strings.json
  • contributor-rewards-with-config/tests/__mocks__/db.ts
  • contributor-rewards-with-config/tests/__mocks__/handlers.ts
  • contributor-rewards-with-config/tests/__mocks__/helpers.ts
  • contributor-rewards-with-config/tests/__mocks__/issue-template.ts
  • contributor-rewards-with-config/tests/__mocks__/node.ts
  • contributor-rewards-with-config/tests/__mocks__/strings.ts
  • contributor-rewards-with-config/tests/__mocks__/users-get.json
  • contributor-rewards-with-config/tests/main.test.ts
  • contributor-rewards-with-config/tsconfig.json
  • contributor-rewards-with-config/wrangler.toml

Comment thread contributor-rewards-with-config/.github/workflows/compute.yml
Comment thread contributor-rewards-with-config/.github/workflows/knip-reporter.yml Outdated
Comment thread contributor-rewards-with-config/src/index.ts Outdated
Comment thread contributor-rewards-with-config/src/index.ts
Comment on lines +38 to +48
// For now, compute reward for the sender
const contributors = [
{
login: sender.login,
issueAuthor: issueOrPull.user?.login,
assignees: issueOrPull.assignees,
isOrgMember: false, // Would need API call to determine
},
];

const rewards: ContributorReward[] = calculateRewards(config, eventName, contributors, contextType, labels);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Only rewarding the sender breaks target-based payouts.

This path never materializes REVIEWERS, COMMENTERS, or COMMITTERS, and COLLABORATOR can never match because Line 44 hard-codes isOrgMember: false. Events like pull_request.review_requested will pay the actor instead of the requested reviewer.

Comment thread contributor-rewards-with-config/tests/__mocks__/handlers.ts Outdated
OpenClaw Bot and others added 3 commits April 13, 2026 23:53
- Add build steps to workflow (setup-node, npm ci, npm run build)
- Scope permissions from write-all to minimum required
- Fix PR comment detection: check payload.issue.pull_request for issue_comment events
- Fix issueAuthor to be boolean (was comparing to login string)
- Fix relative imports in src/index.ts (../types → ./types, ../handlers/rewards → ./handlers/rewards)
- Harden knip-reporter.yml: restrict permissions to least-privilege (contents: read, pull-requests: write) and pin action to specific commit
- Fix PATCH comment handler in tests: use route :id param instead of issue_number, properly lookup existing record
@zhaog100
Copy link
Copy Markdown
Author

Hi! 👋 Friendly follow-up on this PR (submitted 16+ days ago).

Happy to address any feedback or make adjustments if needed. Please let me know if there's anything I can help with to move this forward. 🙏

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