diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e1ab168..d89d5e1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -33,6 +33,9 @@ jobs: cache-read-only: false cache-encryption-key: ${{ secrets.GradleEncryptionKey }} + - name: Test gradle buildSrc srcipts + run: gradle :buildSrc:test --configuration-cache --info + - name: Build run: gradle build -x check --configuration-cache --info @@ -40,6 +43,12 @@ jobs: run: gradle test --configuration-cache --info continue-on-error: true + - name: Collect test reports + run: | + gradle aggregateJunitHtmlReports + gradle aggregateJunitXmlReports + ls build/reports/tests + - name: Generate jacoco report run: gradle testCodeCoverageReport -x check --info --configuration-cache @@ -57,19 +66,14 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} - - name: Collect test reports - run: | - gradle copyJunitHtmlResults --configuration-cache - gradle copyJunitXmlResults --configuration-cache - - name: Save test reports uses: actions/upload-artifact@v4 with: name: reports path: | build/reports - build/test-results build/api-spec + !build/reports/configuration-cache build/docs support/jacoco/reports @@ -102,19 +106,19 @@ jobs: - name: publish core test results uses: EnricoMi/publish-unit-test-result-action@v2 with: - files: './build/test-results/core/TEST-*.xml' + files: './build/reports/tests/xml/core-*.xml' check_name: 'Core' - name: publish api test results uses: EnricoMi/publish-unit-test-result-action@v2 with: - files: './build/test-results/api/TEST-*.xml' + files: './build/reports/tests/xml/api-*.xml' check_name: 'Api' - name: publish admin test results uses: EnricoMi/publish-unit-test-result-action@v2 with: - files: './build/test-results/admin/TEST-*.xml' + files: './build/reports/tests/xml/admin-*.xml' check_name: 'Admin' set-github-pages-resource: diff --git a/build.gradle b/build.gradle index f79f320..dca15e7 100644 --- a/build.gradle +++ b/build.gradle @@ -5,6 +5,7 @@ plugins { id 'org.sonarqube' id "org.asciidoctor.jvm.convert" id 'com.epages.restdocs-api-spec' + id 'com.github.can019.base.github-pages' } //apply from: 'gradle/jacoco.gradle' @@ -145,7 +146,6 @@ subprojects { property 'sonar.java.binaries', "${buildDir}/classes" } } - } sonar { @@ -162,49 +162,55 @@ sonar { } } -tasks.register('copyJunitXmlResults', Copy) { +tasks.register('copyOpenApi3Results',Copy) { subprojects.each { subproject -> - def xmlTestResultsDir = file("${subproject.buildDir}/test-results/test") + def openApi3ResultsDir = file("${subproject.buildDir}/api-spec/") - if (xmlTestResultsDir.exists()) { - from(xmlTestResultsDir) { + if (openApi3ResultsDir.exists()) { + from(openApi3ResultsDir) { into "${subproject.name}" } } else { - logger.info("No test result xml in submodule [${subproject.name}]") + logger.info("No openapi3 file in submodule [${subproject.name}]") } } - into "$buildDir/test-results" // 병합된 결과를 저장할 위치 + into "$buildDir/api-spec" // 병합된 결과를 저장할 +} +tasks.register('aggregateJunitHtmlReports', TestReport){ + destinationDirectory = file("$buildDir/reports/tests") + reportOn subprojects*.test } -tasks.register('copyJunitHtmlResults', Copy) { - subprojects.each { subproject -> - def htmlTestResultsDir = file("${subproject.buildDir}/reports/tests") +tasks.register('aggregateJunitXmlReports', Copy){ + onlyIf { true } + def xmlReportDir = file("$buildDir/reports/tests/xml") + xmlReportDir.mkdirs() - if (htmlTestResultsDir.exists()) { - from(htmlTestResultsDir) { - into "${subproject.name}" + subprojects.each { subproject -> + def testResultDir = subproject.file("${subproject.buildDir}/test-results/test") + + if (testResultDir.exists()) { + copy { + from subproject.test.reports.junitXml.outputLocation + into xmlReportDir + include "**/*.xml" + // Rename files to avoid conflicts + rename { String fileName -> + def projectPath = subproject.path.substring(1).replace(':', '-') + "${projectPath}-${fileName}" + } } } else { - logger.info("No test result xml in submodule [${subproject.name}]") + logger.lifecycle("Skipping ${subproject.path}: No test results found.") } } - into "$buildDir/reports/submodule/tests" // 병합된 결과를 저장할 위치 } -tasks.register('copyOpenApi3Results',Copy) { - subprojects.each { subproject -> - def openApi3ResultsDir = file("${subproject.buildDir}/api-spec/") - - if (openApi3ResultsDir.exists()) { - from(openApi3ResultsDir) { - into "${subproject.name}" - } - } else { - logger.info("No openapi3 file in submodule [${subproject.name}]") - } - } - into "$buildDir/api-spec" // 병합된 결과를 저장할 +tasks.register('aggregateJunitTestReports', TestReport) { + // aggregateJunitXmlReports가 계속 no source로 됨 + aggregateJunitXmlReports.mustRunAfter(aggregateJunitHtmlReports) + dependsOn(aggregateJunitHtmlReports) + dependsOn(aggregateJunitXmlReports) } bootJar.enabled = false \ No newline at end of file diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle new file mode 100644 index 0000000..c0874f9 --- /dev/null +++ b/buildSrc/build.gradle @@ -0,0 +1,38 @@ +plugins { + id 'java' + id 'java-gradle-plugin' +} + +group = 'com.github.can019.base' +version = '0.3.0-SNAPSHOT' + +repositories { + mavenCentral() +} + +java{ + sourceCompatibility = '21' +} + +dependencies { + testImplementation platform('org.junit:junit-bom:5.10.0') + testImplementation 'org.junit.jupiter:junit-jupiter' + implementation 'net.datafaker:datafaker:2.3.1' + testImplementation "org.assertj:assertj-core:3.26.3" + + compileOnly 'org.projectlombok:lombok:1.18.32' + annotationProcessor 'org.projectlombok:lombok:1.18.32' +} + +gradlePlugin { + plugins { + githubPagesPlugin { + id = 'com.github.can019.base.github-pages' + implementationClass = 'com.github.can019.base.gradle.github.GitHubPagesPlugin' + } + } +} + +test { + useJUnitPlatform() +} \ No newline at end of file diff --git a/buildSrc/src/main/java/com/github/can019/base/gradle/github/GitHubPageResourceGeneratorTask.java b/buildSrc/src/main/java/com/github/can019/base/gradle/github/GitHubPageResourceGeneratorTask.java new file mode 100644 index 0000000..bebdc93 --- /dev/null +++ b/buildSrc/src/main/java/com/github/can019/base/gradle/github/GitHubPageResourceGeneratorTask.java @@ -0,0 +1,20 @@ +package com.github.can019.base.gradle.github; + +import org.gradle.api.DefaultTask; +import org.gradle.api.tasks.TaskAction; + +public class GitHubPageResourceGeneratorTask extends DefaultTask { + + public GitHubPageResourceGeneratorTask() { + setDescription("Generates all resources for GitHub Pages"); + setGroup("GitHub Pages"); + + // 의존성 설정 + dependsOn("registerGitHubMetadata"); + } + + @TaskAction + public void generateResources() { + getLogger().lifecycle("Generating all resources for GitHub Pages..."); + } +} \ No newline at end of file diff --git a/buildSrc/src/main/java/com/github/can019/base/gradle/github/GitHubPagesPlugin.java b/buildSrc/src/main/java/com/github/can019/base/gradle/github/GitHubPagesPlugin.java new file mode 100644 index 0000000..22adf27 --- /dev/null +++ b/buildSrc/src/main/java/com/github/can019/base/gradle/github/GitHubPagesPlugin.java @@ -0,0 +1,12 @@ +package com.github.can019.base.gradle.github; + +import org.gradle.api.Plugin; +import org.gradle.api.Project; + +public class GitHubPagesPlugin implements Plugin{ + @Override + public void apply(Project target) { + target.getTasks().register("generateGitHubPageResources", GitHubPageResourceGeneratorTask.class); + target.getTasks().register("registerGitHubMetadata", RegisterGitHubMetadataTask.class); + } +} diff --git a/buildSrc/src/main/java/com/github/can019/base/gradle/github/RegisterGitHubMetadataTask.java b/buildSrc/src/main/java/com/github/can019/base/gradle/github/RegisterGitHubMetadataTask.java new file mode 100644 index 0000000..4311ac6 --- /dev/null +++ b/buildSrc/src/main/java/com/github/can019/base/gradle/github/RegisterGitHubMetadataTask.java @@ -0,0 +1,23 @@ +package com.github.can019.base.gradle.github; + +import org.gradle.api.DefaultTask; +import org.gradle.api.GradleException; +import org.gradle.api.tasks.TaskAction; + +public class RegisterGitHubMetadataTask extends DefaultTask{ + @TaskAction + public void registerMetadata() { + String commitId = (String) getProject().findProperty("commitId"); + String releaseVersion = (String) getProject().findProperty("releaseVersion"); + + if (commitId == null || releaseVersion == null) { + throw new GradleException("Commit id 또는 release version이 없습니다"); + } + + getProject().getExtensions().getExtraProperties().set("commitId", commitId); + getProject().getExtensions().getExtraProperties().set("releaseVersion", releaseVersion); + + getLogger().lifecycle("Commit id stored: " + commitId); + getLogger().lifecycle("Release version stored: " + releaseVersion); + } +} diff --git a/buildSrc/src/main/java/com/github/can019/base/gradle/github/configure/GitHubPageConfigure.java b/buildSrc/src/main/java/com/github/can019/base/gradle/github/configure/GitHubPageConfigure.java new file mode 100644 index 0000000..3cd4fc5 --- /dev/null +++ b/buildSrc/src/main/java/com/github/can019/base/gradle/github/configure/GitHubPageConfigure.java @@ -0,0 +1,24 @@ +package com.github.can019.base.gradle.github.configure; + +import lombok.Getter; + +@Getter +public class GitHubPageConfigure { + private MetaData metaData; + private GithubPageFileTree githubPageFileTree; +} + +@Getter +class MetaData { + private String releaseVersion; + private String commitId; +} + +class GithubPageFileTree{ + private String markUpFileName; + private String rootDirPath; + + public String getRootMarkUpFilePath() { + return String.join("/", rootDirPath, markUpFileName); + } +} \ No newline at end of file diff --git a/buildSrc/src/main/java/com/github/can019/base/gradle/github/structure/FileTree.java b/buildSrc/src/main/java/com/github/can019/base/gradle/github/structure/FileTree.java new file mode 100644 index 0000000..282dd22 --- /dev/null +++ b/buildSrc/src/main/java/com/github/can019/base/gradle/github/structure/FileTree.java @@ -0,0 +1,4 @@ +package com.github.can019.base.gradle.github.structure; + +public interface FileTree { +} diff --git a/buildSrc/src/test/java/com/github/can019/base/gradle/github/RegisterGithubMetadataTaskTest.java b/buildSrc/src/test/java/com/github/can019/base/gradle/github/RegisterGithubMetadataTaskTest.java new file mode 100644 index 0000000..7fb80ed --- /dev/null +++ b/buildSrc/src/test/java/com/github/can019/base/gradle/github/RegisterGithubMetadataTaskTest.java @@ -0,0 +1,73 @@ +package com.github.can019.base.gradle.github; + +import org.gradle.api.GradleException; +import org.gradle.api.Project; +import org.gradle.testfixtures.ProjectBuilder; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import net.datafaker.Faker; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +class RegisterGitHubMetadataTaskTest { + private Project project; + private RegisterGitHubMetadataTask task; + + private Faker faker = new Faker(); + + @BeforeEach + public void setUp() { + project = ProjectBuilder.builder().build(); + + project.getExtensions().getExtraProperties().set("commitId", null); + project.getExtensions().getExtraProperties().set("releaseVersion", null); + + task = project.getTasks().create("registerGitHubMetadata", RegisterGitHubMetadataTask.class); + } + + @Test + @DisplayName("Commit id와 release version이 정상적으로 등록되어야 한다") + public void testRegisterMetadata() { + String commitId = faker.code().ean8(); + project.getExtensions().getExtraProperties().set("commitId", commitId); + + String releaseVersion = faker.app().version(); + project.getExtensions().getExtraProperties().set("releaseVersion", releaseVersion); + + task.registerMetadata(); + + System.out.println(commitId); + System.out.println(releaseVersion); + + + assertThat(commitId).isEqualTo( project.getExtensions().getExtraProperties().get("commitId")); + assertThat(releaseVersion).isEqualTo(project.getExtensions().getExtraProperties().get("releaseVersion")); + } + + @Test + @DisplayName("Commit id가 null인 경우 오류가 발생해야한다") + public void testRegisterMetadataWithoutCommitId() { + String releaseVersion = faker.app().version(); + project.getExtensions().getExtraProperties().set("releaseVersion", releaseVersion); + + project.getExtensions().getExtraProperties().set("commitId", null); + + assertThatThrownBy(()-> task.registerMetadata()) + .isInstanceOf(GradleException.class) + .hasMessage("Commit id 또는 release version이 없습니다"); + } + + @Test + @DisplayName("Release version이 null인 경우 오류가 발생해야한다") + public void testRegisterMetadataWithoutReleaseVersion() { + String commitId = faker.code().ean8(); + project.getExtensions().getExtraProperties().set("commitId", commitId); + project.getExtensions().getExtraProperties().set("releaseVersion", null); + + assertThatThrownBy(()-> task.registerMetadata()) + .isInstanceOf(GradleException.class) + .hasMessage("Commit id 또는 release version이 없습니다"); + } +}