Skip to content

Fix empty candlesticks on ios #41

Fix empty candlesticks on ios

Fix empty candlesticks on ios #41

name: PR Checklist Validator
on:
pull_request:
types: [opened, edited, synchronize, reopened]
jobs:
validate-checklist:
runs-on: ubuntu-latest
name: Validate PR Checklist
steps:
- name: Check PR Checklist
uses: actions/github-script@v7
with:
script: |
const prBody = context.payload.pull_request.body || '';
// Find all checkboxes in the PR body
const checkboxRegex = /- \[([ xX])\]/g;
const checkboxes = [...prBody.matchAll(checkboxRegex)];
if (checkboxes.length === 0) {
core.setFailed('❌ No checkboxes found in PR description. Please use the PR template.');
return;
}
// Count checked and unchecked boxes
const totalBoxes = checkboxes.length;
const checkedBoxes = checkboxes.filter(match =>
match[1].toLowerCase() === 'x'
).length;
const uncheckedBoxes = totalBoxes - checkedBoxes;
// Check for Linear URL/ticket
const linearRegex = /\*\*Linear ticket:\*\*[ \t]*([^\n]+)/i;
const linearMatch = prBody.match(linearRegex);
let linearError = null;
if (!linearMatch) {
linearError = '❌ Linear ticket field not found in PR description';
} else {
const linearValue = linearMatch[1].trim();
// Check if it's still the placeholder or empty
if (!linearValue || linearValue === 'PRO-XXX' || linearValue === '') {
linearError = '❌ Linear ticket is not filled out (still showing placeholder "PRO-XXX")';
} else {
// Validate format: should be either a ticket ID (e.g., PRO-123) or a full Linear URL
const validLinearPattern = /^(?:https?:\/\/linear\.app\/[^\s]+|[A-Z]+-\d+)$/;
if (!validLinearPattern.test(linearValue)) {
linearError = `❌ Linear ticket format is invalid: "${linearValue}" (expected format: PRO-123 or https://linear.app/...)`;
}
}
}
// Create a summary
core.summary
.addHeading('PR Checklist Validation Results')
.addRaw(`Total checkboxes: ${totalBoxes}`)
.addRaw(`\nChecked: ✅ ${checkedBoxes}`)
.addRaw(`\nUnchecked: ❌ ${uncheckedBoxes}`)
.addRaw(`\nLinear ticket: ${linearError ? '❌ Invalid' : '✅ Valid'}`)
.write();
// Log the results
console.log(`Total checkboxes: ${totalBoxes}`);
console.log(`Checked: ${checkedBoxes}`);
console.log(`Unchecked: ${uncheckedBoxes}`);
console.log(`Linear validation: ${linearError || 'Valid'}`);
// Collect all errors
const errors = [];
if (uncheckedBoxes > 0) {
errors.push(
`📊 Status: ${checkedBoxes}/${totalBoxes} items checked\n` +
`⚠️ Please check all ${uncheckedBoxes} remaining checkbox(es) in the PR description before merging.`
);
}
if (linearError) {
errors.push(`🔗 ${linearError}\n⚠️ Please add a valid Linear ticket (e.g., PRO-123 or full Linear URL).`);
}
// Fail if there are any errors
if (errors.length > 0) {
core.setFailed(
`❌ PR validation failed!\n\n` +
errors.join('\n\n') +
`\n\n💡 Tip: Review each section carefully and ensure all requirements are met.`
);
} else {
console.log('✅ All checklist items are complete!');
core.notice('✅ All checklist items are complete! PR is ready for review.');
}
- name: Comment on PR (if incomplete)
if: failure()
uses: actions/github-script@v7
with:
script: |
const prBody = context.payload.pull_request.body || '';
const checkboxes = [...prBody.matchAll(/- \[([ xX])\]/g)];
const totalBoxes = checkboxes.length;
const checkedBoxes = checkboxes.filter(match =>
match[1].toLowerCase() === 'x'
).length;
const uncheckedBoxes = totalBoxes - checkedBoxes;
// Check Linear ticket
const linearRegex = /\*\*Linear ticket:\*\*[ \t]*([^\n]+)/i;
const linearMatch = prBody.match(linearRegex);
let linearError = null;
if (!linearMatch) {
linearError = 'Linear ticket field not found';
} else {
const linearValue = linearMatch[1].trim();
if (!linearValue || linearValue === 'PRO-XXX' || linearValue === '') {
linearError = 'Linear ticket is still showing placeholder "PRO-XXX"';
} else {
const validLinearPattern = /^(?:https?:\/\/linear\.app\/[^\s]+|[A-Z]+-\d+)$/;
if (!validLinearPattern.test(linearValue)) {
linearError = `Linear ticket format is invalid: "${linearValue}"`;
}
}
}
// Check if we already commented
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.payload.pull_request.number,
});
const botComment = comments.find(comment =>
comment.user && comment.user.type === 'Bot' &&
comment.body.includes('PR Checklist Validation')
);
const issues = [];
if (totalBoxes === 0) {
issues.push(`- ❌ **Checklist:** No checkboxes found. Please use the PR template.`);
} else if (uncheckedBoxes > 0) {
issues.push(`- ❌ **Checklist:** ${checkedBoxes}/${totalBoxes} items checked (${uncheckedBoxes} remaining)`);
}
if (linearError) {
issues.push(`- ❌ **Linear ticket:** ${linearError}`);
}
// Build steps dynamically with correct numbering
let stepNum = 1;
const steps = [`${stepNum++}. Review the PR description`];
if (totalBoxes === 0) {
steps.push(`${stepNum++}. Use the PR template to add the required checklist`);
} else if (uncheckedBoxes > 0) {
steps.push(`${stepNum++}. Check all applicable boxes (\`- [x]\`)`);
steps.push(`${stepNum++}. If an item doesn't apply, check it and add a note explaining why`);
}
if (linearError) {
steps.push(`${stepNum++}. Add a valid Linear ticket (format: \`PRO-123\` or \`https://linear.app/...\`)`);
}
steps.push(`${stepNum}. Push an update or edit the PR description to re-trigger this check`);
const commentBody = [
'## 📋 PR Checklist Validation Failed',
'',
'⚠️ This PR cannot be merged until the following issues are resolved:',
'',
...issues,
'',
'### What to do:',
...steps,
'',
'---',
'*This check ensures all PR requirements are met before merging. If you believe this check should not apply to your PR, please discuss with the team.*'
].join('\n');
if (botComment) {
// Update existing comment
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: botComment.id,
body: commentBody
});
} else {
// Create new comment
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.payload.pull_request.number,
body: commentBody
});
}
- name: Comment on PR (if complete)
if: success()
uses: actions/github-script@v7
with:
script: |
const prBody = context.payload.pull_request.body || '';
const checkboxes = [...prBody.matchAll(/- \[([ xX])\]/g)];
const totalBoxes = checkboxes.length;
const checkedBoxes = checkboxes.filter(match =>
match[1].toLowerCase() === 'x'
).length;
// Check if we already commented
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.payload.pull_request.number,
});
const botComment = comments.find(comment =>
comment.user && comment.user.type === 'Bot' &&
comment.body.includes('PR Checklist Validation')
);
const commentBody = [
'## ✅ PR Checklist Validation Passed',
'',
`**Status:** All ${totalBoxes} checklist items completed`,
'**Linear ticket:** Valid ✅',
'',
'🎉 This PR meets all requirements and is ready for review!',
'',
'---',
'*This validation ensures all PR requirements are met before merging.*'
].join('\n');
if (botComment) {
// Update existing comment with success message
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: botComment.id,
body: commentBody
});
} else {
// Create new success comment
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.payload.pull_request.number,
body: commentBody
});
}