Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions __tests__/integration/app.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,9 @@ function createMockOctokit() {
updateComment: jest.fn().mockResolvedValue({}),
deleteComment: jest.fn().mockResolvedValue({})
},
repos: {
getBranch: jest.fn().mockResolvedValue({ data: { name: 'main' } })
},
request: jest.fn().mockResolvedValue({ status: 200, data: {} })
};
}
Expand All @@ -159,6 +162,7 @@ function createRepoCreatedContext(overrides = {}) {
full_name: 'pulseengine/test-repo',
name: 'test-repo',
has_issues: true,
default_branch: 'main',
owner: { login: 'pulseengine' },
...(overrides.repository || {})
},
Expand Down
4 changes: 2 additions & 2 deletions config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,13 @@ dependabot_generation:
max_directories_per_ecosystem: 5

ai_review:
enabled: false
enabled: true
endpoint: "http://localhost:11434/v1/chat/completions"
model: "qwen2.5-coder:3b"
max_diff_size: 12000
max_tokens: 2000
temperature: 0.3
timeout: 120000
timeout: 300000
allow_remote_endpoint: false

scheduler:
Expand Down
5 changes: 3 additions & 2 deletions src/ai-review.js
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ function buildReviewPrompt(prData, diff, files, maxDiffSize) {
}

async function callLocalAI(endpoint, model, systemPrompt, userPrompt, options = {}) {
const { maxTokens = 2000, temperature = 0.3, timeout = 120000 } = options;
const { maxTokens = 2000, temperature = 0.3, timeout = 300000 } = options;

const controller = new AbortController();
const timer = setTimeout(() => controller.abort(), timeout);
Expand All @@ -201,7 +201,8 @@ async function callLocalAI(endpoint, model, systemPrompt, userPrompt, options =
{ role: 'user', content: userPrompt }
],
max_tokens: maxTokens,
temperature
temperature,
stream: false
}),
signal: controller.signal
});
Expand Down
68 changes: 59 additions & 9 deletions src/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -115,20 +115,70 @@ function registerApp(app, { getRouter, addHandler } = {}) {
if (repoOrg === targetOrg) {
getLogger().info({ repo: repository.full_name }, 'New repository created');

// Wait for the default branch to exist before configuring.
// When GitHub fires repository.created, the repo exists but the default
// branch is only created after the first commit.
const defaultBranch = repository.default_branch || 'main';
const owner = repository.owner.login;
const repoName = repository.name;
let branchReady = false;

for (let attempt = 1; attempt <= 5; attempt++) {
try {
await context.octokit.repos.getBranch({
owner,
repo: repoName,
branch: defaultBranch
});
branchReady = true;
break;
} catch (err) {
if (err.status === 404) {
getLogger().info(
{ repo: repository.full_name, branch: defaultBranch, attempt },
`Default branch not ready yet, retrying in 2s (attempt ${attempt}/5)`
);
await new Promise(resolve => setTimeout(resolve, 2000));
} else {
getLogger().warn(
{ repo: repository.full_name, err: err.message },
'Unexpected error checking for default branch'
);
break;
}
}
}

if (!branchReady) {
getLogger().warn(
{ repo: repository.full_name, branch: defaultBranch },
'Default branch never appeared — repo may still be empty. Skipping configuration.'
);
if (deliveryId) markProcessed(deliveryId);
return;
}

const result = await configureRepository(context.octokit, repository, undefined, {
enqueueTask: getEnqueueTask()
});

if (repository.has_issues) {
await context.octokit.issues.create({
owner: repository.owner.login,
repo: repository.name,
title: 'Repository Configuration',
body: result.success
? '✅ This repository has been automatically configured with standard merge settings and branch protection.'
: `❌ Configuration failed: ${result.error}`,
labels: ['automation', 'configuration']
});
try {
await context.octokit.issues.create({
owner,
repo: repoName,
title: 'Repository Configuration',
body: result.success
? '✅ This repository has been automatically configured with standard merge settings and branch protection.'
: `❌ Configuration failed: ${result.error}`,
labels: ['automation', 'configuration']
});
} catch (issueErr) {
getLogger().warn(
{ repo: repository.full_name, err: issueErr.message },
'Failed to create configuration issue — issues may not be fully initialized yet'
);
}
}
}

Expand Down