Skip to content

ci: workflow to add comment for e2e test changes #4

ci: workflow to add comment for e2e test changes

ci: workflow to add comment for e2e test changes #4

name: "E2E PR Checklist"
on:
pull_request:
types: [opened, synchronize]
paths:
- "e2e/**"
permissions:
pull-requests: read
contents: read
jobs:
add-e2e-checklist:
name: "Add E2E Checklist"
runs-on: ubuntu-latest
permissions:
pull-requests: write
steps:
- name: Detect changed E2E platforms
id: detect
uses: actions/github-script@v7
with:
script: |
const { data: files } = await github.rest.pulls.listFiles({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.issue.number,
per_page: 100
});
const desktop = files.some(f => f.filename.startsWith('e2e/desktop/'));
const mobile = files.some(f => f.filename.startsWith('e2e/mobile/'));
core.setOutput('desktop', desktop.toString());
core.setOutput('mobile', mobile.toString());
- name: Add E2E checklist comment
uses: actions/github-script@v7
env:
CHANGED_DESKTOP: ${{ steps.detect.outputs.desktop }}
CHANGED_MOBILE: ${{ steps.detect.outputs.mobile }}
with:
script: |
const desktopChanged = process.env.CHANGED_DESKTOP === 'true';
const mobileChanged = process.env.CHANGED_MOBILE === 'true';
const platformLabel = desktopChanged && mobileChanged
? 'Desktop & Mobile'
: desktopChanged ? 'Desktop' : 'Mobile';
// Build device table with checkboxes and proof link columns per platform
const header = ['Device'];
const separator = ['--------'];
if (desktopChanged) {
header.push('Desktop', 'Proof (Desktop)');
separator.push(':-------:', '---');
}
if (mobileChanged) {
header.push('Mobile', 'Proof (Mobile)');
separator.push(':------:', '---');
}
const devices = ['nanoS', 'nanoSP', 'nanoX', 'stax', 'flex', 'nanoGen5'];
const rows = devices.map(device => {
const cols = [`| ${device}`];
if (desktopChanged) cols.push('🔲', '_paste link_');
if (mobileChanged) cols.push('🔲', '_paste link_');
return cols.join(' | ') + ' |';
});
const deviceTable = [
'| ' + header.join(' | ') + ' |',
'| ' + separator.join(' | ') + ' |',
...rows
].join('\n');
// Build workflow trigger instructions
const workflowLinks = [];
if (desktopChanged) {
workflowLinks.push('- **Desktop:** Trigger [`test-ui-e2e-only-desktop.yml`](../actions/workflows/test-ui-e2e-only-desktop.yml) with `test_filter` set to your test name/tag');
}
if (mobileChanged) {
workflowLinks.push('- **Mobile:** Trigger [`test-mobile-e2e-reusable.yml`](../actions/workflows/test-mobile-e2e-reusable.yml) with `test_filter` set to your test name/tag');
}
const e2eChecklist = `## 🧪 E2E Test Checklist — ${platformLabel}
> This checklist was added automatically because your PR touches \`e2e/\` files.
### General
- [ ] Tests pass locally before pushing
- [ ] No \`.only\` or \`.skip\` left in test files (unless intentional and documented)
- [ ] Tests are independent and can run in any order
### Test Quality
- [ ] Page Object Model (POM) pattern is followed for new pages/components
- [ ] Appropriate device tags are added: \`@NanoSP\`, \`@NanoX\`, \`@Stax\`, \`@Flex\`, \`@NanoGen5\`
- [ ] Family tags are added where applicable: \`@family-evm\`, \`@family-bitcoin\`, etc.
- [ ] \`@smoke\` tag added for critical path tests (if applicable)
- [ ] TMS/Xray ticket IDs are linked in test annotations (e.g., \`B2CQA-XXXX\`)
### Device Coverage (Required for new/updated tests)
Run your tests on **all supported devices** using the E2E workflow(s):
${workflowLinks.join('\n')}
${deviceTable}
> 💡 Use \`workflow_dispatch\` to trigger the workflow manually on your branch. Set the \`speculos_device\` input to test each device. Edit the table: replace 🔲 with ✅ (passed) or ❌ (failed), and replace *paste link* with a link to the workflow run or Allure report.
`;
// Paginate through all comments to reliably find an existing bot comment
const marker = '## 🧪 E2E Test Checklist';
let botComment = null;
for await (const { data: comments } of github.paginate.iterator(
github.rest.issues.listComments,
{ owner: context.repo.owner, repo: context.repo.repo, issue_number: context.issue.number, per_page: 100 }
)) {
botComment = comments.find(c => c.user.type === 'Bot' && c.body.includes(marker));
if (botComment) break;
}
if (!botComment) {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: e2eChecklist
});
console.log(`E2E checklist comment added (${platformLabel})`);
} else {
// Update existing comment if platforms changed (e.g., mobile added after desktop-only)
if (!botComment.body.includes(platformLabel)) {
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: botComment.id,
body: e2eChecklist
});
console.log(`E2E checklist comment updated to ${platformLabel}`);
} else {
console.log('E2E checklist comment already exists and is up to date, skipping');
}
}