diff --git a/full-sync.js b/full-sync.js index 8ba1c735..930f191a 100644 --- a/full-sync.js +++ b/full-sync.js @@ -1,16 +1,32 @@ const appFn = require('./') const { FULL_SYNC_NOP } = require('./lib/env') const { createProbot } = require('probot') +const pino = require('pino') async function performFullSync (appFn, nop) { - const probot = createProbot() + const logLevel = process.env.LOG_LEVEL || 'info' + const logger = pino({ + level: logLevel, + transport: { + target: 'pino-pretty', + options: { + colorize: true, + ignore: 'pid,hostname', + messageFormat: '{msg}', + customColors: 'info:blue,warn:yellow,error:red', + levelFirst: true + } + } + }) + + const probot = createProbot({ overrides: { log: logger } }) probot.log.info(`Starting full sync with NOP=${nop}`) try { const app = appFn(probot, {}) const settings = await app.syncInstallation(nop) - if (settings.errors && settings.errors.length > 0) { + if (settings && settings.errors && settings.errors.length > 0) { probot.log.error('Errors occurred during full sync.') process.exit(1) } @@ -22,7 +38,13 @@ async function performFullSync (appFn, nop) { } } -performFullSync(appFn, FULL_SYNC_NOP).catch((error) => { - console.error('Fatal error during full sync:', error) - process.exit(1) -}) +// Only run if executed directly (not when imported for testing) +if (require.main === module) { + performFullSync(appFn, FULL_SYNC_NOP).catch((error) => { + console.error('Fatal error during full sync:', error) + process.exit(1) + }) +} + +// Export for testing +module.exports = { performFullSync } diff --git a/test/unit/full-sync.test.js b/test/unit/full-sync.test.js new file mode 100644 index 00000000..df37564f --- /dev/null +++ b/test/unit/full-sync.test.js @@ -0,0 +1,37 @@ +/* eslint-disable no-undef */ +const { performFullSync } = require("../../full-sync"); + +jest.mock("probot", () => ({ createProbot: jest.fn() })); +jest.mock("pino", () => jest.fn(() => ({ info: jest.fn() }))); + +describe("full-sync.js", () => { + let mockProbot, mockApp; + + beforeEach(() => { + mockProbot = { log: { info: jest.fn() } }; + require("probot").createProbot.mockReturnValue(mockProbot); + mockApp = { syncInstallation: jest.fn() }; + jest.clearAllMocks(); + }); + + it("should pass logger to createProbot via overrides (v14 fix)", async () => { + mockApp.syncInstallation.mockResolvedValue({ errors: [] }); + await performFullSync(jest.fn().mockReturnValue(mockApp), true); + + expect(require("probot").createProbot).toHaveBeenCalledWith( + expect.objectContaining({ + overrides: expect.objectContaining({ log: expect.any(Object) }), + }), + ); + }); + + it("should handle null settings without crashing (null safety)", async () => { + mockApp.syncInstallation.mockResolvedValue(null); + await performFullSync(jest.fn().mockReturnValue(mockApp), true); + + // Just verify it completes without throwing + expect(mockProbot.log.info).toHaveBeenCalledWith( + "Full sync completed successfully.", + ); + }); +});