Skip to content

Commit

Permalink
docs: releases extension allows CI authentication and retries
Browse files Browse the repository at this point in the history
  • Loading branch information
alandefreitas committed Oct 15, 2024
1 parent 5e0f628 commit 55214d7
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 8 deletions.
4 changes: 4 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -533,6 +533,8 @@ jobs:
# This playbook renders the documentation
# content for the website. It includes
# master, develop, and tags.
GH_TOKEN="${{ secrets.GITHUB_TOKEN }}"
export GH_TOKEN
npm ci
npx antora antora-playbook.yml
mkdir -p ../build/website/docs
Expand All @@ -553,6 +555,8 @@ jobs:
# before a workflow that pushes to the
# website is triggered.
set -x
GH_TOKEN="${{ secrets.GITHUB_TOKEN }}"
export GH_TOKEN
npx antora antora-playbook.yml --attribute branchesarray=HEAD --stacktrace
mkdir -p ../build/docs-local
cp -r build/site/* ../build/docs-local
Expand Down
85 changes: 77 additions & 8 deletions docs/extensions/mrdocs-releases.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,27 +19,96 @@ function humanizeBytes(bytes) {
}

function humanizeDate(date) {
const options = { year: 'numeric', month: 'long', day: 'numeric' };
const options = {year: 'numeric', month: 'long', day: 'numeric'};
return new Date(date).toLocaleDateString('en-US', options);
}

/**
* Formats a given time duration in milliseconds into a human-readable string.
*
* @param {number} milliseconds - The time duration in milliseconds.
* @returns {string} - A formatted string representing the time duration in days, hours, minutes, seconds, and milliseconds.
*/
function formatTime(milliseconds) {
const seconds = Math.floor(milliseconds / 1000);
const remainingMilliseconds = milliseconds % 1000;

const minutes = Math.floor(seconds / 60);
const remainingSeconds = seconds % 60;

const hours = Math.floor(minutes / 60);
const remainingMinutes = minutes % 60;

const days = Math.floor(hours / 24);
const remainingHours = hours % 24;

if (days > 0) {
return `${days} days, ${remainingHours} hours, ${remainingMinutes} minutes, ${remainingSeconds} seconds, ${remainingMilliseconds} milliseconds`;
}
if (hours > 0) {
return `${hours} hours, ${remainingMinutes} minutes, ${remainingSeconds} seconds, ${remainingMilliseconds} milliseconds`;
}
if (minutes > 0) {
return `${minutes} minutes, ${remainingSeconds} seconds, ${remainingMilliseconds} milliseconds`;
}
if (seconds > 0) {
return `${seconds} seconds, ${remainingMilliseconds} milliseconds`;
}
return `${milliseconds} milliseconds`;
}

/**
* Fetches data from a URL with exponential backoff retry strategy.
*
* @param {string} url - The URL to fetch data from.
* @param {Object} headers - The headers to include in the request.
* @returns {string} - The response body.
* @throws {Error} - If all retries fail.
*/
function fetchWithRetry(url, headers) {
const maxRetries = 40;
let retryDelay = 1000; // Initial delay in milliseconds

for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
const response = request('GET', url, {headers});
return response.getBody('utf-8');
} catch (error) {
if (attempt === maxRetries) {
throw new Error(`Failed to fetch data after ${maxRetries} attempts: ${error.message}`);
}
console.error(`Failed to fetch data:\n${error.message}.\nRequest headers: ${JSON.stringify(headers)}.\nRetrying in ${formatTime(retryDelay)}.`);
// Wait for retryDelay milliseconds before retrying
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, retryDelay);
retryDelay *= 2; // Exponential backoff
const maxDelay = 180000; // Maximum delay of 3 minutes
if (retryDelay > maxDelay) {
retryDelay = maxDelay;
}
}
}
}

module.exports = function (registry) {
registry.blockMacro('mrdocs-releases', function () {
const self = this
self.process(function (parent, target, attrs) {
// Collect all release URLs
let cacheFilenamePath = 'releasesResponse.json';
let cachePath = `${__dirname}/../build/requests/${cacheFilenamePath}`;
fs.mkdirSync(`${__dirname}/../build/requests/`, { recursive: true });
fs.mkdirSync(`${__dirname}/../build/requests/`, {recursive: true});
const GH_TOKEN = process.env.GITHUB_TOKEN || process.env.GH_TOKEN || ''
const apiHeaders = GH_TOKEN ? {
'User-Agent': 'request',
'Authorization': `Bearer ${GH_TOKEN}`
} : {
'User-Agent': 'request'
}
const readFromCacheFile = fs.existsSync(cachePath) && fs.statSync(cachePath).mtime > new Date(Date.now() - 1000 * 60 * 60 * 24);
const releasesResponse =
readFromCacheFile ?
fs.readFileSync(cachePath, 'utf-8') :
request('GET', 'https://api.github.com/repos/cppalliance/mrdocs/releases', {
headers: {
'User-Agent': 'request'
}
}).getBody('utf-8')
fs.readFileSync(cachePath, 'utf-8') :
fetchWithRetry('https://api.github.com/repos/cppalliance/mrdocs/releases', apiHeaders)
if (!readFromCacheFile) {
fs.writeFileSync(cachePath, releasesResponse);
}
Expand Down

0 comments on commit 55214d7

Please sign in to comment.