Feature: Entity Framework Core provider (BLite.EntityFrameworkCore) #1
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Issue Pre-check | |
| on: | |
| issues: | |
| types: [opened, reopened] | |
| permissions: | |
| issues: write | |
| jobs: | |
| precheck: | |
| # Only run on real issues, not PRs converted to issues | |
| if: github.event.issue.pull_request == null | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Validate and label issue | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const body = context.payload.issue.body ?? ''; | |
| const labels = []; | |
| const problems = []; | |
| // ── Helpers ──────────────────────────────────────────────────────── | |
| /** Extract the content of a ### Section from the issue body. */ | |
| function section(heading) { | |
| const re = new RegExp( | |
| `###\\s+${heading.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\s*\\n([\\s\\S]*?)(?=\\n###|$)`, | |
| 'i' | |
| ); | |
| const m = body.match(re); | |
| return m ? m[1].trim() : ''; | |
| } | |
| const PLACEHOLDER_RE = [ | |
| /^e\.g\./i, | |
| /\/\/\s*paste your minimal repro here/i, | |
| /\/\/\s*appsettings\.json snippet/i, | |
| /\/\/\s*client code or test/i, | |
| ]; | |
| function isPlaceholder(text) { | |
| return PLACEHOLDER_RE.some(re => re.test(text)); | |
| } | |
| // ── Only validate bug reports (they have a "Minimal reproduction" section) ── | |
| const isBugReport = body.includes('### Minimal reproduction'); | |
| if (!isBugReport) { | |
| // Feature requests get a simple triage label | |
| await github.rest.issues.addLabels({ | |
| ...context.repo, | |
| issue_number: context.issue.number, | |
| labels: ['triage'], | |
| }); | |
| return; | |
| } | |
| // ── Field checks ─────────────────────────────────────────────────── | |
| const version = section('BLite.Server version'); | |
| if (!version || isPlaceholder(version)) { | |
| problems.push('**BLite.Server version** — missing or still contains the placeholder (e.g. `1.2.3`).'); | |
| } | |
| const dotnet = section('.NET version'); | |
| if (!dotnet || isPlaceholder(dotnet)) { | |
| problems.push('**\\.NET version** — missing or still contains the placeholder.'); | |
| } | |
| const os = section('Operating system'); | |
| if (!os || isPlaceholder(os)) { | |
| problems.push('**Operating system** — missing or still contains the placeholder.'); | |
| } | |
| const description = section('Description'); | |
| if (!description || description.length < 15) { | |
| problems.push('**Description** — too short or missing.'); | |
| } | |
| const repro = section('Minimal reproduction'); | |
| if (!repro || repro.length < 30 || isPlaceholder(repro)) { | |
| problems.push('**Minimal reproduction** — missing or appears to be just the placeholder. Please provide a small, self-contained snippet (config + client code or curl request).'); | |
| } | |
| const expected = section('Expected behavior'); | |
| if (!expected || expected.length < 10) { | |
| problems.push('**Expected behavior** — missing or too short.'); | |
| } | |
| const actual = section('Actual behavior'); | |
| if (!actual || actual.length < 10) { | |
| problems.push('**Actual behavior** — missing or too short.'); | |
| } | |
| // ── Auto-label by Affected area ──────────────────────────────────── | |
| const area = section('Affected area').toLowerCase(); | |
| const areaMap = { | |
| 'grpc': 'area/grpc', | |
| 'rest api': 'area/rest', | |
| 'blazor studio': 'area/studio', | |
| 'authentication': 'area/auth', | |
| 'transaction': 'area/transactions', | |
| 'configuration': 'area/config', | |
| }; | |
| for (const [key, label] of Object.entries(areaMap)) { | |
| if (area.includes(key)) { labels.push(label); break; } | |
| } | |
| // ── Status label ─────────────────────────────────────────────────── | |
| labels.push(problems.length > 0 ? 'incomplete' : 'triage'); | |
| // ── Create labels (best-effort, ignore if they already exist) ────── | |
| const labelDefs = { | |
| 'incomplete': { color: 'e11d48', description: 'Issue is missing required information' }, | |
| 'triage': { color: '0ea5e9', description: 'Needs triage by a maintainer' }, | |
| 'area/grpc': { color: '7c3aed', description: 'Affects the gRPC layer' }, | |
| 'area/rest': { color: '7c3aed', description: 'Affects the REST API' }, | |
| 'area/studio': { color: '7c3aed', description: 'Affects the Blazor Studio' }, | |
| 'area/auth': { color: '7c3aed', description: 'Affects authentication or authorization' }, | |
| 'area/transactions': { color: '7c3aed', description: 'Affects the transaction manager' }, | |
| 'area/config': { color: '7c3aed', description: 'Affects configuration or startup' }, | |
| }; | |
| for (const label of labels) { | |
| if (labelDefs[label]) { | |
| try { | |
| await github.rest.issues.createLabel({ | |
| ...context.repo, | |
| name: label, | |
| ...labelDefs[label], | |
| }); | |
| } catch (_) { /* already exists */ } | |
| } | |
| } | |
| await github.rest.issues.addLabels({ | |
| ...context.repo, | |
| issue_number: context.issue.number, | |
| labels, | |
| }); | |
| // ── Comment ──────────────────────────────────────────────────────── | |
| if (problems.length > 0) { | |
| const list = problems.map(p => `- ${p}`).join('\n'); | |
| await github.rest.issues.createComment({ | |
| ...context.repo, | |
| issue_number: context.issue.number, | |
| body: [ | |
| ':wave: Thanks for opening this issue!', | |
| '', | |
| 'It looks like some required information is missing or incomplete:', | |
| '', | |
| list, | |
| '', | |
| 'Please **edit the issue** and fill in all the missing sections.', | |
| 'We will start the investigation once the issue is complete.', | |
| ].join('\n'), | |
| }); | |
| } else { | |
| await github.rest.issues.createComment({ | |
| ...context.repo, | |
| issue_number: context.issue.number, | |
| body: ':wave: Thanks for the well-formed bug report! It has been added to the triage queue.', | |
| }); | |
| } |