diff --git a/.github/workflows/pull-request-check.yaml b/.github/workflows/pull-request-check.yaml index 4105c107..faefaac8 100644 --- a/.github/workflows/pull-request-check.yaml +++ b/.github/workflows/pull-request-check.yaml @@ -1,6 +1,6 @@ name: Pull Request Check -on: [ pull_request ] +on: [pull_request] concurrency: group: pull-request-check-${{ github.event.pull_request.number }} @@ -134,13 +134,53 @@ jobs: - uses: yumemi-inc/setup-java-gradle@v3 with: cache-read-only: false - - run: ./gradlew test - - uses: yumemi-inc/comment-pull-request@v1 + - run: ./gradlew test --continue + - uses: actions/github-script@v7 + if: ${{ !cancelled() }} + with: + script: require("${{ github.workspace }}/.github/workflows/unit-test-top-html.js").createTopHtml() + - uses: actions/upload-artifact@v4 + if: ${{ !cancelled() }} + with: + name: "unit-test-reports" + path: | + build/build-outputs/unit-test-report + + report-unit-test: + needs: [unit-test] + if: ${{ !failure() }} + runs-on: ubuntu-latest + permissions: + contents: write # for peaceiris/actions-gh-pages + pull-requests: write # for yumemi-inc/comment-pull-request + concurrency: + group: pages + cancel-in-progress: false + steps: + - uses: actions/download-artifact@v4 + with: + name: "unit-test-reports" + path: build/build-outputs/unit-test-report + - uses: peaceiris/actions-gh-pages@v4 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: build/build-outputs/unit-test-report + destination_dir: ./pr/${{ github.event.pull_request.number }}/unit-test/ + keep_files: true + - id: get-outputs + run: | + owner_name=${{ github.repository_owner }} + repo_name=$(echo ${{ github.repository }} | cut -d'/' -f2) + pages_url="https://$owner_name.github.io/$repo_name/pr/${{ github.event.pull_request.number }}/unit-test/" + echo "pages_url=$pages_url" >> $GITHUB_OUTPUT + - name: Comment Pull Request + uses: yumemi-inc/comment-pull-request@v1 if: cancelled() != true with: - comment-if-failure: | + comment: | > [!CAUTION] - > There was a problem with the **Unit Test** check. See details [here](${{ env.LOG_URL }}). + > There was a problem with the **Unit Test** check. See details [here](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}). + > Or check test report from [here](${{ steps.get-outputs.outputs.pages_url }}). build: runs-on: ubuntu-latest diff --git a/.github/workflows/unit-test-top-html.js b/.github/workflows/unit-test-top-html.js new file mode 100644 index 00000000..3a683b7e --- /dev/null +++ b/.github/workflows/unit-test-top-html.js @@ -0,0 +1,103 @@ +import * as fs from "node:fs" +import * as path from "node:path" + +export const createTopHtml = () => { + const testReportDir = 'build/build-outputs/unit-test-report'; + const outputFile = path.join(testReportDir, 'index.html'); + + function generateHTML(files) { + // ファイルパスをディレクトリ構造に変換 + const structure = {}; + for (const file of files) { + const relativePath = path.relative(testReportDir, file); + const dirPath = path.dirname(relativePath); + const parts = dirPath.split(path.sep); + let current = structure; + + for (const [index, part] of parts.entries()) { + if (index === parts.length - 1) { + current[part] = dirPath; + } else { + if (!current[part]) { + current[part] = {}; + } + current = current[part]; + } + } + } + + // ディレクトリ構造をHTMLに変換 + function generateList(items) { + if (typeof items === 'string') { + return `
  • ${path.basename(items)}
  • `; + } + + return Object.entries(items).map(([key, value]) => { + if (typeof value === 'string') { + return `
  • ${path.basename(value)}
  • `; + } + return `
  • ${key}
  • `; + }).join('\n'); + } + + const html = ` + + + Unit Test Reports Summary + + + +

    Unit Test Reports

    + + + `; + + return html; + } + + function findHTMLFiles(dir) { + let files = []; + const items = fs.readdirSync(dir); + + for (const item of items) { + const fullPath = path.join(dir, item); + const stat = fs.statSync(fullPath); + + if (stat.isDirectory()) { + files = files.concat(findHTMLFiles(fullPath)); + } else if (item === 'index.html' && fullPath !== outputFile) { + files.push(fullPath); + } + } + + return files; + } + + // Main execution + try { + const htmlFiles = findHTMLFiles(testReportDir); + const htmlContent = generateHTML(htmlFiles); + fs.writeFileSync(outputFile, htmlContent); + console.log(`Successfully generated ${outputFile}`); + } catch (error) { + console.error('Error generating test reports list:', error); + } +} diff --git a/buildLogic/convention/src/main/kotlin/BuildOutputFiles.kt b/buildLogic/convention/src/main/kotlin/BuildOutputFiles.kt index 6b9a93e1..a1a0e8fa 100644 --- a/buildLogic/convention/src/main/kotlin/BuildOutputFiles.kt +++ b/buildLogic/convention/src/main/kotlin/BuildOutputFiles.kt @@ -18,6 +18,10 @@ internal class BuildOutputFiles(private val rootDir: Directory) { .dir(projectDir(project)) .dir("android-lint-report") .file("lint-result.${type.extension}") + + fun unitTestReportDir(project: Project): Directory = rootDir + .dir("unit-test-report") + .dir(projectDir(project)) } internal enum class AndroidLintReportType(val extension: String) { diff --git a/buildLogic/convention/src/main/kotlin/module/Android.kt b/buildLogic/convention/src/main/kotlin/module/Android.kt index 37e5c161..f4e6501a 100644 --- a/buildLogic/convention/src/main/kotlin/module/Android.kt +++ b/buildLogic/convention/src/main/kotlin/module/Android.kt @@ -15,6 +15,7 @@ import dsl.version import org.gradle.api.JavaVersion import org.gradle.api.Project import org.gradle.kotlin.dsl.apply +import org.gradle.kotlin.dsl.assign import org.gradle.kotlin.dsl.dependencies import org.jetbrains.kotlin.gradle.dsl.JvmTarget import org.jetbrains.kotlin.gradle.dsl.KotlinAndroidProjectExtension @@ -58,6 +59,8 @@ internal fun Project.configureAndroid() { } } + configureAndroidTest() + val kotlin = kotlinExtension as KotlinAndroidProjectExtension kotlin.compilerOptions { jvmTarget.set(JvmTarget.JVM_17) @@ -73,3 +76,16 @@ internal fun Project.configureAndroid() { androidTestImplementation(libs.library("androidxEspressoCore")) } } + +private fun Project.configureAndroidTest() { + android { + @Suppress("UnstableApiUsage") + testOptions { + // unitTest.reportDir looks like not work + // refs: https://issuetracker.google.com/issues/37132023 + unitTests.all { + it.reports.html.outputLocation = BuildOutputFiles(rootProject).unitTestReportDir(project) + } + } + } +}