fix(resources): match cr to lf change in pr-build-status.mjs

Follows: #14732
Build-bot: skip
Test-bot: skip
This commit is contained in:
Marc Durdin 2025-09-11 14:59:51 +02:00
parent 52caaa4ea3
commit 293dbb83e9
2 changed files with 193 additions and 193 deletions

View file

@ -1,4 +1,4 @@
# GENERATED FILE - DO NOT EDIT!
# GENERATED FILE - DO NOT EDIT!
#
# Keyman is copyright (C) SIL Global. MIT License.
#
@ -35,194 +35,194 @@ jobs:
id: run_pr_build_status_script
uses: actions/github-script@v7
with:
script: |
// This code is copied out of resources/build/pr-build-status/pr-build-status.mjs
// where it is tested. It is copied inline here in order to avoid requiring the
// repository to be checked out, which dramatically reduces the run time of the
// check.
//
// Note: we don't currently look at check runs, only statuses
//
// Verify the following statuses:
// 'user_testing'
// 'API Verification' (github-actions[bot])
//
// At least 1 of the following statuses must be found:
// 'Test*' (keyman-server), e.g. 'Test Build (Keyman)'
// 'Ubuntu Packaging' (github-actions[bot])
//
// Ignore the following statuses:
// check/web/file-size
//
function addLog(message) {
console.log(message);
return message + String.fromCharCode(10);
}
function addStatus(o, type, context, state) {
if(!o[context]) {
o[context] = {type, state};
return addLog(`Found ${context}: ${state}`);
} else {
return addLog(`Skipping repeated ${context}: ${state}`);
}
}
function reduceStatuses(statuses) {
let summary = '';
const filtered_statuses = statuses.reduce((o, status) => {
if(status.creator?.login == 'keyman-server' && status.context.startsWith('Test')) {
summary += addStatus(o, 'build', status.context, status.state);
} else if(status.creator?.login == 'keymanapp-test-bot[bot]' && status.context == 'user_testing') {
summary += addStatus(o, 'user-test', status.context, status.state);
} else if(status.context == 'API Verification') {
summary += addStatus(o, 'check', status.context, status.state);
} else if(status.context == 'Ubuntu Packaging') {
summary += addStatus(o, 'build', status.context, status.state);
} else if(status.context == 'check/web/file-size') {
// Ignore check/web/file-size -- we won't block automerge for this at this point
summary += addLog(`Skipping ${status.context}`);
} else {
// We fail with an 'unknown status' response if we get a new status check
// so we can be sure we are not skipping known status checks
summary += addLog(`Found unknown ${status.context}: ${status.state}`);
o[status.context] = {type: 'unknown', state: status.state};
}
return o;
}, {});
return { filtered_statuses, summary };
}
//
// Given the collection of status checks we care about, return
// an aggregate status -- error, failure, pending, or success,
// and a summary description
//
function calculateFinalStatus(filtered_statuses, summary) {
const counts = {};
let hasBuilds = false;
for(const context of Object.keys(filtered_statuses)) {
const { state, type } = filtered_statuses[context];
if(type == 'unknown') {
// We special-case for unknown status checks, and never permit them
console.error(`An unknown context ${context} was found, cannot calculate build status.`);
return [
'error', `An unknown context ${context} was found, cannot calculate build status.`, summary
];
}
if(type == 'build') {
hasBuilds = true;
}
counts[state] = counts[state] ? counts[state] + 1 : 1;
}
// If we do not have any statuses yet, we wait
if(Object.keys(filtered_statuses).length == 0 || !hasBuilds) {
console.log(`Builds not yet triggered`);
return ['pending', 'Builds have not yet been triggered ⌛', summary];
}
const state =
counts.error ? 'error' :
counts.failure ? 'failure' :
counts.pending ? 'pending' :
'success';
let description = '';
function appendDescription(count, state) {
if(!count) return;
if(description != '') description += '; ';
description += `${count} check${count == 1 ? '' : 's'} ${state}`;
}
appendDescription(counts.error, 'in an error state ❌');
appendDescription(counts.failure, 'failed ❌');
appendDescription(counts.pending, 'pending ⌛');
appendDescription(counts.success, 'completed successfully ✅');
console.log(`Finished filtering and reviewing status checks: ${state}: ${description}`);
return [ state, description, summary ];
}
async function getCommitStatuses(github, owner, repo, sha) {
console.log(`Getting commit statuses for ${sha}`);
const statuses = await github.paginate('GET /repos/{owner}/{repo}/commits/{sha}/statuses', {
owner,
repo,
sha,
headers: {
'X-GitHub-Api-Version': '2022-11-28'
}
});
return statuses;
}
async function getCommitCheckRuns(github, owner, repo, sha) {
console.log(`Getting commit check runs for ${sha}`);
const statuses = await github.paginate('GET /repos/{owner}/{repo}/commits/{sha}/check-runs', {
owner,
repo,
sha,
headers: {
'X-GitHub-Api-Version': '2022-11-28'
}
});
return statuses;
}
function calculateCheckResult(statuses) {
if(!Array.isArray(statuses)) {
return ['error', 'Failed to retrieve status checks from GitHub ❌', 'statuses is not an array'];
}
const { filtered_statuses, summary } = reduceStatuses(statuses);
return calculateFinalStatus(filtered_statuses, summary);
}
async function test(github, owner, repo, sha) {
// Get statuses from sha
const statuses = await getCommitStatuses(github, owner, repo, sha);
return calculateCheckResult(statuses);
}
async function createCheck(github, owner, repo, sha) {
const check = await github.rest.checks.create({
owner,
repo,
head_sha: sha,
name: 'Build Outcome',
status: 'in_progress',
});
return check.data.id;
}
async function updateCheck(github, owner, repo, checkRunId, status, description, summary) {
const checkStatus = status == 'pending' ? 'in_progress' : 'completed';
const conclusion = checkStatus == 'in_progress' ? undefined : (status == 'success' ? 'success' : 'failure');
await github.rest.checks.update({
owner,
repo,
check_run_id: checkRunId,
status: checkStatus,
conclusion,
output: {
title: description,
summary
}
});
}
const { owner, repo } = context.repo;
const sha =
context.payload?.check_suite?.sha || /* check run completed */
context.payload?.inputs?.commit || /* manual run */
context.payload?.after || /* push */
context.payload?.commit?.sha || /* status */
context.sha; /* probably 'master'! */
const checkRunId = await createCheck(github, owner, repo, sha);
const res = await test(github, owner, repo, sha);
await updateCheck(github, owner, repo, checkRunId, res[0], res[1], res[2]);
script: |
// This code is copied out of resources/build/pr-build-status/pr-build-status.mjs
// where it is tested. It is copied inline here in order to avoid requiring the
// repository to be checked out, which dramatically reduces the run time of the
// check.
//
// Note: we don't currently look at check runs, only statuses
//
// Verify the following statuses:
// 'user_testing'
// 'API Verification' (github-actions[bot])
//
// At least 1 of the following statuses must be found:
// 'Test*' (keyman-server), e.g. 'Test Build (Keyman)'
// 'Ubuntu Packaging' (github-actions[bot])
//
// Ignore the following statuses:
// check/web/file-size
//
function addLog(message) {
console.log(message);
return message + String.fromCharCode(10);
}
function addStatus(o, type, context, state) {
if(!o[context]) {
o[context] = {type, state};
return addLog(`Found ${context}: ${state}`);
} else {
return addLog(`Skipping repeated ${context}: ${state}`);
}
}
function reduceStatuses(statuses) {
let summary = '';
const filtered_statuses = statuses.reduce((o, status) => {
if(status.creator?.login == 'keyman-server' && status.context.startsWith('Test')) {
summary += addStatus(o, 'build', status.context, status.state);
} else if(status.creator?.login == 'keymanapp-test-bot[bot]' && status.context == 'user_testing') {
summary += addStatus(o, 'user-test', status.context, status.state);
} else if(status.context == 'API Verification') {
summary += addStatus(o, 'check', status.context, status.state);
} else if(status.context == 'Ubuntu Packaging') {
summary += addStatus(o, 'build', status.context, status.state);
} else if(status.context == 'check/web/file-size') {
// Ignore check/web/file-size -- we won't block automerge for this at this point
summary += addLog(`Skipping ${status.context}`);
} else {
// We fail with an 'unknown status' response if we get a new status check
// so we can be sure we are not skipping known status checks
summary += addLog(`Found unknown ${status.context}: ${status.state}`);
o[status.context] = {type: 'unknown', state: status.state};
}
return o;
}, {});
return { filtered_statuses, summary };
}
//
// Given the collection of status checks we care about, return
// an aggregate status -- error, failure, pending, or success,
// and a summary description
//
function calculateFinalStatus(filtered_statuses, summary) {
const counts = {};
let hasBuilds = false;
for(const context of Object.keys(filtered_statuses)) {
const { state, type } = filtered_statuses[context];
if(type == 'unknown') {
// We special-case for unknown status checks, and never permit them
console.error(`An unknown context ${context} was found, cannot calculate build status.`);
return [
'error', `An unknown context ${context} was found, cannot calculate build status.`, summary
];
}
if(type == 'build') {
hasBuilds = true;
}
counts[state] = counts[state] ? counts[state] + 1 : 1;
}
// If we do not have any statuses yet, we wait
if(Object.keys(filtered_statuses).length == 0 || !hasBuilds) {
console.log(`Builds not yet triggered`);
return ['pending', 'Builds have not yet been triggered ⌛', summary];
}
const state =
counts.error ? 'error' :
counts.failure ? 'failure' :
counts.pending ? 'pending' :
'success';
let description = '';
function appendDescription(count, state) {
if(!count) return;
if(description != '') description += '; ';
description += `${count} check${count == 1 ? '' : 's'} ${state}`;
}
appendDescription(counts.error, 'in an error state ❌');
appendDescription(counts.failure, 'failed ❌');
appendDescription(counts.pending, 'pending ⌛');
appendDescription(counts.success, 'completed successfully ✅');
console.log(`Finished filtering and reviewing status checks: ${state}: ${description}`);
return [ state, description, summary ];
}
async function getCommitStatuses(github, owner, repo, sha) {
console.log(`Getting commit statuses for ${sha}`);
const statuses = await github.paginate('GET /repos/{owner}/{repo}/commits/{sha}/statuses', {
owner,
repo,
sha,
headers: {
'X-GitHub-Api-Version': '2022-11-28'
}
});
return statuses;
}
async function getCommitCheckRuns(github, owner, repo, sha) {
console.log(`Getting commit check runs for ${sha}`);
const statuses = await github.paginate('GET /repos/{owner}/{repo}/commits/{sha}/check-runs', {
owner,
repo,
sha,
headers: {
'X-GitHub-Api-Version': '2022-11-28'
}
});
return statuses;
}
function calculateCheckResult(statuses) {
if(!Array.isArray(statuses)) {
return ['error', 'Failed to retrieve status checks from GitHub ❌', 'statuses is not an array'];
}
const { filtered_statuses, summary } = reduceStatuses(statuses);
return calculateFinalStatus(filtered_statuses, summary);
}
async function test(github, owner, repo, sha) {
// Get statuses from sha
const statuses = await getCommitStatuses(github, owner, repo, sha);
return calculateCheckResult(statuses);
}
async function createCheck(github, owner, repo, sha) {
const check = await github.rest.checks.create({
owner,
repo,
head_sha: sha,
name: 'Build Outcome',
status: 'in_progress',
});
return check.data.id;
}
async function updateCheck(github, owner, repo, checkRunId, status, description, summary) {
const checkStatus = status == 'pending' ? 'in_progress' : 'completed';
const conclusion = checkStatus == 'in_progress' ? undefined : (status == 'success' ? 'success' : 'failure');
await github.rest.checks.update({
owner,
repo,
check_run_id: checkRunId,
status: checkStatus,
conclusion,
output: {
title: description,
summary
}
});
}
const { owner, repo } = context.repo;
const sha =
context.payload?.check_suite?.sha || /* check run completed */
context.payload?.inputs?.commit || /* manual run */
context.payload?.after || /* push */
context.payload?.commit?.sha || /* status */
context.sha; /* probably 'master'! */
const checkRunId = await createCheck(github, owner, repo, sha);
const res = await test(github, owner, repo, sha);
await updateCheck(github, owner, repo, checkRunId, res[0], res[1], res[2]);

View file

@ -29,7 +29,7 @@
function addLog(message) {
console.log(message);
return message + String.fromCharCode(13);
return message + String.fromCharCode(10);
}
function addStatus(o, type, context, state) {