diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a508772..e89896f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -18,11 +18,11 @@ jobs: - name: Checkout repository uses: actions/checkout@v2 - - name: Set up JDK 11 + - name: Set up JDK 21 uses: actions/setup-java@v2 with: distribution: 'adopt' - java-version: '11' + java-version: '21' - name: Grant execute permission for gradlew run: chmod +x gradlew diff --git a/.github/workflows/manually-release.yml b/.github/workflows/manually-release.yml index 9850dcd..862fba1 100644 --- a/.github/workflows/manually-release.yml +++ b/.github/workflows/manually-release.yml @@ -26,11 +26,11 @@ jobs: - name: Checkout repository uses: actions/checkout@v2 - - name: Set up JDK 11 + - name: Set up JDK 21 uses: actions/setup-java@v2 with: distribution: 'adopt' - java-version: '11' + java-version: '21' - name: Grant execute permission for gradlew run: chmod +x gradlew diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 519f7fd..9ad35cd 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -21,11 +21,11 @@ jobs: - name: Checkout repository uses: actions/checkout@v2 - - name: Set up JDK 11 + - name: Set up JDK 21 uses: actions/setup-java@v2 with: distribution: 'adopt' - java-version: '11' + java-version: '21' - name: Grant execute permission for gradlew run: chmod +x gradlew diff --git a/build.gradle b/build.gradle index 4783b91..6c56aff 100644 --- a/build.gradle +++ b/build.gradle @@ -1,12 +1,8 @@ -import com.github.spotbugs.SpotBugsTask - plugins { - id "io.spring.dependency-management" version "1.0.9.RELEASE" + id "io.spring.dependency-management" version "1.1.4" id 'java' id 'jacoco' - id "com.github.spotbugs" version "3.0.0" id "com.github.node-gradle.node" version "2.2.1" - id 'nu.studer.jooq' version '3.0.3' } apply from: 'project-properties.gradle' @@ -14,7 +10,6 @@ apply from: 'project-properties.gradle' def scriptsUrl = 'https://raw.githubusercontent.com/reportportal/gradle-scripts/' + (releaseMode ? getProperty('scripts.version') : 'develop') -apply from: 'jooq.gradle' apply from: 'ui.gradle' apply from: scriptsUrl + '/release-fat.gradle' apply from: scriptsUrl + '/signing.gradle' @@ -35,47 +30,29 @@ dependencyManagement { } dependencies { + // ALL new dependencies should be included in shadowJar plugin! + // transitive dependencies may be required as well. could be checked in runtime only! if (releaseMode) { implementation 'com.epam.reportportal:commons-dao' implementation 'com.epam.reportportal:plugin-api' annotationProcessor 'com.epam.reportportal:plugin-api' } else { - implementation 'com.github.reportportal:commons-dao:acf1ec7' - implementation 'com.github.reportportal:plugin-api:188792e' - annotationProcessor 'com.github.reportportal:plugin-api:188792e' + implementation 'com.github.reportportal:commons-dao:8dcc514' + implementation 'com.github.reportportal:plugin-api:815c74a' + annotationProcessor 'com.github.reportportal:plugin-api:815c74a' } - implementation 'org.hibernate:hibernate-core:5.6.15.Final' - - implementation group: 'javax.servlet', name: 'javax.servlet-api', version: '4.0.1' - implementation group: 'org.jooq', name: 'jooq', version: '3.14.4' - jooqRuntime 'org.postgresql:postgresql:42.7.3' - - compile 'ch.qos.logback:logback-classic:1.2.3' - compile 'org.slf4j:slf4j-api:1.7.25' - - compile 'io.atlassian.fugue:fugue:4.7.2' - compile 'com.atlassian.jira:jira-rest-java-client-core:5.2.1' - testImplementation('org.junit.jupiter:junit-jupiter:5.6.0') + implementation("com.atlassian.jira:jira-rest-java-client-core:6.0.1") + implementation "io.atlassian.fugue:fugue:6.0.1" -} - -spotbugs { - sourceSets = [sourceSets.main] - reportLevel = "high" -} -tasks.withType(SpotBugsTask) { - reports { - xml.enabled false - html.enabled true - } + testImplementation('org.junit.jupiter:junit-jupiter:5.11.0') } test { useJUnitPlatform() jacocoTestReport { reports { - xml.enabled true + xml.required = true } } } @@ -106,7 +83,7 @@ jar { } manifest { attributes( - "Class-Path": configurations.compile.collect { it.getName() }.join(' '), + "Class-Path": configurations.compileClasspath.collect { it.getName() }.join(' '), "Plugin-Id": "${pluginId}", "Plugin-Version": "${project.version}", "Plugin-Provider": "Report Portal", @@ -124,17 +101,32 @@ shadowJar { from("ui/build") { into("/resources") } - configurations = [project.configurations.compile] + configurations = [project.configurations.compileClasspath] zip64 true dependencies { - exclude(dependency('com.github.reportportal:')) - exclude(dependency('com.epam.reportportal:')) - exclude(dependency('org.springframework:')) - exclude(dependency('org.springframework.security:')) - exclude(dependency('org.springframework.data:')) - exclude(dependency('org.springframework.boot:')) - exclude(dependency('ch.qos.logback:')) - exclude(dependency('org.slf4j:')) + include(dependency("com.atlassian.jira:jira-rest-java-client-api:.*")) + include(dependency("com.atlassian.jira:jira-rest-java-client-core:.*")) + include(dependency("com.atlassian.httpclient:atlassian-httpclient-api:.*")) + include(dependency("com.atlassian.httpclient:atlassian-httpclient-library:.*")) + include(dependency("com.atlassian.sal:sal-api:.*")) + include(dependency("com.atlassian.event:atlassian-event:.*")) + include(dependency("io.atlassian.util.concurrent:atlassian-util-concurrent:.*")) + include(dependency("io.atlassian.fugue:fugue:.*")) + include(dependency("org.apache.httpcomponents:httpasyncclient:.*")) + include(dependency("org.apache.httpcomponents:httpasyncclient-cache:.*")) + include(dependency("org.apache.httpcomponents:httpclient:.*")) + include(dependency("org.apache.httpcomponents:httpclient-cache:.*")) + include(dependency("org.apache.httpcomponents:httpcore:.*")) + include(dependency("org.apache.httpcomponents:httpcore-nio:.*")) + include(dependency("org.apache.httpcomponents:httpcore-mime:.*")) + include(dependency("org.glassfish.jersey.core:jersey-server:.*")) + include(dependency("org.glassfish.jersey.core:jersey-common:.*")) + include(dependency("jakarta.ws.rs:jakarta.ws.rs-api:.*")) + //include(dependency("jakarta.annotation:jakarta.annotation-api:.*")) + include(dependency("org.apache.tomcat:tomcat-annotations-api:.*")) + include(dependency("org.glassfish.hk2.external:jakarta.inject:.*")) + include(dependency("org.glassfish.hk2:osgi-resource-locator:.*")) + include(dependency("org.glassfish.jaxb:jaxb-runtime:.*")) } } @@ -144,9 +136,9 @@ task plugin(type: Jar) { with jar } into('lib') { - from configurations.compile + from configurations.compileClasspath } - extension('zip') + archiveExtension.set('zip') } task assemblePlugin(type: Copy) { diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index cc4fdc2..a4b76b9 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index c4520c4..df97d72 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,7 @@ -#Fri Mar 13 14:15:13 MSK 2020 -distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip +networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/jooq.gradle b/jooq.gradle index 0f38b27..accb253 100644 --- a/jooq.gradle +++ b/jooq.gradle @@ -1,7 +1,5 @@ jooq { - version = '3.12.4' - edition = 'OSS' - sample(sourceSets.main) { + configuration { jdbc { driver = 'org.postgresql.Driver' url = 'jdbc:postgresql://localhost:5432/reportportal' @@ -33,8 +31,4 @@ jooq { } } } -} - -generateSampleJooqSchemaSource { - enabled = false } \ No newline at end of file diff --git a/project-properties.gradle b/project-properties.gradle index 4a68d7f..7d7763d 100755 --- a/project-properties.gradle +++ b/project-properties.gradle @@ -1,5 +1,7 @@ -sourceCompatibility = JavaVersion.VERSION_11 -targetCompatibility = JavaVersion.VERSION_11 +java { + sourceCompatibility = JavaVersion.VERSION_21 + targetCompatibility = JavaVersion.VERSION_21 +} project.ext { publishRepo = "https://maven.pkg.github.com/reportportal/plugin-bts-jira-cloud" @@ -7,7 +9,3 @@ project.ext { releaseMode = project.hasProperty("releaseMode") pluginsDir = "$buildDir/plugins" } - -wrapper { - gradleVersion = '5.4.1' -} diff --git a/src/main/java/com/epam/reportportal/extension/jira/CloudJiraExtension.java b/src/main/java/com/epam/reportportal/extension/jira/CloudJiraExtension.java index b7051e5..e4d16e3 100644 --- a/src/main/java/com/epam/reportportal/extension/jira/CloudJiraExtension.java +++ b/src/main/java/com/epam/reportportal/extension/jira/CloudJiraExtension.java @@ -29,9 +29,9 @@ import com.epam.reportportal.extension.jira.command.GetIssueTypesCommand; import com.epam.reportportal.extension.jira.command.PostTicketCommand; import com.epam.reportportal.extension.jira.command.RetrieveCreationParamsCommand; +import com.epam.reportportal.extension.jira.command.RetrieveUpdateParamsCommand; import com.epam.reportportal.extension.jira.command.UserSearchCommand; import com.epam.reportportal.extension.jira.command.atlassian.CloudJiraClientProviderExtended; -import com.epam.reportportal.extension.jira.command.RetrieveUpdateParamsCommand; import com.epam.reportportal.extension.jira.command.connection.TestConnectionCommand; import com.epam.reportportal.extension.jira.command.utils.CloudJiraClientProvider; import com.epam.reportportal.extension.jira.command.utils.JIRATicketDescriptionService; @@ -62,7 +62,6 @@ import java.util.stream.Collectors; import javax.annotation.PostConstruct; import org.jasypt.util.text.BasicTextEncryptor; -import org.jooq.DSLContext; import org.pf4j.Extension; import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.annotation.Autowired; @@ -77,7 +76,6 @@ */ @Extension public class CloudJiraExtension implements ReportPortalExtensionPoint, DisposableBean { - private static final String DOCUMENTATION_LINK_FIELD = "documentationLink"; private static final String DOCUMENTATION_LINK = "https://reportportal.io/docs/plugins/AtlassianJiraCloud"; public static final String BINARY_DATA_PROPERTIES_FILE_ID = "binary-data.properties"; @@ -104,10 +102,6 @@ public class CloudJiraExtension implements ReportPortalExtensionPoint, Disposabl @Autowired private ApplicationContext applicationContext; - - @Autowired - private DSLContext dsl; - @Autowired private IntegrationTypeRepository integrationTypeRepository; diff --git a/src/main/java/com/epam/reportportal/extension/jira/command/connection/TestConnectionCommand.java b/src/main/java/com/epam/reportportal/extension/jira/command/connection/TestConnectionCommand.java index 1d42776..6fcf64c 100644 --- a/src/main/java/com/epam/reportportal/extension/jira/command/connection/TestConnectionCommand.java +++ b/src/main/java/com/epam/reportportal/extension/jira/command/connection/TestConnectionCommand.java @@ -22,16 +22,15 @@ import com.epam.reportportal.extension.PluginCommand; import com.epam.reportportal.extension.jira.command.utils.CloudJiraClientProvider; import com.epam.reportportal.extension.jira.command.utils.CloudJiraProperties; +import com.epam.reportportal.extension.jira.utils.IntegrationValidator; +import com.epam.reportportal.rules.exception.ErrorType; +import com.epam.reportportal.rules.exception.ReportPortalException; import com.epam.ta.reportportal.entity.integration.Integration; import com.epam.ta.reportportal.entity.integration.IntegrationParams; -import com.epam.reportportal.rules.exception.ReportPortalException; -import com.epam.reportportal.rules.exception.ErrorType; import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import static java.util.Optional.ofNullable; - /** * @author Pavel Bortnik */ @@ -60,6 +59,7 @@ public Boolean executeCommand(Integration integration, Map param () -> new ReportPortalException(ErrorType.UNABLE_INTERACT_WITH_INTEGRATION, "Project key is not specified." )); + IntegrationValidator.validateThirdPartyUrl(integration); try (JiraRestClient restClient = cloudJiraClientProvider.get(integrationParams)) { return restClient.getProjectClient().getProject(project).claim() != null; diff --git a/src/main/java/com/epam/reportportal/extension/jira/utils/IntegrationValidator.java b/src/main/java/com/epam/reportportal/extension/jira/utils/IntegrationValidator.java new file mode 100644 index 0000000..0d1e7ed --- /dev/null +++ b/src/main/java/com/epam/reportportal/extension/jira/utils/IntegrationValidator.java @@ -0,0 +1,52 @@ +/* + * Copyright 2024 EPAM Systems + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.epam.reportportal.extension.jira.utils; + +import com.epam.reportportal.rules.commons.validation.BusinessRule; +import com.epam.reportportal.rules.commons.validation.Suppliers; +import com.epam.reportportal.rules.exception.ErrorType; +import com.epam.ta.reportportal.commons.Predicates; +import com.epam.ta.reportportal.entity.integration.Integration; +import java.util.regex.Pattern; + +/** + * @author Siarhei Hrabko + */ +public final class IntegrationValidator { + + private static final String JIRA_URL_PATTERN = "https://[^?]*\\.atlassian\\.(com|net).*"; + + private IntegrationValidator() { + //static only + } + + + /** + * Validates Validates Rally server url. + * + * @param integration {@link Integration} + */ + public static void validateThirdPartyUrl(Integration integration) { + var valid = Pattern.matches(JIRA_URL_PATTERN, + String.valueOf(integration.getParams().getParams().get("url"))); + + BusinessRule.expect(valid, Predicates.equalTo(true)) + .verify(ErrorType.BAD_REQUEST_ERROR, + Suppliers.formattedSupplier("Integration url is not acceptable") + ); + } +} diff --git a/src/test/java/com/epam/reportportal/extension/jira/utils/IntegrationValidatorTest.java b/src/test/java/com/epam/reportportal/extension/jira/utils/IntegrationValidatorTest.java new file mode 100644 index 0000000..f7322da --- /dev/null +++ b/src/test/java/com/epam/reportportal/extension/jira/utils/IntegrationValidatorTest.java @@ -0,0 +1,66 @@ +/* + * Copyright 2024 EPAM Systems + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.epam.reportportal.extension.jira.utils; + +import com.epam.reportportal.rules.exception.ReportPortalException; +import com.epam.ta.reportportal.entity.integration.Integration; +import com.epam.ta.reportportal.entity.integration.IntegrationParams; +import java.util.HashMap; +import java.util.Map; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +class IntegrationValidatorTest { + + @ParameterizedTest + @CsvSource(value = { + "https://jira.atlassian.com", + "https://random.atlassian.com/", + "https://jira.atlassian.net", + "https://another.atlassian.net/", + }, delimiter = ',') + void validateThirdPartyUrl(String url) { + Assertions.assertDoesNotThrow(() -> + IntegrationValidator.validateThirdPartyUrl(getIntegration(url))); + } + + @ParameterizedTest + @CsvSource(value = { + "https://atlassian.com/", + "https://jiraatlassian.com/", + "https://zloi.hacker.com?jira=fake.atlassian.com", + }, delimiter = ',') + void validateThirdPartyUrlFailed(String url) { + Assertions.assertThrows(ReportPortalException.class, () -> + IntegrationValidator.validateThirdPartyUrl(getIntegration(url))); + } + + private static Integration getIntegration(String url) { + Map params = new HashMap<>(); + params.put("url", url); + + IntegrationParams integrationParams = new IntegrationParams(); + integrationParams.setParams(params); + + Integration integration = new Integration(); + integration.setParams(integrationParams); + + return integration; + } + +}