diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cc60ebb..9b41025 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,6 +14,8 @@ jobs: permissions: contents: read + checks: write + pull-requests: write steps: - uses: actions/checkout@v4 @@ -33,6 +35,28 @@ jobs: run: npm test working-directory: create-github-app-token + - name: Publish Test Results + uses: dorny/test-reporter@dc3a92680fcc15842eef52e8c4606ea7ce6bd3f3 # v2.1.1 + if: success() || failure() + with: + name: Jest Tests + path: create-github-app-token/test-results/junit.xml + reporter: jest-junit + fail-on-error: true + use-actions-summary: true + + - name: Publish Code Coverage Results + uses: 5monkeys/cobertura-action@ee5787cc56634acddedc51f21c7947985531e6eb # v14 + if: success() || failure() + with: + path: create-github-app-token/coverage/cobertura-coverage.xml + minimum_coverage: 80 + fail_below_threshold: false + show_line: true + show_branch: true + show_class_names: true + only_changed_files: false + - name: Build run: npm run build working-directory: create-github-app-token diff --git a/.gitignore b/.gitignore index 5d8f313..5a3175e 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,7 @@ lib *.pem .taskkey -coverage/ \ No newline at end of file +coverage/ + +# Test results +test-results/ \ No newline at end of file diff --git a/README.md b/README.md index 7e90de2..f604b57 100644 --- a/README.md +++ b/README.md @@ -223,7 +223,25 @@ For comprehensive guidance, refer to the [official Microsoft documentation on cr Both GitHub Actions as well as Azure Pipelines are provided to execute continuous integration. (they are triggered by either a pull request or a push against the `main` branch). -The CI Action packages the extension and uploads it as an artifact, the extension is packaged as `ENTER YOUR PUBLISHER HERE` publisher. You should use your own publisher by setting a variable with the name `PUBLISHER` on the CI pipeline. +The CI workflows include the following features: + +- **Build and Test**: Compile TypeScript, run unit tests, and package the extension +- **Unit Test Results**: Both CI systems are configured to publish unit test results: + - **GitHub Actions**: Uses `dorny/test-reporter` to publish test results as pull request comments with detailed test summaries + - **Azure Pipelines**: Uses `PublishTestResults@2` task to display test results in the pipeline run with integrated reporting +- **Code Coverage Results**: Both CI systems are configured to publish code coverage reports: + - **GitHub Actions**: Uses `5monkeys/cobertura-action` to publish coverage results as pull request comments with coverage summaries and line-by-line coverage information + - **Azure Pipelines**: Uses `PublishCodeCoverageResults@1` task to display coverage results in the pipeline run with detailed coverage reports +- **Test and Coverage Configuration**: Jest is configured with: + - JUnit XML reporting (`jest-junit`) for standardized test result files + - Multiple coverage formats including Cobertura XML for CI integration and HTML reports for local viewing + - Coverage thresholds set at 80% for branches, functions, lines, and statements +- **Artifact Publishing**: The extension is packaged and uploaded as an artifact + +The extension is packaged as `ENTER YOUR PUBLISHER HERE` publisher. You should use your own publisher by setting a variable with the name `PUBLISHER` on the CI pipeline. + +> [!NOTE] +> Test results and code coverage reports are published even if tests fail, providing visibility into both test outcomes and coverage metrics for successful and failing builds. ## Contributing diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 523823b..091d5c4 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -23,9 +23,27 @@ steps: displayName: 'Install dependencies' workingDirectory: create-github-app-token -- script: npm test - displayName: 'Run unit tests' - workingDirectory: create-github-app-token +- script: npm test + displayName: 'Run unit tests' + workingDirectory: create-github-app-token + +- task: PublishTestResults@2 + displayName: 'Publish Test Results' + condition: succeededOrFailed() # publish results even if tests failed + inputs: + testResultsFormat: 'JUnit' + testResultsFiles: 'create-github-app-token/test-results/junit.xml' + testRunTitle: 'Jest Unit Tests' + publishRunAttachments: true + +- task: PublishCodeCoverageResults@1 + displayName: 'Publish Code Coverage Results' + condition: succeededOrFailed() # publish results even if tests failed + inputs: + codeCoverageTool: 'Cobertura' + summaryFileLocation: 'create-github-app-token/coverage/cobertura-coverage.xml' + reportDirectory: 'create-github-app-token/coverage/lcov-report' + failIfCoverageEmpty: false - script: | npm run clean diff --git a/create-github-app-token/jest.config.js b/create-github-app-token/jest.config.js index 128c5b2..6dd97b0 100644 --- a/create-github-app-token/jest.config.js +++ b/create-github-app-token/jest.config.js @@ -9,7 +9,21 @@ module.exports = { '!**/node_modules/**' ], coverageDirectory: 'coverage', - coverageReporters: ['text', 'text-summary', 'lcov', 'html', 'json'], + coverageReporters: ['text', 'text-summary', 'lcov', 'html', 'json', 'cobertura'], + + // JUnit XML reporting for CI systems + reporters: [ + 'default', + ['jest-junit', { + outputDirectory: 'test-results', + outputName: 'junit.xml', + ancestorSeparator: ' › ', + uniqueOutputName: 'false', + suiteNameTemplate: '{filepath}', + classNameTemplate: '{classname}', + titleTemplate: '{title}' + }] + ], coveragePathIgnorePatterns: [ '/node_modules/', '/test/', diff --git a/create-github-app-token/package-lock.json b/create-github-app-token/package-lock.json index 04c47aa..05bea7f 100644 --- a/create-github-app-token/package-lock.json +++ b/create-github-app-token/package-lock.json @@ -24,6 +24,7 @@ "@vercel/ncc": "^0.38.3", "jest": "^29.7.0", "jest-environment-node": "^29.7.0", + "jest-junit": "^16.0.0", "nock": "^13.5.1", "ts-jest": "^29.1.1", "typescript": "^5.8.2" @@ -2836,6 +2837,32 @@ "fsevents": "^2.3.2" } }, + "node_modules/jest-junit": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/jest-junit/-/jest-junit-16.0.0.tgz", + "integrity": "sha512-A94mmw6NfJab4Fg/BlvVOUXzXgF0XIH6EmTgJ5NDPp4xoKq0Kr7sErb+4Xs9nZvu58pJojz5RFGpqnZYJTrRfQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "mkdirp": "^1.0.4", + "strip-ansi": "^6.0.1", + "uuid": "^8.3.2", + "xml": "^1.0.1" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/jest-junit/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true, + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/jest-leak-detector": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", @@ -3512,6 +3539,19 @@ "node": "*" } }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -4469,6 +4509,13 @@ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, + "node_modules/xml": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz", + "integrity": "sha512-huCv9IH9Tcf95zuYCsQraZtWnJvBtLVE0QHMOs8bWyZAFZNDcYjsPq1nEx8jKA9y+Beo9v+7OBPRisQTjinQMw==", + "dev": true, + "license": "MIT" + }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", diff --git a/create-github-app-token/package.json b/create-github-app-token/package.json index 80743fe..67372cf 100644 --- a/create-github-app-token/package.json +++ b/create-github-app-token/package.json @@ -23,12 +23,13 @@ "devDependencies": { "@types/jest": "^29.5.12", "@types/jsonwebtoken": "^9.0.5", - "@types/node": "^18.*", "@types/nock": "^11.1.0", + "@types/node": "^18.*", "@types/q": "^1.5.8", "@vercel/ncc": "^0.38.3", "jest": "^29.7.0", "jest-environment-node": "^29.7.0", + "jest-junit": "^16.0.0", "nock": "^13.5.1", "ts-jest": "^29.1.1", "typescript": "^5.8.2"