fix: CI indexing

This commit is contained in:
valknarness
2025-10-26 22:04:46 +01:00
parent 9eb428dd63
commit c0d3ffd328
3 changed files with 93 additions and 7 deletions

View File

@@ -58,8 +58,8 @@ jobs:
INDEX_MODE="${{ github.event.inputs.index_mode || 'full' }}" INDEX_MODE="${{ github.event.inputs.index_mode || 'full' }}"
echo "Index mode: $INDEX_MODE" echo "Index mode: $INDEX_MODE"
# Build the index in non-interactive mode # Build the index in non-interactive mode (170m timeout, job timeout is 180m)
timeout 150m node -e " timeout 170m node -e "
const db = require('./lib/database'); const db = require('./lib/database');
const dbOps = require('./lib/db-operations'); const dbOps = require('./lib/db-operations');
const indexer = require('./lib/indexer'); const indexer = require('./lib/indexer');
@@ -73,6 +73,8 @@ jobs:
if (process.env.GITHUB_TOKEN) { if (process.env.GITHUB_TOKEN) {
dbOps.setSetting('githubToken', process.env.GITHUB_TOKEN); dbOps.setSetting('githubToken', process.env.GITHUB_TOKEN);
console.log('GitHub token configured'); console.log('GitHub token configured');
} else {
console.warn('⚠️ WARNING: No GitHub token found! Rate limit will be 60/hour instead of 5000/hour');
} }
// Build index // Build index
@@ -92,7 +94,8 @@ jobs:
" || { " || {
EXIT_CODE=$? EXIT_CODE=$?
if [ $EXIT_CODE -eq 124 ]; then if [ $EXIT_CODE -eq 124 ]; then
echo "Index building timed out after 150 minutes" echo "Index building timed out after 170 minutes"
echo "This may indicate rate limiting issues or too many lists to index"
fi fi
exit $EXIT_CODE exit $EXIT_CODE
} }

View File

