Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion actions/setup/js/github_rate_limit_logger.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -183,11 +183,23 @@ function createRateLimitAwareGithub(github) {
get(target, method) {
const fn = target[method];
if (typeof fn !== "function") return fn;
return async (/** @type {any[]} */ ...args) => {
const wrapper = async (/** @type {any[]} */ ...args) => {
const response = await fn.apply(target, args);
logRateLimitFromResponse(response, `${namespaceName}.${String(method)}`);
return response;
};
// Wrap the wrapper in a Proxy so that Octokit-specific property accesses
// (e.g. .endpoint, used by github.paginate()) fall back to the original fn.
// Without this, github.paginate(github.rest.checks.listForRef, ...) throws
// "route.endpoint is not a function" because the wrapper does not have
// the .endpoint decorator that Octokit endpoint methods carry.
return new Proxy(wrapper, {
get(wrapperTarget, prop) {
const own = Reflect.get(wrapperTarget, prop);
if (own !== undefined) return own;
return Reflect.get(fn, prop);
},
});
},
});
}
Expand Down
45 changes: 45 additions & 0 deletions actions/setup/js/github_rate_limit_logger.test.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -354,4 +354,49 @@ describe("createRateLimitAwareGithub", () => {
expect(first.remaining).toBe(4999);
expect(second.remaining).toBe(4998);
});

it("preserves .endpoint on the wrapped method for github.paginate() compatibility", () => {
// Octokit endpoint-decorated methods (e.g. github.rest.checks.listForRef) carry
// a .endpoint property used by github.paginate() internally. The proxy must
// forward .endpoint to the original function so paginate() doesn't throw
// "route.endpoint is not a function".
const endpointObj = { merge: vi.fn(), defaults: vi.fn() };
const mockListForRef = vi.fn().mockResolvedValue({ data: [], headers: {} });
mockListForRef.endpoint = endpointObj;

const mockGithub = {
rest: {
checks: { listForRef: mockListForRef },
},
};

const gh = createRateLimitAwareGithub(mockGithub);
const wrapped = gh.rest.checks.listForRef;

// The wrapped function must expose .endpoint from the original
expect(typeof wrapped).toBe("function");
expect(wrapped.endpoint).toBe(endpointObj);
expect(wrapped.endpoint.merge).toBe(endpointObj.merge);
});

it("allows github.paginate() to call endpoint.merge on the wrapped method", () => {
// Simulate how @octokit/plugin-paginate-rest v9+ uses the endpoint method:
// const options = route.endpoint.merge(parameters)
const mergedOptions = { url: "/repos/o/r/commits/main/check-runs", per_page: 100 };
const endpointObj = { merge: vi.fn().mockReturnValue(mergedOptions) };
const mockListForRef = vi.fn().mockResolvedValue({ data: [], headers: {} });
mockListForRef.endpoint = endpointObj;

const mockGithub = {
rest: { checks: { listForRef: mockListForRef } },
};

const gh = createRateLimitAwareGithub(mockGithub);
const wrapped = gh.rest.checks.listForRef;

// paginate() would call this internally
const result = wrapped.endpoint.merge({ owner: "o", repo: "r", ref: "main", per_page: 100 });
expect(result).toBe(mergedOptions);
expect(endpointObj.merge).toHaveBeenCalledWith({ owner: "o", repo: "r", ref: "main", per_page: 100 });
});
});
2 changes: 2 additions & 0 deletions actions/setup/setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ MCP_SCRIPTS_FILES=(
"read_buffer.cjs"
"generate_mcp_scripts_config.cjs"
"setup_globals.cjs"
"github_rate_limit_logger.cjs"
"error_helpers.cjs"
"error_codes.cjs"
"constants.cjs"
Expand Down Expand Up @@ -288,6 +289,7 @@ SAFE_OUTPUTS_FILES=(
"write_large_content_to_file.cjs"
"generate_compact_schema.cjs"
"setup_globals.cjs"
"github_rate_limit_logger.cjs"
"error_helpers.cjs"
"error_codes.cjs"
"constants.cjs"
Expand Down
Loading