@@ -71,115 +71,132 @@ jobs:
7171 script : |
7272 const fs = require('fs');
7373 const testsPassed = '${{ steps.tests.outcome }}' === 'success';
74-
75- // Build workflow run URL
7674 const runUrl = `https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`;
77-
78- let comment = '';
79-
75+ const COMMENT_MARKER = '<!-- sdk-coverage-report -->';
76+
77+ let lines = [COMMENT_MARKER];
78+
8079 if (!testsPassed) {
81- // Try to parse failed tests from the log
82- let failedTests = '';
80+ let failedTests = [];
8381 try {
8482 const testOutput = fs.readFileSync('test-output.log', 'utf8');
85-
86- // Extract failed test names using regex
8783 const failedMatches = testOutput.match(/● (.+?)(?:\n|$)/g);
88- if (failedMatches && failedMatches.length > 0) {
89- const failedTestList = failedMatches
90- .map(match => match.replace('● ', '').trim())
91- .filter(test => test.length > 0)
92- .slice(0, 10) // Limit to first 10 failures
93- .map(test => `- ${test}`)
94- .join('\n');
95-
96- if (failedTestList) {
97- failedTests = `\n\n**Failed Tests:**\n${failedTestList}`;
98- if (failedMatches.length > 10) {
99- failedTests += `\n- ... and ${failedMatches.length - 10} more`;
100- }
101- }
84+ if (failedMatches) {
85+ failedTests = failedMatches
86+ .map(m => m.replace('● ', '').trim())
87+ .filter(t => t.length > 0)
88+ .slice(0, 10);
10289 }
103- } catch (error) {
104- console.log('Could not read test output:', error.message);
105- }
106-
107- comment = `## ❌ Object Smoke Tests Failed
108-
109- ### Test Results
110- ❌ Some smoke tests failed
111- ${failedTests}
90+ } catch (e) {}
11291
113- **Please fix the failing tests before checking coverage.**
114-
115- [📋 View full test logs](${runUrl})`;
92+ lines.push('## ❌ Object Smoke Tests Failed');
93+ lines.push('');
94+ lines.push('### Test Results');
95+ lines.push('❌ Some smoke tests failed');
96+ if (failedTests.length > 0) {
97+ lines.push('');
98+ lines.push('**Failed Tests:**');
99+ failedTests.forEach(t => lines.push(`- ${t}`));
100+ }
101+ lines.push('');
102+ lines.push('**Please fix the failing tests before checking coverage.**');
103+ lines.push('');
104+ lines.push(`[📋 View full test logs](${runUrl})`);
116105 } else {
117106 let coverageSummary = null;
118107 try {
119108 coverageSummary = JSON.parse(fs.readFileSync('coverage-objects/coverage-summary.json', 'utf8'));
120- } catch (error) {
121- console.log('Coverage summary not found:', error.message);
122- comment = `## ⚠️ Coverage Data Missing
123-
124- ### Test Results
125- ✅ All smoke tests passed
109+ } catch (e) {}
110+
111+ if (!coverageSummary) {
112+ lines.push('## ⚠️ Coverage Data Missing');
113+ lines.push('');
114+ lines.push('### Test Results');
115+ lines.push('✅ All smoke tests passed');
116+ lines.push('');
117+ lines.push('### Coverage Results');
118+ lines.push('⚠️ Coverage data could not be read');
119+ lines.push('');
120+ lines.push(`[📋 View workflow logs](${runUrl})`);
121+ } else {
122+ const total = coverageSummary.total;
123+ const funcs = total.functions.pct;
124+ const lns = total.lines.pct;
125+ const branches = total.branches.pct;
126+ const stmts = total.statements.pct;
127+ const coveragePassed = funcs === 100;
128+ const statusEmoji = coveragePassed ? '✅' : '⚠️';
126129
127- ### Coverage Results
128- ⚠️ Coverage data could not be read
130+ lines.push(`## ${statusEmoji} Object Smoke Tests & Coverage Report`);
131+ lines.push('');
132+ lines.push('### Test Results');
133+ lines.push('✅ All smoke tests passed');
134+ lines.push('');
135+ lines.push('### Coverage Results');
136+ lines.push('| Metric | Coverage | Required | Status |');
137+ lines.push('|--------|----------|----------|--------|');
138+ lines.push(`| **Functions** | **${funcs}%** | **100%** | ${coveragePassed ? '✅' : '❌'} |`);
139+ lines.push(`| Lines | ${lns}% | - | ℹ️ |`);
140+ lines.push(`| Branches | ${branches}% | - | ℹ️ |`);
141+ lines.push(`| Statements | ${stmts}% | - | ℹ️ |`);
142+ lines.push('');
143+ lines.push('**Coverage Requirement:** 100% function coverage (all public methods must be called in smoke tests)');
144+ lines.push('');
145+ lines.push(coveragePassed
146+ ? '✅ All tests passed and all object methods are covered!'
147+ : '⚠️ Some object methods are not covered in smoke tests. Please add tests that call all public methods.');
148+ lines.push('');
149+ lines.push('<details>');
150+ lines.push('<summary>View detailed coverage report</summary>');
151+ lines.push('');
152+ lines.push('| File | Functions | Lines | Branches |');
153+ lines.push('|------|-----------|-------|----------|');
129154
130- [📋 View workflow logs](${runUrl})`;
155+ for (const [filePath, data] of Object.entries(coverageSummary)) {
156+ if (filePath === 'total') continue;
157+ const shortPath = filePath.replace(/^.*?src\//, 'src/');
158+ const funcPct = data.functions.pct;
159+ const linesPct = data.lines.pct;
160+ const branchesPct = data.branches.pct;
161+ const funcStatus = funcPct === 100 ? '✅' : '❌';
162+ lines.push(`| ${shortPath} | ${funcStatus} ${funcPct}% | ${linesPct}% | ${branchesPct}% |`);
163+ }
131164
132- github.rest.issues.createComment({
133- issue_number: context.issue.number,
134- owner: context.repo.owner,
135- repo: context.repo.repo,
136- body: comment
137- });
138- return;
165+ lines.push('');
166+ lines.push('</details>');
167+ lines.push('');
168+ lines.push(`[📋 View workflow run](${runUrl})`);
139169 }
140-
141- const total = coverageSummary.total;
142- const functions = total.functions.pct;
143- const lines = total.lines.pct;
144- const branches = total.branches.pct;
145- const statements = total.statements.pct;
146-
147- const coveragePassed = functions === 100;
148- const allPassed = testsPassed && coveragePassed;
149- const statusEmoji = allPassed ? '✅' : '⚠️';
150-
151- comment = `## ${statusEmoji} Object Smoke Tests & Coverage Report
152-
153- ### Test Results
154- ✅ All smoke tests passed
155-
156- ### Coverage Results
157- | Metric | Coverage | Required | Status |
158- |--------|----------|----------|--------|
159- | **Functions** | **${functions}%** | **100%** | ${coveragePassed ? '✅' : '❌'} |
160- | Lines | ${lines}% | - | ℹ️ |
161- | Branches | ${branches}% | - | ℹ️ |
162- | Statements | ${statements}% | - | ℹ️ |
163-
164- **Coverage Requirement:** 100% function coverage (all public methods must be called in smoke tests)
165-
166- ${coveragePassed
167- ? '✅ All tests passed and all object methods are covered!'
168- : '⚠️ Some object methods are not covered in smoke tests. Please add tests that call all public methods.'}
169-
170- <details>
171- <summary>View detailed coverage report</summary>
172-
173- Coverage reports are available in the workflow artifacts. Lines/branches/statements coverage is tracked but not required to be 100%.
174-
175- </details>
176-
177- [📋 View workflow run](${runUrl})`;
178170 }
179-
180- github.rest.issues.createComment({
181- issue_number: context.issue.number,
171+
172+ const comment = lines.join('\n');
173+
174+ const { data: comments } = await github.rest.issues.listComments({
182175 owner: context.repo.owner,
183176 repo: context.repo.repo,
184- body: comment
177+ issue_number: context.issue.number
185178 });
179+
180+ const existingComment = comments.find(c => c.body.includes(COMMENT_MARKER));
181+
182+ if (existingComment) {
183+ await github.rest.issues.updateComment({
184+ owner: context.repo.owner,
185+ repo: context.repo.repo,
186+ comment_id: existingComment.id,
187+ body: comment
188+ });
189+ } else {
190+ await github.rest.issues.createComment({
191+ issue_number: context.issue.number,
192+ owner: context.repo.owner,
193+ repo: context.repo.repo,
194+ body: comment
195+ });
196+ }
197+
198+ - name : Fail if tests failed
199+ if : steps.tests.outcome != 'success'
200+ run : |
201+ echo "Smoke tests failed. See PR comment for details."
202+ exit 1
0 commit comments