Skip to content

Commit

Permalink
Merge pull request #47 from interactivethings/feat/team-projects
Browse files Browse the repository at this point in the history
  • Loading branch information
noahonyejese authored Jan 8, 2025
2 parents 3285edb + 6ab67b2 commit 71e3f6b
Show file tree
Hide file tree
Showing 7 changed files with 228 additions and 43 deletions.
123 changes: 83 additions & 40 deletions app/api/github/events/projects/route.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
import { verifyGitHubRequest } from '@/server/security';
import { createError } from '@/utils/error-handling';
import {
CheckRunEvent,
CreateEvent,
DeleteEvent,
DeploymentEvent,
DeploymentStatusEvent,
PingEvent,
PullRequestEvent,
PullRequestReviewEvent,
PushEvent,
RepositoryEvent,
WebhookEventMap,
WebhookEventName,
} from '@octokit/webhooks-types';
import { NextRequest, NextResponse } from 'next/server';

export const POST = async (req: NextRequest) => {
Expand All @@ -13,85 +27,114 @@ export const POST = async (req: NextRequest) => {
});
}

const body = JSON.parse(rawBody);
const event = req.headers.get('x-github-event');
const body = JSON.parse(rawBody) as WebhookEventMap[WebhookEventName];
const event = req.headers.get('x-github-event') as WebhookEventName;

switch (event) {
case 'ping':
case 'ping': {
const pingEvent = body as PingEvent;
return NextResponse.json({
status: 'success',
message: 'Pong!',
zen: pingEvent.zen,
});
}

case 'create':
case 'create': {
const createEvent = body as CreateEvent;
console.log('Create event:', {
ref_type: body.ref_type,
ref: body.ref,
repository: body.repository.full_name,
ref_type: createEvent.ref_type,
ref: createEvent.ref,
repository: createEvent.repository.full_name,
});
break;
}

case 'delete':
case 'delete': {
const deleteEvent = body as DeleteEvent;
console.log('Delete event:', {
ref_type: body.ref_type,
ref: body.ref,
repository: body.repository.full_name,
ref_type: deleteEvent.ref_type,
ref: deleteEvent.ref,
repository: deleteEvent.repository.full_name,
});
break;
}

case 'check_run':
case 'check_run': {
const checkRunEvent = body as CheckRunEvent;
console.log('Check run event:', {
action: body.action, // created, completed, rerequested
status: body.check_run.status,
conclusion: body.check_run.conclusion,
name: body.check_run.name,
action: checkRunEvent.action,
status: checkRunEvent.check_run.status,
conclusion: checkRunEvent.check_run.conclusion,
name: checkRunEvent.check_run.name,
});
break;
}

case 'deployment_status':
// Deployment status updates
case 'deployment_status': {
const deploymentStatusEvent = body as DeploymentStatusEvent;
console.log('Deployment status event:', {
action: body.action,
state: body.deployment_status.state,
environment: body.deployment.environment,
action: deploymentStatusEvent.action,
state: deploymentStatusEvent.deployment_status.state,
environment: deploymentStatusEvent.deployment.environment,
});
break;
}

case 'pull_request_review':
// PR review events
case 'pull_request_review': {
const pullRequestReviewEvent = body as PullRequestReviewEvent;
console.log('PR review event:', {
action: body.action,
state: body.review.state,
pr_number: body.pull_request.number,
action: pullRequestReviewEvent.action,
state: pullRequestReviewEvent.review.state,
pr_number: pullRequestReviewEvent.pull_request.number,
});
break;
}

case 'pull_request':
case 'pull_request': {
const pullRequestEvent = body as PullRequestEvent;
console.log('Pull request event:', {
action: body.action,
number: body.pull_request.number,
state: body.pull_request.state,
merged: body.pull_request.merged,
action: pullRequestEvent.action,
number: pullRequestEvent.pull_request.number,
state: pullRequestEvent.pull_request.state,
merged: pullRequestEvent.pull_request.merged,
});
break;
}

case 'push':
case 'push': {
const pushEvent = body as PushEvent;
console.log('Push event:', {
ref: body.ref,
commits: body.commits.length,
repository: body.repository.full_name,
ref: pushEvent.ref,
commits: pushEvent.commits.length,
repository: pushEvent.repository.full_name,
});
break;
}

case 'repository':
case 'repository': {
const repositoryEvent = body as RepositoryEvent;
console.log('Repository event:', {
action: body.action,
repository: body.repository.full_name,
action: repositoryEvent.action,
repository: repositoryEvent.repository.full_name,
});
break;
}

case 'deployment': {
const deploymentEvent = body as DeploymentEvent;
console.log('Deployment event:', {
action: deploymentEvent.action,
environment: deploymentEvent.deployment.environment,
repository: deploymentEvent.repository.full_name,
});
break;
}

default:
console.log(`Unhandled event type: ${event}`);
default: {
const eventName = event as WebhookEventName;
console.log(`Unhandled event type: ${eventName}`);
}
}