@@ -13,6 +13,37 @@ function getGitHubToken() {
return db.getSetting('githubToken', null); return db.getSetting('githubToken', null);
} }
// Check rate limit status proactively
async function checkRateLimit() {
const token = getGitHubToken();
const headers = {
'Accept': 'application/vnd.github.v3+json',
'User-Agent': 'awesome-cli'
};
if (token) {
headers['Authorization'] = `token ${token}`;
}
try {
const response = await axios.get('https://api.github.com/rate_limit', {
timeout: 5000,
headers
});
const core = response.data.resources.core;
return {
limit: core.limit,
remaining: core.remaining,
reset: core.reset * 1000,
used: core.used
};
} catch (error) {
// If we can't check rate limit, continue anyway
return null;
}
}
// Rate-limited request with better handling // Rate-limited request with better handling
async function rateLimitedRequest(url, options = {}) { async function rateLimitedRequest(url, options = {}) {
const now = Date.now(); const now = Date.now();
@@ -22,6 +53,26 @@ async function rateLimitedRequest(url, options = {}) {
await new Promise(resolve => setTimeout(resolve, RATE_LIMIT_DELAY - timeSinceLastRequest)); await new Promise(resolve => setTimeout(resolve, RATE_LIMIT_DELAY - timeSinceLastRequest));
} }
// Check rate limit proactively every 50 requests
if (Math.random() < 0.02) { // 2% chance = roughly every 50 requests
const rateLimitStatus = await checkRateLimit();
if (rateLimitStatus && rateLimitStatus.remaining < 10) {
const waitTime = Math.max(0, rateLimitStatus.reset - Date.now());
const waitMinutes = Math.ceil(waitTime / 60000);
console.log();
console.log(chalk.yellow(`⚠️ Rate limit low: ${rateLimitStatus.remaining}/${rateLimitStatus.limit} remaining`));
console.log(chalk.yellow(` Proactively waiting ${waitMinutes} minutes to avoid exhausting limit...`));
const isCI = process.env.CI === 'true';
if (isCI) {
console.log(chalk.cyan('🤖 CI mode: automatically waiting...'));
await new Promise(resolve => setTimeout(resolve, waitTime + 30000)); // 30s buffer
console.log(chalk.green('✓ Rate limit reset, resuming...'));
}
}
}
lastRequestTime = Date.now(); lastRequestTime = Date.now();
const token = getGitHubToken(); const token = getGitHubToken();
@@ -50,9 +101,15 @@ async function rateLimitedRequest(url, options = {}) {
const waitMinutes = Math.ceil(waitTime / 60000); const waitMinutes = Math.ceil(waitTime / 60000);
if (remaining === '0' || remaining === 0) { if (remaining === '0' || remaining === 0) {
const rateLimit = error.response.headers['x-ratelimit-limit'];
const resetDate = new Date(resetTime).toISOString();
console.log(); console.log();
console.log(chalk.red('⚠️ GitHub API Rate Limit Exceeded!')); console.log(chalk.red('⚠️ GitHub API Rate Limit Exceeded!'));
console.log(chalk.yellow(` Rate limit: ${rateLimit} requests/hour`));
console.log(chalk.yellow(` Reset at: ${resetDate}`));
console.log(chalk.yellow(` Wait time: ${waitMinutes} minutes`)); console.log(chalk.yellow(` Wait time: ${waitMinutes} minutes`));
console.log(chalk.gray(` Token status: ${token ? 'USING TOKEN ✓' : 'NO TOKEN ✗'}`));
if (!token && !rateLimitWarningShown) { if (!token && !rateLimitWarningShown) {
console.log(); console.log();
@@ -93,9 +150,13 @@ async function rateLimitedRequest(url, options = {}) {
} else if (action === 'skip') { } else if (action === 'skip') {
throw new Error('SKIP_RATE_LIMIT'); // Special error to skip throw new Error('SKIP_RATE_LIMIT'); // Special error to skip
} else { } else {
// Wait with countdown // Wait with countdown and add 30 second buffer to ensure rate limit has fully reset
console.log(chalk.gray(`\nWaiting ${waitMinutes} minutes...`)); const bufferTime = 30000; // 30 seconds
await new Promise(resolve => setTimeout(resolve, waitTime + 1000)); const totalWaitTime = waitTime + bufferTime;
const totalWaitMinutes = Math.ceil(totalWaitTime / 60000);
console.log(chalk.gray(`\nWaiting ${totalWaitMinutes} minutes (including 30s buffer)...`));
await new Promise(resolve => setTimeout(resolve, totalWaitTime));
console.log(chalk.green('✓ Rate limit should be reset, resuming...'));
return rateLimitedRequest(url, options); return rateLimitedRequest(url, options);
} }
} }
@@ -223,5 +284,6 @@ module.exports = {
getLatestCommit, getLatestCommit,
getAwesomeListsIndex, getAwesomeListsIndex,
parseGitHubUrl, parseGitHubUrl,
rateLimitedRequest rateLimitedRequest,
getRateLimitStatus: checkRateLimit
}; };

View File

@@ -202,6 +202,27 @@ async function buildIndex(force = false, mode = null) {
} }
} }
// Check rate limit status before starting
try {
const rateLimitInfo = await github.getRateLimitStatus();
if (rateLimitInfo) {
console.log(chalk.cyan('📊 GitHub API Rate Limit Status:'));
console.log(chalk.gray(` Limit: ${rateLimitInfo.limit} requests/hour`));
console.log(chalk.gray(` Remaining: ${rateLimitInfo.remaining}/${rateLimitInfo.limit}`));
console.log(chalk.gray(` Used: ${rateLimitInfo.used}`));
console.log(chalk.gray(` Resets at: ${new Date(rateLimitInfo.reset).toISOString()}`));
console.log();
if (rateLimitInfo.limit === 60) {
console.log(chalk.yellow('⚠️ WARNING: Using unauthenticated rate limit (60/hour)'));
console.log(chalk.yellow(' This will likely not be enough to complete indexing'));
console.log();
}
}
} catch (error) {
console.log(chalk.gray('Could not check rate limit status, continuing...'));
}
console.log(pinkPurple(`\n✨ Starting index of ${listsToIndex.length} awesome lists ✨\n`)); console.log(pinkPurple(`\n✨ Starting index of ${listsToIndex.length} awesome lists ✨\n`));
// Progress bars // Progress bars