Skip to content

Commit

Permalink
refactor to make workflow more testable, code fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
gautamkrishnar committed Jan 8, 2024
1 parent 7783844 commit 17b50a8
Showing 1 changed file with 164 additions and 149 deletions.
313 changes: 164 additions & 149 deletions src/blog-post-workflow.js
Original file line number Diff line number Diff line change
Expand Up @@ -195,8 +195,12 @@ feedList.forEach((siteUrl) => {
) {
post = null;
} else {
post.title && appendedPostTitles.push(post.title.trim());
post.description && appendedPostDesc.push(post.description.trim());
if (post.title) {
appendedPostTitles.push(post.title.trim());
}
if (post.description) {
appendedPostDesc.push(post.description.trim());
}
}
}

Expand All @@ -219,165 +223,176 @@ feedList.forEach((siteUrl) => {
}));
});

// Processing the generated promises
Promise.allSettled(promiseArray).then((results) => {
results.forEach((result, index) => {
if (result.status === 'fulfilled') {
// Succeeded
core.info(runnerNameArray[index] + ' runner succeeded. Post count: ' + result.value.length);
// Adds feed name to the items
if (typeof feedNamesList[index] !== undefined && feedNamesList[index]) {
result.value = result.value.map((item) => {
item.feedName = feedNamesList[index];
return item;
});
}
postsArray.push(...result.value);
} else {
jobFailFlag = true;
// Rejected
core.error(runnerNameArray[index] + ' runner failed, please verify the configuration. Error:');
if (result.reason && result.reason.message && result.reason.message.startsWith('Status code')) {
const code = result.reason.message.replace('Status code ', '');
core.error(`Looks like your website returned ${code}, There is nothing blog post workflow` +
` can do to fix it. Please check your website's RSS feed generation source code. Also double check the URL.`);
if (code === `503`) {
core.error(`If you are using Cloudflare or Akamai, make sure that you have the user agent ` +
` ${userAgent} or GitHub actions IP ranges whitelisted in your firewall.`);
const runWorkflow = async () => {
// Processing the generated promises
await Promise.allSettled(promiseArray).then((results) => {
results.forEach((result, index) => {
if (result.status === 'fulfilled') {
// Succeeded
core.info(runnerNameArray[index] + ' runner succeeded. Post count: ' + result.value.length);
// Adds feed name to the items
if (typeof feedNamesList[index] !== undefined && feedNamesList[index]) {
result.value = result.value.map((item) => {
item.feedName = feedNamesList[index];
return item;
});
}
postsArray.push(...result.value);
} else {
core.error(result.reason || result.reason.message);
jobFailFlag = true;
// Rejected
core.error(runnerNameArray[index] + ' runner failed, please verify the configuration. Error:');
if (result.reason && result.reason.message && result.reason.message.startsWith('Status code')) {
const code = result.reason.message.replace('Status code ', '');
core.error(`Looks like your website returned ${code}, There is nothing blog post workflow` +
` can do to fix it. Please check your website's RSS feed generation source code. Also double check
the URL.`);
if (code === `503`) {
core.error(`If you are using Cloudflare or Akamai, make sure that you have the user agent ` +
` ${userAgent} or GitHub actions IP ranges whitelisted in your firewall.`);
}
} else {
core.error(result.reason || result.reason.message);
}
}
}
});
}).finally(async () => {
// Ignore null items, allows you to ignore items by setting null in post via `item_exec`
postsArray = postsArray.filter(item => item !== null);

// Sorting posts based on date
if (ENABLE_SORT) {
postsArray.sort(function (a, b) {
return b.date - a.date;
});
}
// Slicing with the max count
postsArray = postsArray.slice(0, TOTAL_POST_COUNT);
if (postsArray.length > 0) {
try {
if (!process.env.TEST_MODE) {
await exec('git', ['config', 'pull.rebase', 'true'], {stdio: ['pipe', 'pipe', 'pipe']});
// Pulling the latest changes from upstream
await exec('git', ['pull'], {stdio: ['pipe', 'pipe', 'pipe']});
}
const template = core.getInput('template');
const randEmojiArr = getParameterisedTemplate(template, 'randomEmoji');
const constEmojiArr = getParameterisedTemplate(template, 'emojiKey');
const postListMarkdown = postsArray.reduce((acc, cur, index) => {
if (template === 'default') {
// Default template: - [$title]($url)
return acc + `\n- [${cur.title}](${cur.url})` + (((index + 1) === postsArray.length) ? '\n' : '');
} else {
// Building categories listing
const categoryTemplate = core.getInput('categories_template');
const categoryList = categoryTemplate === 'default' ?
cur.categories.join(', ') : cur.categories.reduce((prev, current) =>
prev + categoryTemplate.replace(/\$category\b/g, current.toString()), '');
// Building with custom template
const date = dateFormat(cur.date, core.getInput('date_format')); // Formatting date
let content = template
.replace(/\$title\b/g, cur.title)
.replace(/\$url\b/g, cur.url)
.replace(/\$description\b/g, cur.description)
.replace(/\$date\b/g, date)
.replace(/\$counter\b/g, (index + 1).toString())
.replace(/\$feedName\b/g, cur.feedName ? cur.feedName : '')
.replace(/\$categories\b/g, categoryList.toString())
.replace(/\$newline/g, '\n');

// Setting Custom tags to the template
Object.keys(CUSTOM_TAGS).forEach((tag) => {
const replaceValue = cur[tag] ? cur[tag] : '';
content = content.replace(new RegExp('\\$' + tag + '\\b', 'g'), replaceValue);
});
}).finally(async () => {
// Ignore null items, allows you to ignore items by setting null in post via `item_exec`
postsArray = postsArray.filter(item => item !== null);

// Sorting posts based on date
if (ENABLE_SORT) {
postsArray.sort(function (a, b) {
return b.date - a.date;
});
}
// Slicing with the max count
postsArray = postsArray.slice(0, TOTAL_POST_COUNT);
if (postsArray.length > 0) {
try {
if (!process.env.TEST_MODE) {
await exec('git', ['config', 'pull.rebase', 'true'], {stdio: ['pipe', 'pipe', 'pipe']});
// Pulling the latest changes from upstream
await exec('git', ['pull'], {stdio: ['pipe', 'pipe', 'pipe']});
}
const template = core.getInput('template');
const randEmojiArr = getParameterisedTemplate(template, 'randomEmoji');
const constEmojiArr = getParameterisedTemplate(template, 'emojiKey');
const postListMarkdown = postsArray.reduce((acc, cur, index) => {
if (template === 'default') {
// Default template: - [$title]($url)
return acc + `\n- [${cur.title}](${cur.url})` + (((index + 1) === postsArray.length) ? '\n' : '');
} else {
// Building categories listing
const categoryTemplate = core.getInput('categories_template');
const categoryList = categoryTemplate === 'default' ?
cur.categories.join(', ') : cur.categories.reduce((prev, current) =>
prev + categoryTemplate.replace(/\$category\b/g, current.toString()), '');
// Building with custom template
const date = dateFormat(cur.date, core.getInput('date_format')); // Formatting date
let content = template
.replace(/\$title\b/g, cur.title)
.replace(/\$url\b/g, cur.url)
.replace(/\$description\b/g, cur.description)
.replace(/\$date\b/g, date)
.replace(/\$counter\b/g, (index + 1).toString())
.replace(/\$feedName\b/g, cur.feedName ? cur.feedName : '')
.replace(/\$categories\b/g, categoryList.toString())
.replace(/\$newline/g, '\n');

// Setting Custom tags to the template
Object.keys(CUSTOM_TAGS).forEach((tag) => {
const replaceValue = cur[tag] ? cur[tag] : '';
content = content.replace(new RegExp('\\$' + tag + '\\b', 'g'), replaceValue);
});

// Emoji implementation: Random
if (randEmojiArr) {
// For making randomness unique for each repos
let seed = (process.env.GITHUB_REPOSITORY && !process.env.TEST_MODE ?
process.env.GITHUB_REPOSITORY : 'example') + index;
if (core.getInput('rand_seed')) {
// If manual seed is provided, use it
seed = core.getInput('rand_seed') + index;
// Emoji implementation: Random
if (randEmojiArr) {
// For making randomness unique for each repos
let seed = (process.env.GITHUB_REPOSITORY && !process.env.TEST_MODE ?
process.env.GITHUB_REPOSITORY : 'example') + index;
if (core.getInput('rand_seed')) {
// If manual seed is provided, use it
seed = core.getInput('rand_seed') + index;
}
const emoji = randEmojiArr[rand.create(seed).range(randEmojiArr.length)];
content = content.replace(/\$randomEmoji\((\S)*\)/g, emoji);
}
const emoji = randEmojiArr[rand.create(seed).range(randEmojiArr.length)];
content = content.replace(/\$randomEmoji\((\S)*\)/g, emoji);
}

// Emoji implementation: Static
if (constEmojiArr) {
// using modulus
content = content.replace(/\$emojiKey\((\S)*\)/g, constEmojiArr[index % constEmojiArr.length]);
}
// Emoji implementation: Static
if (constEmojiArr) {
// using modulus
content = content.replace(/\$emojiKey\((\S)*\)/g, constEmojiArr[index % constEmojiArr.length]);
}

return acc + content;
}
}, '');

// Output only mode
const outputOnly = core.getInput('output_only') !== 'false';
if (outputOnly) {
// Sets output as output as `results` variable in github action
core.info('outputOnly mode: set `results` variable. Readme not committed.');
core.setOutput('results', postsArray);
const outputFilePath = path.join('/','tmp', 'blog_post_workflow_output.json');
if(fs.existsSync(outputFilePath)) {
fs.rmSync(outputFilePath);
return acc + content;
}
}, '');

// Output only mode
const outputOnly = core.getInput('output_only') !== 'false';
if (outputOnly) {
// Sets output as output as `results` variable in github action
core.info('outputOnly mode: set `results` variable. Readme not committed.');
core.setOutput('results', postsArray);
const outputFilePath = path.join('/','tmp', 'blog_post_workflow_output.json');
if(fs.existsSync(outputFilePath)) {
fs.rmSync(outputFilePath);
}
fs.writeFileSync(outputFilePath, JSON.stringify(postsArray), { encoding: 'utf-8'});
process.exit(jobFailFlag ? 1 : 0);
}
fs.writeFileSync(outputFilePath, JSON.stringify(postsArray), { encoding: 'utf-8'});
process.exit(jobFailFlag ? 1 : 0);
}

// Writing to each readme file
let changedReadmeCount = 0;
README_FILE_PATH_LIST.forEach((README_FILE_PATH) => {
const readmeData = fs.readFileSync(README_FILE_PATH, 'utf8');
const newReadme = buildReadme(readmeData, postListMarkdown);
// if there's change in readme file update it
if (newReadme !== readmeData) {
core.info('Writing to ' + README_FILE_PATH);
fs.writeFileSync(README_FILE_PATH, newReadme);
changedReadmeCount = changedReadmeCount + 1;
}
});
// Writing to each readme file
let changedReadmeCount = 0;
README_FILE_PATH_LIST.forEach((README_FILE_PATH) => {
const readmeData = fs.readFileSync(README_FILE_PATH, 'utf8');
const newReadme = buildReadme(readmeData, postListMarkdown);
// if there's change in readme file update it
if (newReadme !== readmeData) {
core.info('Writing to ' + README_FILE_PATH);
fs.writeFileSync(README_FILE_PATH, newReadme);
changedReadmeCount = changedReadmeCount + 1;
}
});

if (changedReadmeCount > 0 && !SKIP_COMMITS) {
if (!process.env.TEST_MODE) {
// Commit to readme
await commitReadme(GITHUB_TOKEN, README_FILE_PATH_LIST).then(() => {
// Making job fail if one of the source fails
process.exit(jobFailFlag ? 1 : 0);
});
}
} else {
// Calculating last commit date, please see https://git.io/Jtm4V
if (!process.env.TEST_MODE && ENABLE_KEEPALIVE) {
// Do dummy commit if elapsed time is greater than 50 days
const committerUsername = core.getInput('committer_username');
const committerEmail = core.getInput('committer_email');
const message = await keepaliveWorkflow.KeepAliveWorkflow(GITHUB_TOKEN, committerUsername, committerEmail,
'dummy commit to keep the repository active, see https://git.io/Jtm4V', 50, true);
core.info(message);
if (changedReadmeCount > 0 && !SKIP_COMMITS) {
if (!process.env.TEST_MODE) {
// Commit to readme
await commitReadme(GITHUB_TOKEN, README_FILE_PATH_LIST).then(() => {
// Making job fail if one of the source fails
process.exit(jobFailFlag ? 1 : 0);
});
}
} else {
core.info('No change detected, skipping');
// Calculating last commit date, please see https://git.io/Jtm4V
if (!process.env.TEST_MODE && ENABLE_KEEPALIVE) {
// Do dummy commit if elapsed time is greater than 50 days
const committerUsername = core.getInput('committer_username');
const committerEmail = core.getInput('committer_email');
const message = await keepaliveWorkflow.KeepAliveWorkflow(GITHUB_TOKEN, committerUsername, committerEmail,
'dummy commit to keep the repository active, see https://git.io/Jtm4V', 50, true);
core.info(message);
} else {
core.info('No change detected, skipping');
}
process.exit(jobFailFlag ? 1 : 0);
}
process.exit(jobFailFlag ? 1 : 0);
} catch (e) {
core.error(e);
process.exit(1);
}
} catch (e) {
core.error(e);
process.exit(1);
} else {
core.info('0 blog posts fetched');
process.exit(jobFailFlag ? 1 : 0);
}
} else {
core.info('0 blog posts fetched');
process.exit(jobFailFlag ? 1 : 0);
}
});
});
};

module.exports = {
runWorkflow
};

if (!module.parent) {
runWorkflow().then();
}

0 comments on commit 17b50a8

Please sign in to comment.