Skip to content

CI Comment

CI Comment #1680

Workflow file for this run

name: CI Comment
on:
workflow_run:
workflows: ["CI"]
types:
- completed
jobs:
ci-comment:
name: Update PR body
if: >
${{ github.event.workflow_run.event == 'pull_request' &&
github.event.workflow_run.conclusion == 'success' }}
runs-on: ubuntu-latest
env:
OPAMSOLVERTIMEOUT: 3600
SNAPSHOT: "snapshot-${{ matrix.snapshot }}"
steps:
- name: Checkout code (10 commits)
uses: actions/checkout@v2
with:
fetch-depth: 10
submodules: true
- name: 'Download artifact'
uses: actions/github-script@v3.1.0
with:
script: |
const artifacts = await github.actions.listWorkflowRunArtifacts({
owner: context.repo.owner,
repo: context.repo.repo,
run_id: ${{github.event.workflow_run.id }},
});
const fs = require('fs');
const matchedArtifacts = artifacts.data.artifacts.filter((artifact) => {
return artifact.name.startsWith('pr');
});
for await (const artifact of matchedArtifacts) {
console.log('download artifact', artifact);
const download = await github.actions.downloadArtifact({
owner: context.repo.owner,
repo: context.repo.repo,
artifact_id: artifact.id,
archive_format: 'zip',
});
fs.writeFileSync(`${{github.workspace}}/pr-${artifact.id}.zip`, Buffer.from(download.data));
}
- name: Extract
run: |
shopt -s nullglob
for file in *.zip ; do
unzip "$file" -d "${file%.zip}"
done
for f in pr-*/comment.txt ; do
echo "# $f"
cat "$f"
done
- name: Update the PR body
uses: actions/github-script@v2
env:
SNAPSHOT_UPDATABLE: ${{ steps.test-update-snapshot.outputs.result }}
PACKAGES_TO_UPDATE: ${{ steps.test-update-snapshot.outputs.packages }}
with:
github-token: ${{ github.token }}
script: |
const fs = require('fs');
const dir = await fs.promises.opendir('.');
const snapshots = [];
const readFile = (fileName, d) => {
try {
return fs.readFileSync(fileName, 'utf8').trim();
} catch (e) {
console.log(e);
return d;
}
};
for await (const dirent of dir) {
if (dirent.isDirectory() && dirent.name.startsWith('pr-')) {
const dirname = dirent.name;
if (!fs.existsSync(`${dirname}/pull-number.txt`)) {
continue;
}
const pull_number = Number(fs.readFileSync(`${dirname}/pull-number.txt`, 'utf8'));
const run_id = Number(fs.readFileSync(`${dirname}/run-id.txt`, 'utf8'));
const snapshot = fs.readFileSync(`${dirname}/id.txt`, 'utf8').trim();
const matrix = fs.readFileSync(`${dirname}/matrix.txt`, 'utf8').trim();
const result = readFile(`${dirname}/result.txt`, undefined);
const packages = readFile(`${dirname}/packages.txt`, 'unknown');
const comment = readFile(`${dirname}/comment.txt`, undefined);
snapshots.push({pull_number, run_id, snapshot, matrix, result, packages, comment});
}
}
console.log('snapshots', snapshots);
if (snapshots.length === 0) {
console.log('No artifacts read');
return;
}
const pull_number = snapshots[0].pull_number;
const pullRequestId = {
owner: context.repo.owner,
repo: context.repo.repo,
pull_number
};
const pull_request = await github.pulls.get(pullRequestId);
const actionHeader = '\n# Automatic follow-ups\n';
const actionText = (snapshot) => `Add to snapshot \`${snapshot}\``;
const body = pull_request.data.body.replace(/\r?\n/g, '\n');
const extractAction = (str) =>
str.replace(/^\[.\] /, "")
.replace(/ :: .*/, "")
.replace(/^~~(.*)~~.*/, "$1");
if (body) {
const splitted = body.split(actionHeader);
const actions = splitted[1]
? splitted[1]
.split('\n- ')
.map((action) => {
for (snapshot of snapshots) {
console.log('action', action, actionText(snapshot.snapshot), snapshot);
const extractedAction = extractAction(action);
if (extractedAction === actionText(snapshot.snapshot)) {
switch (snapshot.result) {
case 'updated':
return `[ ] ${extractedAction} :: ${snapshot.packages}`;
case 'no-updates':
return `~~${extractedAction}~~ (No updates)`;
case 'failed':
// return `~~${extractedAction}~~ ([Inconsistent](https://github.com/${context.repo.owner}/${context.repo.repo}/runs/${snapshot.run_id}?check_suite_focus=true))`;
return `~~${extractedAction}~~ (Inconsistent)`;
case 'unknown':
return `~~${extractedAction}~~ (Result unknown)`;
default:
if (snapshot.result.startsWith('inconsistent-snapshot ')) {
return `~~${extractedAction}~~ (${snapshot.result})`;
}
return `~~${extractedAction}~~ (Result unknown)`;
}
}
}
return action;
})
: [];
const replacedBody = `${splitted[0]}${actionHeader}${actions.join('\n- ')}`;
await github.pulls.update({
...pullRequestId,
body: replacedBody
});
}
const comments = [
'# CI Summary'
];
for (snapshot of snapshots) {
if (snapshot.comment) {
comments.push(`## Matrix: ${snapshot.matrix}`);
comments.push(snapshot.comment);
}
}
if (comments.length) {
await github.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: pull_number,
body: comments.join('\n')
});
}