-
Notifications
You must be signed in to change notification settings - Fork 1
[sc-30416]: Cache Slack user details by GitHub user login to mitigate API rate limiting #167
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
[sc-30416]: Cache Slack user details by GitHub user login to mitigate API rate limiting #167
Conversation
NOTES: - Introduce `.github/actions/generate-mapping/action.yml` for generating a JSON mapping of Slack users by GitHub login. - Add `src/githubToSlackMapping.ts` to fetch GitHub org users, match them to Slack users, and output mapping. - Refactor `src/main.ts` to support `notify` and `generate-mapping` modes via `__mode` input. - Update `action.yml` to include `__mode` input for internal mode selection. Signed-off-by: Jake Schurch <[email protected]>
…er by GitHub login - Introduce `user_mapping_filepath` input in `action.yml` to optionally provide a mapping file for Slack user details by GitHub login. - Update `getMessageAuthorFactory` and related logic to use the mapping file if provided, avoiding Slack and GitHub API calls when possible. - Add fallback and error handling for mapping file usage. - Refactor main entry to pass `user_mapping_filepath` to author resolution. Signed-off-by: Jake Schurch <[email protected]>
…er by GitHub login - Introduce `user_mapping_filepath` input in `action.yml` to optionally provide a mapping file for Slack user details by GitHub login. - Update `getMessageAuthorFactory` and related logic to use the mapping file if provided, avoiding Slack and GitHub API calls when possible. - Add fallback and error handling for mapping file usage. - Refactor main entry to pass `user_mapping_filepath` to author resolution. Signed-off-by: Jake Schurch <[email protected]>
Signed-off-by: Jake Schurch <[email protected]>
fc64a95
to
346c9a6
Compare
Signed-off-by: Jake Schurch <[email protected]>
Signed-off-by: Jake Schurch <[email protected]>
9430cde
to
ae30272
Compare
Signed-off-by: Jake Schurch <[email protected]>
Signed-off-by: Jake Schurch <[email protected]>
- Separate notify and generateMapping logic into distinct entrypoints (`src/notify.ts` and new `src/generateMapping.ts`) - Remove internal `__mode` input from action.yml files - Update action.yml and generate-mapping/action.yml to reference new dist entrypoints - Refactor package.json exports and scripts for new structure - Improve maintainability and clarity by decoupling action responsibilities refs: [sc-30416] Signed-off-by: Jake Schurch <[email protected]>
…g to file - Change output from file path to raw JSON string in GitHub Action output (`raw_mapping_json`) - Update `generateGithubToSlackMapping` to return JSON string instead of writing to disk - Remove file system operations from mapping generation logic - Update action input/output and usage to reflect new output format Signed-off-by: Jake Schurch <[email protected]>
…Slack user mapping - Add details to README about the optional SLACK_GITHUB_MAPPING_RAW environment variable, allowing users to provide raw JSON or YAML mappings of GitHub logins to Slack user details. - Explains usage, example formats, and benefits of avoiding API calls for user mapping. refs: sc-30416 Signed-off-by: Jake Schurch <[email protected]>
Signed-off-by: Jake Schurch <[email protected]>
Signed-off-by: Jake Schurch <[email protected]>
Signed-off-by: Jake Schurch <[email protected]>
Signed-off-by: Jake Schurch <[email protected]>
Signed-off-by: Jake Schurch <[email protected]>
fdef784
to
251c8b8
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for your work on this, @jakeschurch – this is looking great!
I might take a pass through the README once the dust settles.
… guard tests - Refactor mapping extraction to use `githubUserMapping` instead of `rawMapping` - Validate mapping shape using new `isMessageAuthor` type guard - Extract and use `isMemberWithProfile` and `isMessageAuthor` type guards across codebase - Add tests for type guards in `src/slack/__tests__/types.test.ts` - Update environment variable to `SLACK_DEPLOY_GITHUB_USERS` - Remove redundant debug logging and simplify Slack user matching logic - Update README refs: [sc-30416] Signed-off-by: Jake Schurch <[email protected]>
Signed-off-by: Jake Schurch <[email protected]>
…gic to helper - Move Slack user lookup by GitHub name to new `getSlackUserFromGithubName` function for reuse and clarity. - Replace inline Slack user matching logic in `getMessageAuthorFactory` and `generateGithubToSlackMapping` with the new helper. - Update `isMemberWithProfile` type guard to remove `real_name` null check, relying only on `display_name` and `image_48` presence. - Minor option default value change in `getMessageAuthorFactory` (`githubUserMapping: undefined`). Signed-off-by: Jake Schurch <[email protected]>
Signed-off-by: Jake Schurch <[email protected]>
Signed-off-by: Jake Schurch <[email protected]>
Signed-off-by: Jake Schurch <[email protected]>
Signed-off-by: Jake Schurch <[email protected]>
Signed-off-by: Jake Schurch <[email protected]>
Signed-off-by: Jake Schurch <[email protected]>
Signed-off-by: Jake Schurch <[email protected]>
Signed-off-by: Jake Schurch <[email protected]>
- move to separate module - rename from getSlackUserFromGithubName - filter MemberWithProfile in SlackClient
- remove unnecessary reduce - surface empty set short circuits; move to warning - preserve not found `null` values - fix GitHubUser type
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is close! I pushed up a few commits and have a few more comments before I do some manual testing on my end. I'm happy to help with some of the loose ends – just let me know.
src/generateMapping.ts
Outdated
} | ||
} | ||
|
||
async function generateMapping( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jakeschurch, would you be open to making this name more specific? I'd be happy to make the change, if so.
src/generateUserMapping.ts
Outdated
channel, | ||
errorReaction |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jakeschurch, any objections to making these channel
/ errorReaction
dependencies optional?
/** | ||
* Return all GitHub usernames from the specified `github_org`, mapped to their Slack user. | ||
* | ||
* The users are matched by full name. If a match is not found, the value will be `null`. | ||
*/ | ||
export async function githubToSlackMapping( | ||
octokit: OctokitClient, | ||
slack: SlackClient, | ||
github_org: string | ||
): Promise<Record<string, MessageAuthor | null>> { | ||
const githubUsers = await fetchGitHubUsers(octokit, github_org) | ||
if (githubUsers.length === 0) { | ||
warning('No GitHub members found.') | ||
return {} | ||
} | ||
|
||
info('Fetching Slack users') | ||
const slackUsers = await slack.getRealUsers() | ||
if (slackUsers.length === 0) { | ||
warning('No Slack users found.') | ||
return {} | ||
} | ||
|
||
const result: Record<string, MessageAuthor | null> = {} | ||
|
||
for (const githubUser of githubUsers) { | ||
try { | ||
const slackUser = getSlackUserFromName(slackUsers, githubUser.name) | ||
|
||
result[githubUser.login] = { | ||
slack_user_id: slackUser.id, | ||
username: slackUser.profile.display_name, | ||
icon_url: slackUser.profile.image_48 | ||
} | ||
} catch (err) { | ||
warning(err instanceof Error ? err.message : String(err)) | ||
|
||
result[githubUser.login] = null | ||
} | ||
} | ||
|
||
return result | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
4edb065 simplified this implementation a bit.
Also notably, I widened the return interface to include null
values, signifying a Slack user could not be matched. I was thinking that could enable a nice getMessageAuthor
optimization – essentially skipping the expensive API calls when we already know a user will not match (via null
) while still falling back to them for a presumably new / unknown user (via undefined
).
Thoughts on that proposed behavior? I didn't update getMessageAuthor
yet but happy to do so if you're onboard.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated getMessageAuthor
in 4732a6a.
- collapse getMessageAuthorFromGithubUserMapping into maybeGetMessageAuthorFromGithubUserMapping - tighten type predicate - improve error handling - introduce GitHubUserMapping type
- notify -> notifySlack - generateMapping -> generateUserMapping - move non-entrypoints to utils/ namespace
channel and errorReaction are unnecessary in the generateUserMapping context
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alright I think this is pretty close to code-complete. @jakeschurch, would you mind glancing at where this is landing?
I just need to do some manual testing and would like to take a pass at documentation.
src/generateMapping.ts
Outdated
} | ||
} | ||
|
||
async function generateMapping( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Renamed to generateUserMapping
in b1f2cb5.
I also renamed notify
→ notifySlack
.
/** | ||
* Return all GitHub usernames from the specified `github_org`, mapped to their Slack user. | ||
* | ||
* The users are matched by full name. If a match is not found, the value will be `null`. | ||
*/ | ||
export async function githubToSlackMapping( | ||
octokit: OctokitClient, | ||
slack: SlackClient, | ||
github_org: string | ||
): Promise<Record<string, MessageAuthor | null>> { | ||
const githubUsers = await fetchGitHubUsers(octokit, github_org) | ||
if (githubUsers.length === 0) { | ||
warning('No GitHub members found.') | ||
return {} | ||
} | ||
|
||
info('Fetching Slack users') | ||
const slackUsers = await slack.getRealUsers() | ||
if (slackUsers.length === 0) { | ||
warning('No Slack users found.') | ||
return {} | ||
} | ||
|
||
const result: Record<string, MessageAuthor | null> = {} | ||
|
||
for (const githubUser of githubUsers) { | ||
try { | ||
const slackUser = getSlackUserFromName(slackUsers, githubUser.name) | ||
|
||
result[githubUser.login] = { | ||
slack_user_id: slackUser.id, | ||
username: slackUser.profile.display_name, | ||
icon_url: slackUser.profile.image_48 | ||
} | ||
} catch (err) { | ||
warning(err instanceof Error ? err.message : String(err)) | ||
|
||
result[githubUser.login] = null | ||
} | ||
} | ||
|
||
return result | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated getMessageAuthor
in 4732a6a.
src/generateUserMapping.ts
Outdated
channel, | ||
errorReaction |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated in 942c96a.
Description
This PR introduces robust caching and mapping of Slack user details by GitHub login, significantly reducing reliance on Slack and GitHub API calls and mitigating rate limiting issues. It incorporates extensive requested changes and feedback from review:
Mapping Support & Caching
SLACK_DEPLOY_GITHUB_USERS
, formerlySLACK_GITHUB_MAPPING_RAW
) or file.Action & Workflow Refactor
notify
in dist output..github/actions/generate-mapping/action.yml
for generating a JSON mapping of Slack users by GitHub login.Code Quality & Feedback
MessageAuthor
type for mapping output.getEnv
for environment variable access.Documentation
Testing
Reviewer Notes