Skip to content

Commit

Permalink
[#77] Ability to provide stagingRepositoryId
Browse files Browse the repository at this point in the history
E.g. by some external plugin which created it explicitly.
  • Loading branch information
szpak committed Jan 2, 2019
1 parent 01620a2 commit df4ee71
Show file tree
Hide file tree
Showing 12 changed files with 129 additions and 91 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import io.codearte.gradle.nexus.functional.BaseNexusStagingFunctionalSpec
import nebula.test.functional.ExecutionResult
import spock.lang.Stepwise

//TODO: Temporary. Remove duplication with tests for 'maven'
//TODO: Remove duplication with tests for 'maven' - @Stepwise works with abstract tests in super class?
@Stepwise
class BasicPublishSmokeE2ESpec extends BaseNexusStagingFunctionalSpec implements E2ESpecHelperTrait {

Expand All @@ -31,8 +31,6 @@ class BasicPublishSmokeE2ESpec extends BaseNexusStagingFunctionalSpec implements
result.wasExecuted("publishToNexus")
and:
result.standardOutput.contains('to repository remote at https://oss.sonatype.org/service/local/staging/deployByRepositoryId/iogitlabnexus-at-')
and:
println result.standardOutput
}

def "should close and release repository"() {
Expand All @@ -46,6 +44,10 @@ class BasicPublishSmokeE2ESpec extends BaseNexusStagingFunctionalSpec implements
result.wasExecuted("closeAndReleaseRepository")
and:
result.standardOutput.contains('has been effectively released')
println result.standardOutput

and: "reuse provided staging profile in both close and release"
result.standardOutput.contains("Reusing staging repository id: iogitlabnexus-at")
// //Uncomment once bumped nexus-publish-plugin dependency to version implementing https://github.com/marcphilipp/nexus-publish-plugin/issues/11
// !result.standardOutput.contains("DEPRECATION WARNING. The staging repository ID is not provided.")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,7 @@ class BasicSmokeE2ESpec extends BaseNexusStagingFunctionalSpec implements E2ESpe
result.wasExecuted("closeAndReleaseRepository")
and:
result.standardOutput.contains('has been effectively released')
and:
result.standardOutput.contains("Reusing staging repository id: iogitlabnexus-at") //at least in release
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ class ExploratoryE2ESpec extends BaseNexusStagingFunctionalSpec implements E2ESp
given:
RepositoryFetcher fetcher = new RepositoryFetcher(client, E2E_SERVER_BASE_PATH)
when:
String stagingRepositoryId = fetcher.getOpenRepositoryIdForStagingProfileId(E2E_STAGING_PROFILE_ID)
String stagingRepositoryId = fetcher.getRepositoryIdWithGivenStateForStagingProfileId(E2E_STAGING_PROFILE_ID, RepositoryState.OPEN)
then:
println stagingRepositoryId
stagingRepositoryId == resolvedStagingRepositoryId
Expand Down
60 changes: 58 additions & 2 deletions src/main/groovy/io/codearte/gradle/nexus/BaseStagingTask.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,21 @@ import io.codearte.gradle.nexus.logic.OperationRetrier
import io.codearte.gradle.nexus.logic.RepositoryCloser
import io.codearte.gradle.nexus.logic.RepositoryFetcher
import io.codearte.gradle.nexus.logic.RepositoryReleaser
import io.codearte.gradle.nexus.logic.RepositoryState
import io.codearte.gradle.nexus.logic.RepositoryStateFetcher
import io.codearte.gradle.nexus.logic.StagingProfileFetcher
import org.gradle.api.DefaultTask
import org.gradle.api.Incubating
import org.gradle.api.Project
import org.gradle.api.model.ObjectFactory
import org.gradle.api.provider.Property
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.Optional

import javax.inject.Inject

@CompileStatic
@SuppressWarnings("UnstableApiUsage")
abstract class BaseStagingTask extends DefaultTask {

@Input
Expand Down Expand Up @@ -44,12 +52,27 @@ abstract class BaseStagingTask extends DefaultTask {
@Input
String repositoryDescription

@Input
@Optional
@Incubating
final Property<String> stagingRepositoryId

final private NexusStagingExtension extension

@Inject
BaseStagingTask(Project project, NexusStagingExtension extension) {
this.extension = extension
ObjectFactory objectFactory = project.getObjects();
stagingRepositoryId = objectFactory.property(String)
stagingRepositoryId.set(extension.getStagingRepositoryId())
}

@PackageScope
SimplifiedHttpJsonRestClient createClient() {
return new SimplifiedHttpJsonRestClient(new RESTClient(), getUsername(), getPassword())
}

protected StagingProfileFetcher createFetcherWithGivenClient(SimplifiedHttpJsonRestClient client) {
protected StagingProfileFetcher createProfileFetcherWithGivenClient(SimplifiedHttpJsonRestClient client) {
return new StagingProfileFetcher(client, getServerUrl())
}

Expand All @@ -73,15 +96,48 @@ abstract class BaseStagingTask extends DefaultTask {
return new OperationRetrier<T>(getNumberOfRetries(), getDelayBetweenRetriesInMillis())
}

protected String fetchAndCacheStagingProfileId(StagingProfileFetcher stagingProfileFetcher) {
protected String getConfiguredStagingProfileIdOrFindAndCacheOne(StagingProfileFetcher stagingProfileFetcher) {
String configuredStagingProfileId = getStagingProfileId()
if (configuredStagingProfileId != null) {
logger.info("Using configured staging profile id: $configuredStagingProfileId")
return configuredStagingProfileId
} else {
String receivedStagingProfileId = stagingProfileFetcher.getStagingProfileIdForPackageGroup(getPackageGroup())
//TODO: Get from and set in plugin extension instead of in task directly
setStagingProfileId(receivedStagingProfileId)
return receivedStagingProfileId
}
}

protected void savePassedRepositoryIdForReusingInInOtherTasks(String repositoryId) {
extension.stagingRepositoryId.set(repositoryId)
}

protected String getConfiguredRepositoryIdForStagingProfileOrFindAndCacheOneInGivenState(String stagingProfileId, RepositoryState repositoryState) {
return tryToGetConfiguredRepositoryId().orElseGet {
String repositoryId = findOneRepositoryIdInGivenStateForStagingProfileIdWithRetrying(repositoryState, stagingProfileId,
createRepositoryFetcherWithGivenClient(createClient()))
savePassedRepositoryIdForReusingInInOtherTasks(repositoryId)
return repositoryId
}
}

private java.util.Optional<String> tryToGetConfiguredRepositoryId() {
//Provider doesn't not provide orElseGet()
if (getStagingRepositoryId().isPresent()) {
String reusedStagingRepositoryId = getStagingRepositoryId().get()
logger.info("Reusing staging repository id: $reusedStagingRepositoryId")
return java.util.Optional.of(reusedStagingRepositoryId)
} else {
return java.util.Optional.empty()
}
}

private String findOneRepositoryIdInGivenStateForStagingProfileIdWithRetrying(RepositoryState repositoryState, String stagingProfileId,
RepositoryFetcher repositoryFetcher) {
logger.warn("DEPRECATION WARNING. The staging repository ID is not provided. The fallback mode may impact release reliability and is deprecated. " +
"Please consult the project FAQ how it can be fixed.")
OperationRetrier<String> retrier = createOperationRetrier()
return retrier.doWithRetry { repositoryFetcher.getRepositoryIdWithGivenStateForStagingProfileId(stagingProfileId, repositoryState) }
}
}
Original file line number Diff line number Diff line change
@@ -1,49 +1,27 @@
package io.codearte.gradle.nexus

import groovy.transform.CompileStatic
import groovy.transform.InheritConstructors
import io.codearte.gradle.nexus.logic.OperationRetrier
import io.codearte.gradle.nexus.logic.RepositoryCloser
import io.codearte.gradle.nexus.logic.RepositoryFetcher
import io.codearte.gradle.nexus.logic.RepositoryState
import io.codearte.gradle.nexus.logic.RepositoryStateFetcher
import io.codearte.gradle.nexus.logic.RetryingRepositoryTransitioner
import io.codearte.gradle.nexus.logic.StagingProfileFetcher
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.Optional
import org.gradle.api.tasks.TaskAction

@CompileStatic
@InheritConstructors(constructorAnnotations = true)
class CloseRepositoryTask extends BaseStagingTask {

@Input
@Optional
String stagingRepositoryId

@SuppressWarnings("unused")
@TaskAction
void doAction() {
StagingProfileFetcher stagingProfileFetcher = createFetcherWithGivenClient(createClient()) //Here or in fetchAndCacheStagingProfileId()?
RepositoryFetcher repositoryFetcher = createRepositoryFetcherWithGivenClient(createClient())

String stagingProfileId = fetchAndCacheStagingProfileId(stagingProfileFetcher)

String repositoryId = findOneOpenRepositoryIdForStagingProfileIdWithRetrying(stagingProfileId, repositoryFetcher)

memorizeRepositoryIdForReusingInInOtherTasks(repositoryId)
void closeRepository() {
String stagingProfileId = getConfiguredStagingProfileIdOrFindAndCacheOne(createProfileFetcherWithGivenClient(createClient()))
String repositoryId = getConfiguredRepositoryIdForStagingProfileOrFindAndCacheOneInGivenState(stagingProfileId, RepositoryState.OPEN)

closeRepositoryByIdAndProfileIdWithRetrying(repositoryId, stagingProfileId)
}

private String findOneOpenRepositoryIdForStagingProfileIdWithRetrying(String stagingProfileId, RepositoryFetcher repositoryFetcher) {
//TODO: Repository provided by Gradle upload mechanism should be used, but unfortunately it seems to be unsupported by Gradle.
// Therefore, check for just one repository in "open" state
OperationRetrier<String> retrier = createOperationRetrier()
return retrier.doWithRetry { repositoryFetcher.getOpenRepositoryIdForStagingProfileId(stagingProfileId) }
}

private void memorizeRepositoryIdForReusingInInOtherTasks(String repositoryId) {
stagingRepositoryId = repositoryId
}

private void closeRepositoryByIdAndProfileIdWithRetrying(String repositoryId, String stagingProfileId) {
RepositoryCloser repositoryCloser = createRepositoryCloserWithGivenClient(createClient())
RepositoryStateFetcher repositoryStateFetcher = createRepositoryStateFetcherWithGivenClient(createClient())
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
package io.codearte.gradle.nexus

import groovy.transform.CompileStatic
import groovy.transform.InheritConstructors
import io.codearte.gradle.nexus.logic.StagingProfileFetcher
import org.gradle.api.tasks.TaskAction

@CompileStatic
@InheritConstructors(constructorAnnotations = true)
class GetStagingProfileTask extends BaseStagingTask {

@TaskAction
void doAction() {
StagingProfileFetcher stagingProfileFetcher = createFetcherWithGivenClient(createClient())
StagingProfileFetcher stagingProfileFetcher = createProfileFetcherWithGivenClient(createClient())
String receivedStagingProfileId = stagingProfileFetcher.getStagingProfileIdForPackageGroup(getPackageGroup())
logger.lifecycle("Received staging profile id: $receivedStagingProfileId")
setStagingProfileId(receivedStagingProfileId)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@ import groovy.transform.CompileStatic
import groovy.transform.ToString
import groovy.util.logging.Slf4j
import org.gradle.api.Incubating
import org.gradle.api.Project
import org.gradle.api.model.ObjectFactory
import org.gradle.api.provider.Property

@SuppressWarnings("UnstableApiUsage")
@CompileStatic
@Slf4j
@ToString(includeFields = true, includeNames = true, includePackage = false)
Expand All @@ -18,4 +22,12 @@ class NexusStagingExtension {
@Incubating Integer numberOfRetries
@Incubating Integer delayBetweenRetriesInMillis
@Incubating String repositoryDescription //since 0.10.0

@Incubating
final Property<String> stagingRepositoryId //since 0.20.0

NexusStagingExtension(Project project) {
ObjectFactory objectFactory = project.getObjects()
stagingRepositoryId = objectFactory.property(String)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import org.gradle.api.tasks.Upload

import java.lang.invoke.MethodHandles

@SuppressWarnings("UnstableApiUsage")
class NexusStagingPlugin implements Plugin<Project> {

private final static Logger log = Logging.getLogger(MethodHandles.lookup().lookupClass())
Expand Down Expand Up @@ -58,7 +59,7 @@ class NexusStagingPlugin implements Plugin<Project> {
}

private NexusStagingExtension createAndConfigureExtension(Project project) {
NexusStagingExtension extension = project.extensions.create("nexusStaging", NexusStagingExtension)
NexusStagingExtension extension = project.extensions.create("nexusStaging", NexusStagingExtension, project)
extension.with {
serverUrl = "https://oss.sonatype.org/service/local/"
numberOfRetries = OperationRetrier.DEFAULT_NUMBER_OF_RETRIES
Expand All @@ -69,20 +70,20 @@ class NexusStagingPlugin implements Plugin<Project> {
}

private void createAndConfigureGetStagingProfileTask(Project project) {
GetStagingProfileTask task = project.tasks.create(GET_STAGING_PROFILE_TASK_NAME, GetStagingProfileTask)
GetStagingProfileTask task = project.tasks.create(GET_STAGING_PROFILE_TASK_NAME, GetStagingProfileTask, project, extension)
setTaskDescriptionAndGroup(task, "Gets a staging profile id in Nexus - a diagnostic task")
setTaskDefaultsAndDescription(task)
}

private CloseRepositoryTask createAndConfigureCloseRepositoryTask(Project project) {
CloseRepositoryTask task = project.tasks.create(CLOSE_REPOSITORY_TASK_NAME, CloseRepositoryTask)
CloseRepositoryTask task = project.tasks.create(CLOSE_REPOSITORY_TASK_NAME, CloseRepositoryTask, project, extension)
setTaskDescriptionAndGroup(task, "Closes an open artifacts repository in Nexus")
setTaskDefaultsAndDescription(task)
return task
}

private ReleaseRepositoryTask createAndConfigureReleaseRepositoryTask(Project project) {
ReleaseRepositoryTask task = project.tasks.create(RELEASE_REPOSITORY_TASK_NAME, ReleaseRepositoryTask)
ReleaseRepositoryTask task = project.tasks.create(RELEASE_REPOSITORY_TASK_NAME, ReleaseRepositoryTask, project, extension)
setTaskDescriptionAndGroup(task, "Releases a closed artifacts repository in Nexus")
setTaskDefaultsAndDescription(task)
return task
Expand Down
Original file line number Diff line number Diff line change
@@ -1,27 +1,25 @@
package io.codearte.gradle.nexus

import groovy.transform.CompileStatic
import groovy.transform.InheritConstructors
import io.codearte.gradle.nexus.logic.OperationRetrier
import io.codearte.gradle.nexus.logic.RepositoryFetcher
import io.codearte.gradle.nexus.logic.RepositoryReleaser
import io.codearte.gradle.nexus.logic.RepositoryState
import io.codearte.gradle.nexus.logic.RepositoryStateFetcher
import io.codearte.gradle.nexus.logic.RetryingRepositoryTransitioner
import io.codearte.gradle.nexus.logic.StagingProfileFetcher
import org.gradle.api.tasks.TaskAction

@CompileStatic
@InheritConstructors(constructorAnnotations = true)
class ReleaseRepositoryTask extends BaseStagingTask {

@TaskAction
void doAction() {
StagingProfileFetcher stagingProfileFetcher = createFetcherWithGivenClient(createClient())
RepositoryFetcher repositoryFetcher = createRepositoryFetcherWithGivenClient(createClient())

void releaseRepository() {
//TODO: Remove once stagingProfileId migrated to plugin extension
tryToTakeStagingProfileIdFromCloseRepositoryTask()
String stagingProfileId = fetchAndCacheStagingProfileId(stagingProfileFetcher)

String repositoryId = getRepositoryIdFromCloseTaskOrFromServer(stagingProfileId, repositoryFetcher)
String stagingProfileId = getConfiguredStagingProfileIdOrFindAndCacheOne(createProfileFetcherWithGivenClient(createClient()))
String repositoryId = getConfiguredRepositoryIdForStagingProfileOrFindAndCacheOneInGivenState(stagingProfileId, RepositoryState.CLOSED)

releaseRepositoryByIdAndProfileIdWithRetrying(repositoryId, stagingProfileId)
}
Expand All @@ -42,17 +40,6 @@ class ReleaseRepositoryTask extends BaseStagingTask {
return project.tasks.withType(CloseRepositoryTask)[0]
}

private String getRepositoryIdFromCloseTaskOrFromServer(String stagingProfileId, RepositoryFetcher repositoryFetcher) {
String repositoryIdFromCloseTask = getCloseRepositoryTask().stagingRepositoryId
if (repositoryIdFromCloseTask != null) {
logger.debug("Reusing staging repository id from closeRepository task: $repositoryIdFromCloseTask")
return repositoryIdFromCloseTask
}

OperationRetrier<String> retrier = createOperationRetrier()
return retrier.doWithRetry { repositoryFetcher.getClosedRepositoryIdForStagingProfileId(stagingProfileId) }
}

private void releaseRepositoryByIdAndProfileIdWithRetrying(String repositoryId, String stagingProfileId) {
RepositoryReleaser repositoryReleaser = createRepositoryReleaserWithGivenClient(createClient())
RepositoryStateFetcher repositoryStateFetcher = createRepositoryStateFetcherWithGivenClient(createClient())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,10 @@ import io.codearte.gradle.nexus.infra.WrongNumberOfRepositories
@Slf4j
class RepositoryFetcher extends BaseOperationExecutor {

String getOpenRepositoryIdForStagingProfileId(String stagingProfileId) {
return getRepositoryIdWithGivenStateForStagingProfileId(RepositoryState.OPEN.toString(), stagingProfileId)
}

String getClosedRepositoryIdForStagingProfileId(String stagingProfileId) {
return getRepositoryIdWithGivenStateForStagingProfileId(RepositoryState.CLOSED.toString(), stagingProfileId)
}

private String getRepositoryIdWithGivenStateForStagingProfileId(String state, String stagingProfileId) {
String getRepositoryIdWithGivenStateForStagingProfileId(String stagingProfileId, RepositoryState state) {
log.info("Getting '$state' repository for staging profile '$stagingProfileId'")
Map<String, List> allStagingRepositoriesResponseAsMap = client.get(nexusUrl + "/staging/profile_repositories/$stagingProfileId") //TODO: Constant
return parseResponseAndGetRepositoryIdInGivenState(allStagingRepositoriesResponseAsMap, state)
return parseResponseAndGetRepositoryIdInGivenState(allStagingRepositoriesResponseAsMap, state.toString())
}

private String parseResponseAndGetRepositoryIdInGivenState(Map<String, List> allStagingRepositoriesResponseAsMap, String repositoryState) {
Expand Down
Loading

0 comments on commit df4ee71

Please sign in to comment.