return NextResponse.json({
Expand Down
8 changes: 8 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"zod": "^3.23.8"
},
"devDependencies": {
"@octokit/webhooks-types": "^7.6.1",
"@types/animejs": "^3.1.12",
"@types/d3": "^7.4.3",
"@types/node": "^20",
Expand Down
30 changes: 30 additions & 0 deletions server/github/syncs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { TeamProjectFirebase } from '@/types/firebase';
import { Repository } from '@octokit/webhooks-types';
import * as admin from 'firebase-admin';

export const projectSync = async (project: Repository) => {
const db = admin.database();
const userRef = db.ref(
`data/team-projects/sensors/github/values/${project.id}`
);

const snapshot = await userRef.once('value');
const projectData = snapshot.val() as TeamProjectFirebase;

if (projectData) {
await userRef.update({
...projectData,
frequency: projectData.frequency + 1,
lastUpdated: Date.now(),
});
} else {
await userRef.set({
title: project.name,
logo: `https://github.com/${project.owner.id}/${project.id}/pinned-icon.svg`,
defaulBranch: project.default_branch,
masterBranch: project.master_branch,
frequency: 1,
lastUpdated: Date.now(),
});
}
};
3 changes: 2 additions & 1 deletion types/data.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { NoiseLevelsData } from './firebase';
import { NoiseLevelsData, TeamProject } from './firebase';
import { TeamMember } from './team-activity';

export interface FormtattedDataBaseType {
'team-communication': FormattedDataBase<TeamMember[]>;
'noise-levels': FormattedDataBase<NoiseLevelsData>;
'team-projects': FormattedDataBase<TeamProject[]>;
}

export interface FormattedDataBase<T> {
Expand Down
104 changes: 103 additions & 1 deletion types/firebase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,13 @@ export interface Metric<T extends keyof Views> {
}

export interface Settings {
view_time: number;
[key: string]: number;
}

export interface Views {
'team-communication': View[];
'noise-levels': View[];
'team-projects': View[];
}

export interface View {
Expand All @@ -39,6 +40,7 @@ export interface User {
export interface DisplayDataType {
'team-communication': DisplayDataBase<TeamCommunicationData>;
'noise-levels': DisplayDataBase<NoiseLevelsData>;
'team-projects': DisplayDataBase<TeamProjectFirebasesData>;
}

export interface DisplayDataBase<T> {
Expand All @@ -56,3 +58,103 @@ export interface DisplayDataBase<T> {
export interface NoiseLevelsData {
db: number;
}

export interface TeamProjectFirebasesData {
[key: string]: TeamProjectFirebase;
}

export interface TeamProject {
title: string;
logo: string;
pullRequests: PullRequest[];
branches: Branch[];
users: User[];
}

export interface TeamProjectFirebase {
title: string;
logo: string;
frequency: number;
lastUpdated: number;
masterBranch: string;
defaultBranch: string;
pullRequests: {
[key: string]: PullRequestFirebase;
};
branches: {
[key: string]: BranchFirebase;
};
users: {
[key: string]: User;
};
}

export interface PullRequest {
title: string;
author: string;
createdAt: number;
status: string;
sourceBranch: string;
targetBranch: string;
commits: Commit[];
checks: Check[];
timeline: GithubEvent[];
}
export interface PullRequestFirebase {
title: string;
author: string;
createdAt: number;
status: string;
sourceBranch: string;
targetBranch: string;
commits: {
[key: string]: Commit;
};
checks: {
[key: string]: Check;
};
timeline: {
[key: string]: GithubEvent;
};
}

export interface Check {
name: string;
status: string;
timestamp: number;
type: string;
}

export interface GithubEvent {
type: string;
timestamp: number;
actor: string;
}

export interface Commit {
hash: string;
message: string;
timestamp: number;
}

export interface BranchFirebase {
lastCommit: string;
lastUpdated: number;
}

export interface Branch {
branch: string;
lastCommit: string;
lastUpdated: number;
}

export interface User {
name: string;
email: string;
activePrs?: {
[key: string]: boolean;
};
activeReviews?: {
[key: string]: boolean;
};
}
2 changes: 1 addition & 1 deletion utils/general.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ export const viewTeamPositions = ({

const diagLength = space - margin * 2;

const outerOffset = 50; // Space between end and last point
const outerOffset = 50;

const half = Math.ceil(members.length / 2);
const positiveDiagonalMembers = members.slice(0, half);
Expand Down

0 comments on commit 71e3f6b

Please sign in to comment.