Skip to content

Commit 49b94a9

Browse files
committed
Refactor GitHub integration connect endpoint and update dependencies
Refactored the /integration/github/connect endpoint to return a JSON object with the installation redirect URL instead of performing a direct redirect, and added colorized logging with environment-based suppression for tests. Updated Jest and argon2 dependencies, added Jest moduleNameMapper for node:crypto and node:util, and introduced mocks for these modules. Added comprehensive tests for the GitHub integration connect route.
1 parent d60f2be commit 49b94a9

File tree

8 files changed

+506
-177
lines changed

8 files changed

+506
-177
lines changed

.env.sample

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ GITHUB_WEBHOOK_SECRET=623f6ed30b1f762803149893263a95cc2687fe3ce5a9f30648dcbf2571
101101
GITHUB_APP_ID=1234567
102102

103103
# GitHub App slug/name. Used to generate installation URLs
104-
GITHUB_APP_SLUG=hawk-tracker-app;
104+
GITHUB_APP_SLUG=hawk-tracker-app
105105

106106
# Private key generated in GitHub app settings
107107
GITHUB_PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----

jest.config.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,16 @@ module.exports = {
2929
}],
3030
},
3131

32+
/**
33+
* Map node: prefixed imports to mock files
34+
* Jest 27 supports node: prefix for ESM imports, but CommonJS require('node:crypto')
35+
* in modules like argon2.cjs still needs explicit mapping to mocks
36+
*/
37+
moduleNameMapper: {
38+
'^node:crypto$': '<rootDir>/test/__mocks__/node_crypto.js',
39+
'^node:util$': '<rootDir>/test/__mocks__/node_util.js',
40+
},
41+
3242
/**
3343
* Ignore folders
3444
*/

package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,16 @@
2222
"devDependencies": {
2323
"@shelf/jest-mongodb": "^6.0.2",
2424
"@swc/core": "^1.3.0",
25-
"@types/jest": "^26.0.8",
25+
"@types/jest": "^27.5.0",
2626
"@types/xml2js": "^0.4.14",
2727
"eslint": "^6.7.2",
2828
"eslint-config-codex": "1.2.4",
2929
"eslint-plugin-import": "^2.19.1",
30-
"jest": "^26.2.2",
30+
"jest": "^27.6.0",
3131
"mongodb-memory-server": "^6.6.1",
3232
"nodemon": "^2.0.2",
3333
"redis-mock": "^0.56.3",
34-
"ts-jest": "^26.1.4",
34+
"ts-jest": "^27.1.0",
3535
"ts-node": "^10.9.1",
3636
"typescript": "^4.7.4",
3737
"xml2js": "^0.6.2"
@@ -64,7 +64,7 @@
6464
"amqp-connection-manager": "^3.1.0",
6565
"amqplib": "^0.5.5",
6666
"apollo-server-express": "^3.10.0",
67-
"argon2": "^0.28.7",
67+
"argon2": "^0.44.0",
6868
"aws-sdk": "^2.1174.0",
6969
"axios": "^0.27.2",
7070
"body-parser": "^1.19.0",

src/integrations/github/routes.ts

Lines changed: 44 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { GitHubService } from './service';
55
import { ContextFactories } from '../../types/graphql';
66
import { RedisInstallStateStore } from './store/install-state.redis.store';
77
import WorkspaceModel from '../../models/workspace';
8+
import { sgr, Effect } from '../../utils/ansi';
89

910
/**
1011
* Create GitHub router
@@ -17,6 +18,40 @@ export function createGitHubRouter(factories: ContextFactories): express.Router
1718
const githubService = new GitHubService();
1819
const stateStore = new RedisInstallStateStore();
1920

21+
/**
22+
* Log message with GitHub Integration prefix
23+
*
24+
* @param level - log level ('log', 'warn', 'error', 'info')
25+
* @param args - arguments to log
26+
*/
27+
function log(level: 'log' | 'warn' | 'error' | 'info', ...args: unknown[]): void {
28+
/**
29+
* Disable logging in test environment
30+
*/
31+
if (process.env.NODE_ENV === 'test') {
32+
return;
33+
}
34+
35+
const colors = {
36+
log: Effect.ForegroundGreen,
37+
warn: Effect.ForegroundYellow,
38+
error: Effect.ForegroundRed,
39+
info: Effect.ForegroundBlue,
40+
};
41+
42+
let logger: typeof console.log;
43+
44+
if (level === 'error') {
45+
logger = console.error;
46+
} else if (level === 'warn') {
47+
logger = console.warn;
48+
} else {
49+
logger = console.log;
50+
}
51+
52+
logger(sgr('[GitHub Integration]', colors[level]), ...args);
53+
}
54+
2055
/**
2156
* GET /integration/github/connect?projectId=<projectId>
2257
* Initiate GitHub integration connection
@@ -122,25 +157,25 @@ export function createGitHubRouter(factories: ContextFactories): express.Router
122157

123158
await stateStore.saveState(state, stateData);
124159

125-
console.log(
126-
`[GitHub Integration] Created state for project ${projectId}: ${state.slice(0, 8)}...`
127-
);
160+
log('info', `Created state for project ${sgr(projectId, Effect.ForegroundCyan)}: ${sgr(state.slice(0, 8), Effect.ForegroundGray)}...`);
128161

129162
/**
130163
* Generate GitHub installation URL with state
131164
*/
132165
const installationUrl = githubService.getInstallationUrl(state);
133166

134-
console.log(
135-
`[GitHub Integration] Redirecting to GitHub installation URL for project ${projectId}`
136-
);
167+
log('info', `Generated GitHub installation URL for project ${sgr(projectId, Effect.ForegroundCyan)}`);
137168

138169
/**
139-
* Redirect user to GitHub installation page
170+
* Return installation URL in JSON response
171+
* Frontend will handle the redirect using window.location.href
172+
* This allows Authorization header to be sent correctly
140173
*/
141-
res.redirect(installationUrl);
174+
res.json({
175+
redirectUrl: installationUrl,
176+
});
142177
} catch (error) {
143-
console.error('[GitHub Integration] Error in /connect endpoint:', error);
178+
log('error', 'Error in /connect endpoint:', error);
144179
next(error);
145180
}
146181
});

test/__mocks__/node_crypto.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
/**
2+
* Mock for node:crypto to support Jest with CommonJS require() calls
3+
* This re-exports crypto module as node:crypto
4+
*/
5+
module.exports = require('crypto');

test/__mocks__/node_util.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
/**
2+
* Mock for node:util to support Jest with CommonJS require() calls
3+
* This re-exports util module as node:util
4+
*/
5+
module.exports = require('util');

0 commit comments

Comments
 (0)