Skip to content
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

Extract GitHubApp logic #563

Closed
wants to merge 24 commits into from
Closed

Extract GitHubApp logic #563

wants to merge 24 commits into from

Conversation

bkeepers
Copy link
Contributor

@bkeepers bkeepers commented Jun 11, 2018

Now that we're migrated to TypeScript, this is another attempt (#410) to extract some of the GitHub App logic so it's more encapsulated and reusable. The goal is to get to where Application only has an event emitter and router, but no GitHub-specific logic.

There are a few things driving this refactoring:

  1. People doing custom stuff can reach directly for an instance of GitHubApp instead of having to jump through hoops to get app.auth() and friends to work.
  2. As we look to make it easier to run Probot in serverless environments, we override parts of GitHubApp (e.g. change how webhooks are delivered)
  3. We could make it easier for other platforms to implement similar adapters.

TODO:

  • Create a class to encapsulate all GitHub App logic: GitHubApp
  • define createContext method and move to class
  • Move jwt creation into class
  • Move webhook handling into class WIP: Move Webhooks to GitHubApp #565
  • Properly deprecate app.auth and figure out replacement

@bkeepers bkeepers requested a review from a team June 11, 2018 04:30
baseUrl: process.env.GHE_HOST && `https://${process.env.GHE_HOST}/api/v3`,
debug: process.env.LOG_LEVEL === 'trace',
logger: log.child({name: 'github', installation: String(id)})
})
Copy link
Contributor Author

Choose a reason for hiding this comment

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

FIXME: extract this into a method so client creation can be reused.

github.authenticate({type: 'app', token: this.jwt()})

return github.apps.createInstallationToken({installation_id: String(id)})
}, {ttl: 60 * 59}) // Cache for 1 minute less than GitHub expiry
Copy link
Contributor Author

Choose a reason for hiding this comment

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

FIXME: extract into a method so installation token logic can be reused.

src/index.ts Outdated
this.server.use(this.webhook.middleware)


this.adapter = new GitHubApp({ id: options.id, cert: options.cert })

