Skip to content
50 changes: 45 additions & 5 deletions .github/workflows/pull-request-check.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: Pull Request Check

on: [ pull_request ]
on: [pull_request]

concurrency:
group: pull-request-check-${{ github.event.pull_request.number }}
Expand Down Expand Up @@ -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
Expand Down
103 changes: 103 additions & 0 deletions .github/workflows/unit-test-top-html.js
Original file line number Diff line number Diff line change
@@ -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 `<li><a href="${items}/index.html">${path.basename(items)}</a></li>`;
}

return Object.entries(items).map(([key, value]) => {
if (typeof value === 'string') {
return `<li><a href="${value}/index.html">${path.basename(value)}</a></li>`;
}
return `<li>${key}<ul>${generateList(value)}</ul></li>`;
}).join('\n');
}

const html = `<!DOCTYPE html>
<html>
<head>
<title>Unit Test Reports Summary</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 20px;
line-height: 1.6;
}
h1 {
color: #333;
}
a {
color: #0066cc;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
</style>
</head>
<body>
<h1>Unit Test Reports</h1>
<ul>
${generateList(structure)}
</ul>
</body>
</html>`;

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);
}
}
4 changes: 4 additions & 0 deletions buildLogic/convention/src/main/kotlin/BuildOutputFiles.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
16 changes: 16 additions & 0 deletions buildLogic/convention/src/main/kotlin/module/Android.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -58,6 +59,8 @@ internal fun Project.configureAndroid() {
}
}

configureAndroidTest()

val kotlin = kotlinExtension as KotlinAndroidProjectExtension
kotlin.compilerOptions {
jvmTarget.set(JvmTarget.JVM_17)
Expand All @@ -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)
}
}
}
}
Loading