-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapp.js
More file actions
144 lines (121 loc) · 5.37 KB
/
app.js
File metadata and controls
144 lines (121 loc) · 5.37 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
// index.js
// Required dependencies:
// npm install jsonwebtoken axios
// You'll also need to have your private key file (.pem) from your GitHub App settings.
const jwt = require('jsonwebtoken');
const axios = require('axios');
const fs = require('fs');
const path = require('path');
// --- Configuration ---
// Replace these values with your GitHub App's specific details.
// The unique ID of your GitHub App. Found in your app's settings page.
const APP_ID = '1845091';
// The installation ID for the repository you want to access.
// You get this when a user installs your app on their repository.
// For testing, you can find it in the URL after installing the app on a repo
// (e.g., https://github.com/settings/installations/INSTALLATION_ID)
const INSTALLATION_ID = '82827805';
// The path to your private key (.pem file) downloaded from your GitHub App settings.
const PRIVATE_KEY_PATH = path.join(__dirname, './private.pem');
// Repository details
const REPO_OWNER = 'harshit-bstack'; // e.g., 'octocat'
const REPO_NAME = 'flask-otel'; // e.g., 'Hello-World'
const BRANCH_NAME = 'test'; // The branch to compare against 'main'
/**
* Generates a JSON Web Token (JWT) to authenticate as the GitHub App.
* The JWT is valid for 10 minutes, which is the maximum allowed by GitHub.
* @returns {string} The generated JWT.
*/
function generateJwt() {
// Read the private key from the file system.
const privateKey = fs.readFileSync(PRIVATE_KEY_PATH, 'utf8');
// Get the current time in seconds.
const now = Math.floor(Date.now() / 1000);
// Create the payload for the JWT.
const payload = {
iat: now - 60, // Issued at time (60 seconds in the past to account for clock drift)
exp: now + (10 * 60), // Expiration time (10 minutes from now)
iss: APP_ID // Issuer: your GitHub App's ID
};
// Sign the JWT with your private key using the RS256 algorithm.
console.log('Generating JWT...');
return jwt.sign(payload, privateKey, { algorithm: 'RS256' });
}
/**
* Gets an installation access token for a specific repository.
* This token is used to make API requests on behalf of the installation.
* @param {string} appJwt - The JWT for the GitHub App.
* @returns {Promise<string>} A promise that resolves with the installation access token.
*/
async function getInstallationAccessToken(appJwt) {
console.log('Requesting installation access token...');
try {
const response = await axios.post(
`https://api.github.com/app/installations/${INSTALLATION_ID}/access_tokens`,
{}, // No request body is needed
{
headers: {
'Accept': 'application/vnd.github.v3+json',
'Authorization': `Bearer ${appJwt}`, // Authenticate with the JWT
'X-GitHub-Api-Version': '2022-11-28'
}
}
);
const accessToken = response.data.token;
console.log('Successfully received installation access token.');
return accessToken;
} catch (error) {
console.error('Error getting installation access token:', error.response ? error.response.data : error.message);
throw error;
}
}
/**
* Fetches the diff between the 'main' branch and a specified branch.
* @param {string} accessToken - The installation access token.
* @param {string} owner - The repository owner's username or organization name.
* @param {string} repo - The repository name.
* @param {string} branch - The name of the branch to compare.
* @returns {Promise<string>} A promise that resolves with the diff content.
*/
async function getBranchDiff(accessToken, owner, repo, branch) {
const base = 'main'; // The base branch for comparison
const head = branch; // The head branch (the one with new changes)
const compareUrl = `https://api.github.com/repos/${owner}/${repo}/compare/${base}...${head}`;
console.log(`Fetching diff from: ${compareUrl}`);
try {
const response = await axios.get(compareUrl, {
headers: {
// IMPORTANT: The 'Accept' header is crucial to get the diff format.
'Accept': 'application/vnd.github.v3.diff',
'Authorization': `token ${accessToken}`, // Authenticate with the installation token
'X-GitHub-Api-Version': '2022-11-28'
}
});
console.log('Successfully fetched diff!');
return response.data;
} catch (error) {
console.error('Error fetching diff:', error.response ? error.response.data : error.message);
throw error;
}
}
/**
* Main function to run the entire process.
*/
async function main() {
try {
// Step 1: Generate the JWT to authenticate as the app.
const appJwt = generateJwt();
// Step 2: Use the JWT to get an installation-specific access token.
const accessToken = await getInstallationAccessToken(appJwt);
// Step 3: Use the installation access token to fetch the diff from the repo.
const diff = await getBranchDiff(accessToken, REPO_OWNER, REPO_NAME, BRANCH_NAME);
// Step 4: Print the resulting diff to the console.
console.log('\n--- GIT DIFF ---');
console.log(diff);
console.log('--- END OF DIFF ---\n');
} catch (error) {
console.error('The process failed:', error.message);
}
}
// Execute the main function.
main();