// Log all received webhooks
this.webhook.on('*', (event: any) => {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

FIXME: move to GitHubApp class

…dapter

* origin/master:
  chore: Turn on esModuleInterop for TypeScript (#564)
* instead of as a specific installation, which means it can only be used for
* [app APIs](https://developer.github.com/v3/apps/).
*
* @returns {Promise<github>} - An authenticated GitHub API client
Copy link
Contributor

Choose a reason for hiding this comment

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

minor nit, just to make sure it's consistent with the name of the TS type

@returns {Promise<GitHubAPI>} 

@tcbyrd
Copy link
Contributor

tcbyrd commented Jun 16, 2018

@bkeepers I know there's more left to do here, but wanted to add that I tested invite-koa locally with this branch and it's 👍 so far.

Properly deprecate app.auth and figure out replacement

app.adapter.auth() is working for me when I do

const app = new Probot({
  id: process.env.APP_ID,
  cert: process.env.PRIVATE_KEY
})

const github = await app.adapter.auth()

In fact when I do that, app.auth() doesn't work at all. I might be missing some context here, though.


Do we want to encourage import {GitHubApp} from 'probot' so users can create the adapter without the logging and express server? Mainly I'm trying to think of ways to avoid things like in github-robot, where they disable the built-in logger so it can use the features of the Firebase platform:

// < /src/index.ts >
// disable probot logging
bot.logger.streams.splice(0, 1);
// Use node console as the output stream
bot.logger.addStream(consoleStream(store));

// < /src/util.js >
/**
 * Stream Probot logs to console for Firebase
 */
export const consoleStream = (store: FirebaseFirestore.Firestore) => ({
  type: "raw",
  level: "debug",
  stream: new Stream(store)
});

I think this is where you're going with making everything modular, but it could be nice if everything in Probot could be imported as needed, then probot run gives you the server to run it all on top of when you don't have an http router otherwise (in an existing App, in Serverless environments, etc.)

@gr2m
Copy link
Contributor

gr2m commented Jun 19, 2018

Could you update documentation for the feature?

I think it might be useful to align work with @octokit/app? Sounds like ideally we would use that module eventually? See octokit/app.js#1

@tcbyrd
Copy link
Contributor

tcbyrd commented Jun 22, 2018

@gr2m Yeh definitely looks like we could just move to that module. The API is the exact same. Is there a line we need to draw somewhere on the what's in Probot vs what's in Octokit? Once you have apps, pagination, & graphql in Octokit, it seems like Probot becomes mainly an opinionated way of running an Express server with Octokit.

@gr2m
Copy link
Contributor

gr2m commented Jun 22, 2018

It seems like Probot becomes mainly an opinionated way of running an Express server with Octokit

Yeah that sounds about right. I think I’d also leave an http server out of Octokit so folks can use servers other than express.

Thanks for reviewing!

…dapter

* origin/master:
  chore(package): update @types/jest to version 23.1.3 (#593)
  Revert "Configuration: DISABLE_STATS=true" (#591)
  chore(package): update @types/jest to version 23.0.0 (#555)
  docs(configuration): DISABLE_STATS=true (#578)
  fix: Fix path to GraphQL API when using GitHub Enterprise (#580)
  Adds error case (#589)
  doc: Clarify that `WEBHOOK_SECRET` needs to match GitHub settings
(#588)
  chore: Replace jsdoc with typedoc (#583)
  Adds missing awaits (#584)
  doc: Update robot => app in README (#586)
  docs: clarify GitHub apps as GA in 2.13 and above (#579)
  docs: Tweak payload info in testing.md (#575)
  add backticks (#574)
  docs: Typo (#572)
  fix: Throw if GHE_HOST includes a protocol (#570)
  feat: app.load() (#554)
  fix: Optimize IGNORED_ACCOUNTS check to reduce the number of API
requests that the stats endpoint makes for spammy accounts (#566)
  add env config docs (#544)
@hiimbex
Copy link
Contributor

hiimbex commented Jul 10, 2018

Is there still work to be done on this or was it handled in another ts pr?

I misunderstood this PR! 🙈

…dapter

* origin/master:
  chore(package): update ts-jest to version 23.0.0 (#602)
  chore(test): Convert application tests to TypeScript (#614)
  Clarifies the Probot requires a webhook secret (#621)
  chore(test): Run tslint against tests (#622)
  Tweak formatting of config docs (#603)
  Fix: Improve typing of Context (#617)
  fix: Make cacheErrors option optional (#616)
  7.0.1
  Update ocotokit/rest.js to v15.9.4 (#610)
  fix: Remove extra event setting (#611)
  Update eslint to the latest version 🚀 (#581)
  docs: Fix new contribution grammar (#609)
  update the example app id image (#606)
  Update links for our API (#604)
  Remove next tag (#595)
  7.0.0
  Various cleanup and fixes from TS checklist (#585)
  Add some documentation about TS to README and CONTRIBUTING (#590)
  chore: Use tslint-config-standard (#594)
@bkeepers bkeepers requested a review from a team July 15, 2018 13:19
@bkeepers
Copy link
Contributor Author

@probot/maintainers While there's a lot more I'd like to do here, I'd like to try to get this merged and finish the rest of the refactoring in #565.

Here are the notable changes in this PR:

  • app.auth() and app.app() have been deprecated and will print these warnings when called:

        Method `app` has been deprecated, use `github.jwt` instead.
            at /Users/bkeepers/projects/probot/probot/test/application.test.ts:262:18
    
       Method `auth` has been deprecated, use `github.auth` instead.
            at /Users/bkeepers/projects/probot/probot/test/application.test.ts:268:24
    
  • app.github is an instance of GitHubApp, which has:

    • jwt() - returns a new JWT for the GitHub app
    • auth(id?: number) - returns a new authenticated octokit client for the given installation id
    • createContext(event: WebhookEvent) - creates a new Context for the given webhook event

So an example of this being used:

module.exports = async app => {
  // returns a new octokit instance
  const github = await app.github.auth()
}

Copy link
Contributor

@hiimbex hiimbex left a comment

Choose a reason for hiding this comment

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

LGTM! Few minor comments

}

/**
* Authenticate and get a GitHub client that can be used to make API calls.
Copy link
Contributor

Choose a reason for hiding this comment

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

I know this is just copy pasted form the old but maybe here would be a good place to clarify that GitHub client = authenticated as an installation: https://developer.github.com/apps/building-github-apps/authenticating-with-github-apps/#authenticating-as-an-installation

@@ -15,7 +15,8 @@
"skipLibCheck": true,
"noImplicitAny": true,
"esModuleInterop": true,
"declaration": true // enable this once all files are .ts and we can remove allowJs
"declaration": true, // enable this once all files are .ts and we can remove allowJs
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we nix this comment? declaration is already true and allowJs is already false. Also json doens't support comments in the first place.

app = new Application({} as any)
app.auth = jest.fn().mockReturnValue({})
github = new GitHubApp(1, 'cert')
github.auth = jest.fn().mockReturnValue({})
Copy link
Contributor

Choose a reason for hiding this comment

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

These tests would be clearer to me if we used app.github.auth to replace app.auth instead of github.auth.

Is there reasoning for not having it that way?

@JasonEtco JasonEtco mentioned this pull request Aug 2, 2018
@stale
Copy link

stale bot commented Sep 15, 2018

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the wontfix label Sep 15, 2018
@stale stale bot closed this Sep 22, 2018
…dapter

* origin/master: (51 commits)
  remove manual base64 encoding/decoding of private key (#717)
  chore(test): convert app/default test to TypeScript (#703)
  chore(test): convert Sentry test to TypeScript (#702)
  Detect color support (#708)
  Fix two typos (#709)
  7.2.0
  httpSSSSSSS (#701)
  chore(tests): convert serializers test to TypeScript (#695)
  Update development docs to explain GitHub App Manifests (#700)
  Probot Support for GitHub App Manifests (#650)
  Resolve Jest transform option deprecation warning (#694)
  chore(package): update nock to version 10.0.0
  7.1.2
  fix(package): require @octokit/webhooks@^5.0.2 (#691)
  Relax webhooks requirement
  fix(package): update @octokit/webhooks to version 5.0.1
  Update best-practices.md (#682)
  7.1.1
  add npm ignore for package-locks
  update octokit/rest and tests to use /app/installations (#681)
  ...
@bkeepers bkeepers reopened this Oct 7, 2018
@stale stale bot removed the wontfix label Oct 7, 2018
@jamime
Copy link

jamime commented Nov 8, 2018

@bkeepers What's the latest on this, happy to contribute.

@gr2m gr2m added the pinned label Jan 10, 2019
@gr2m gr2m mentioned this pull request Jan 19, 2019
15 tasks
@gr2m gr2m added this to the v10.0.0 milestone Jun 25, 2020
@gr2m
Copy link
Contributor

gr2m commented Aug 26, 2020

done in v10

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.

5 participants