Getting Started
Events
github.pull_request
This event occurs when there is activity on a pull request.
@on("github.pull_request")
def automation(input):
pass
The following is an example payload which is passed in as an argument to your automation’s entrypoint:
{
"$raw": {},
"action": "opened",
"author": "developer123",
"changes": [
{
"additions": 25,
"changes": 35,
"deletions": 10,
"filename": "src/services/auth.ts",
"patch": "@@ -15,10 +15,25 @@ export class AuthService {\n private async validateToken(token: string) {\n- // Basic auth validation\n- const [username, password] = Buffer.from(token, 'base64')\n- .toString()\n- .split(':');\n-\n- return this.validateCredentials(username, password);\n+ try {\n+ const decoded = jwt.verify(token, this.config.jwt_secret) as JwtPayload;\n+ \n+ if (!decoded.sub || !decoded.exp) {\n+ throw new Error('Invalid token structure');\n+ }\n+ \n+ if (decoded.exp < Date.now() / 1000) {\n+ throw new Error('Token has expired');\n+ }\n+ \n+ const user = await this.userService.findById(decoded.sub);\n+ if (!user) {\n+ throw new Error('User not found');\n+ }\n+ \n+ if (!user.active) {\n+ throw new Error('User account is disabled');\n+ }\n+ \n+ return user;\n+ } catch (error) {\n+ throw new AuthenticationError('Invalid or expired token');\n+ }\n }",
"status": "modified"
},
{
"additions": 50,
"changes": 50,
"deletions": 0,
"filename": "tests/auth.test.ts",
"patch": "@@ -0,0 +1,50 @@\n+import { describe, it, expect, jest } from 'jest';\n+import { AuthService } from '../src/services/auth';\n+import { UserService } from '../src/services/user';\n+import { AuthenticationError } from '../src/errors';\n+\n+describe('AuthService', () => {\n+ let authService: AuthService;\n+ let userService: jest.Mocked<UserService>;\n+\n+ beforeEach(() => {\n+ userService = {\n+ findById: jest.fn(),\n+ } as any;\n+\n+ authService = new AuthService({\n+ jwt_secret: 'test-secret',\n+ token_expiry: '1h'\n+ }, userService);\n+ });\n+\n+ describe('validateToken', () => {\n+ it('should successfully validate a valid token', async () => {\n+ const mockUser = {\n+ id: '123',\n+ active: true,\n+ name: 'Test User'\n+ };\n+\n+ userService.findById.mockResolvedValue(mockUser);\n+\n+ const token = authService.generateToken(mockUser);\n+ const result = await authService.validateToken(token);\n+\n+ expect(result).toEqual(mockUser);\n+ expect(userService.findById).toHaveBeenCalledWith('123');\n+ });\n+\n+ it('should throw on expired token', async () => {\n+ const mockUser = {\n+ id: '123',\n+ active: true,\n+ name: 'Test User'\n+ };\n+\n+ // Generate token that's already expired\n+ const token = authService.generateToken(mockUser, '-1h');\n+\n+ await expect(authService.validateToken(token))\n+ .rejects\n+ .toThrow(AuthenticationError);\n+ });\n+ });\n+});",
"status": "added"
},
{
"additions": 15,
"changes": 20,
"deletions": 5,
"filename": "README.md",
"patch": "@@ -10,8 +10,18 @@ ## Authentication\n-### Basic Authentication\n-To authenticate requests, provide your credentials in the Authorization header:\n-\n-```\n-Authorization: Basic base64(username:password)\n-```\n+### OAuth2 Authentication\n+\n+This API uses OAuth2 for authentication. To authenticate requests, include a Bearer token in the Authorization header:\n+\n+```\n+Authorization: Bearer <your_token>\n+```\n+\n+#### Obtaining a Token\n+\n+1. Redirect users to `/oauth/authorize`\n+2. Users approve the application\n+3. Exchange the authorization code for a token at `/oauth/token`\n+\n+Tokens expire after 1 hour. Use the refresh token to obtain a new access token.\n+\n+For more details, see our [OAuth2 Implementation Guide](./docs/oauth2.md).",
"status": "modified"
}
],
"commit_message": "feat: implement OAuth2 authentication",
"commit_sha": "abc123def456789ghijklmnop",
"files_changed": [
"src/services/auth.ts",
"tests/auth.test.ts",
"README.md"
],
"owner": "octocat",
"pull_request": {
"author": "developer123",
"body": "This PR adds OAuth2 authentication support and removes the basic auth implementation.\n\nChanges:\n- Replaces basic auth with JWT-based OAuth2\n- Adds comprehensive tests\n- Updates documentation\n- Adds token validation and expiry handling\n\nPlease review the token expiry duration and error messages.",
"comments": [
{
"author": "reviewer456",
"body": "Could you add some documentation about token refresh flows? Particularly around handling expired refresh tokens.",
"created_at": "2024-03-21T11:30:00Z",
"diff_hunk": "@@ -15,7 +15,12 @@ export class AuthService {\n private async validateToken(token: string) {\n- // Basic auth validation\n- const [username, password] = Buffer.from(token, 'base64')\n- .toString()\n- .split(':');\n-\n- return this.validateCredentials(username, password);\n+ try {\n+ const decoded = jwt.verify(token, this.config.jwt_secret) as JwtPayload;",
"filename": "src/services/auth.ts",
"id": 444555666,
"line": 17,
"node_id": "PRRC_kwDOA3333333333",
"original_line": 2,
"original_position": 2,
"original_start_line": 15,
"start_line": 17,
"start_side": "RIGHT",
"subject_type": "line",
"url": "https://api.github.com/repos/octocat/Hello-World/pulls/comments/444555666"
},
{
"author": "security-reviewer",
"body": "We should add a check for token blacklisting here in case we need to revoke access.",
"created_at": "2024-03-21T12:15:00Z",
"diff_hunk": "@@ -20,6 +20,11 @@ export class AuthService {\n if (!decoded.sub || !decoded.exp) {\n throw new Error('Invalid token structure');\n }\n+ \n+ if (decoded.exp < Date.now() / 1000) {\n+ throw new Error('Token has expired');\n+ }\n+ \n+ const user = await this.userService.findById(decoded.sub);",
"filename": "src/services/auth.ts",
"id": 444555667,
"line": 25,
"node_id": "PRRC_kwDOA3333333334",
"original_line": null,
"original_position": 5,
"original_start_line": null,
"start_line": 25,
"start_side": "RIGHT",
"subject_type": "line",
"url": "https://api.github.com/repos/octocat/Hello-World/pulls/comments/444555667"
},
{
"author": "developer123",
"body": "Good catch! I'll add the blacklist check in the next commit.",
"created_at": "2024-03-21T12:30:00Z",
"diff_hunk": "@@ -25,6 +25,10 @@ export class AuthService {\n if (decoded.exp < Date.now() / 1000) {\n throw new Error('Token has expired');\n }\n+ \n+ const user = await this.userService.findById(decoded.sub);\n+ if (!user) {\n+ throw new Error('User not found');\n+ }",
"filename": "src/services/auth.ts",
"id": 444555668,
"line": 28,
"node_id": "PRRC_kwDOA3333333335",
"original_line": null,
"original_position": 8,
"original_start_line": null,
"start_line": 28,
"start_side": "RIGHT",
"subject_type": "line",
"url": "https://api.github.com/repos/octocat/Hello-World/pulls/comments/444555668"
}
],
"created_at": "2024-03-21T10:00:00Z",
"id": 987654321,
"labels": [
{
"color": "84b6eb",
"default": true,
"description": "New feature or request",
"id": 111222,
"name": "enhancement",
"node_id": "LA_kwDOA1111111111"
},
{
"color": "d93f0b",
"default": false,
"description": "Security related changes",
"id": 333444,
"name": "security",
"node_id": "LA_kwDOA2222222222"
}
],
"node_id": "PR_kwDOA1234567890",
"number": 123,
"state": "open",
"title": "Implement OAuth2 Authentication",
"url": "https://api.github.com/repos/octocat/Hello-World/pulls/123"
},
"ref": "feature/oauth-auth",
"repo": "Hello-World"
}
Fields
The raw Github pull_request
event payload.
The author of the pull request.
The changes that were made to the files in the pull request.
The number of additions in the change.
The number of changes in the change.
The number of deletions in the change.
The filename of the file that the change is on.
The patch of the change.
The status of the change.
The commit message of the pull request.
The SHA of the commit that was used to create the pull request.
The files that were changed in the pull request.
The owner of the repository.
The pull request object.
The author of the pull request.
The body of the pull request.
The comments on the pull request.
The author of the comment.
The body of the comment.
The date and time the comment was created.
The diff hunk of the comment.
The filename of the file that the comment is on.
The ID of the comment.
The line number of the comment.
The node ID of the comment.
The original line number of the comment.
The original position of the comment.
The original start line of the comment.
The start line of the comment.
The start side of the comment.
The subject type of the comment.
The URL of the comment.
The date and time the pull request was created.
The ID of the pull request.
The node ID of the pull request.
The number of the pull request.
The state of the pull request.
The title of the pull request.
The URL of the pull request.
The ref of the pull request.
The repository of the pull request.