Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in / Register
Toggle navigation
S
spring-boot
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
DEMO
spring-boot
Commits
209c5c40
Commit
209c5c40
authored
Jun 12, 2020
by
Phillip Webb
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch '2.1.x' into 2.2.x
parents
4999ca5f
6d93d732
Changes
20
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
265 additions
and
100 deletions
+265
-100
ArtifactoryService.java
...course/releasescripts/artifactory/ArtifactoryService.java
+24
-9
BuildInfoResponse.java
...releasescripts/artifactory/payload/BuildInfoResponse.java
+49
-1
BintrayService.java
...ring/concourse/releasescripts/bintray/BintrayService.java
+47
-26
PackageFile.java
.../spring/concourse/releasescripts/bintray/PackageFile.java
+15
-9
CommandProcessor.java
...ng/concourse/releasescripts/command/CommandProcessor.java
+10
-2
DistributeCommand.java
...g/concourse/releasescripts/command/DistributeCommand.java
+25
-5
PromoteCommand.java
...ring/concourse/releasescripts/command/PromoteCommand.java
+5
-0
PublishGradlePlugin.java
...concourse/releasescripts/command/PublishGradlePlugin.java
+5
-0
SyncToCentralCommand.java
...oncourse/releasescripts/command/SyncToCentralCommand.java
+5
-0
SonatypeService.java
...ng/concourse/releasescripts/sonatype/SonatypeService.java
+7
-6
application.properties
.../releasescripts/src/main/resources/application.properties
+2
-1
ArtifactoryServiceTests.java
...e/releasescripts/artifactory/ArtifactoryServiceTests.java
+37
-15
BintrayServiceTests.java
...concourse/releasescripts/bintray/BintrayServiceTests.java
+12
-10
DistributeCommandTests.java
...course/releasescripts/command/DistributeCommandTests.java
+11
-4
SonatypeServiceTests.java
...ncourse/releasescripts/sonatype/SonatypeServiceTests.java
+2
-4
all-package-files.json
...g/concourse/releasescripts/bintray/all-package-files.json
+3
-3
no-package-files.json
...ng/concourse/releasescripts/bintray/no-package-files.json
+1
-0
some-package-files.json
.../concourse/releasescripts/bintray/some-package-files.json
+1
-1
promote.sh
ci/scripts/promote.sh
+3
-3
sync-to-maven-central.sh
ci/scripts/sync-to-maven-central.sh
+1
-1
No files found.
ci/images/releasescripts/src/main/java/io/spring/concourse/releasescripts/artifactory/ArtifactoryService.java
View file @
209c5c40
...
...
@@ -17,13 +17,16 @@
package
io
.
spring
.
concourse
.
releasescripts
.
artifactory
;
import
java.net.URI
;
import
java.time.Duration
;
import
java.util.Set
;
import
io.spring.concourse.releasescripts.ReleaseInfo
;
import
io.spring.concourse.releasescripts.artifactory.payload.BuildInfoResponse
;
import
io.spring.concourse.releasescripts.artifactory.payload.DistributionRequest
;
import
io.spring.concourse.releasescripts.artifactory.payload.PromotionRequest
;
import
io.spring.concourse.releasescripts.bintray.BintrayService
;
import
io.spring.concourse.releasescripts.system.ConsoleLogger
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.boot.web.client.RestTemplateBuilder
;
import
org.springframework.http.MediaType
;
...
...
@@ -42,6 +45,8 @@ import org.springframework.web.client.RestTemplate;
@Component
public
class
ArtifactoryService
{
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
ArtifactoryService
.
class
);
private
static
final
String
ARTIFACTORY_URL
=
"https://repo.spring.io"
;
private
static
final
String
PROMOTION_URL
=
ARTIFACTORY_URL
+
"/api/build/promote/"
;
...
...
@@ -56,8 +61,6 @@ public class ArtifactoryService {
private
final
BintrayService
bintrayService
;
private
static
final
ConsoleLogger
console
=
new
ConsoleLogger
();
public
ArtifactoryService
(
RestTemplateBuilder
builder
,
ArtifactoryProperties
artifactoryProperties
,
BintrayService
bintrayService
)
{
this
.
bintrayService
=
bintrayService
;
...
...
@@ -78,20 +81,21 @@ public class ArtifactoryService {
PromotionRequest
request
=
getPromotionRequest
(
targetRepo
);
String
buildName
=
releaseInfo
.
getBuildName
();
String
buildNumber
=
releaseInfo
.
getBuildNumber
();
console
.
log
(
"Promoting "
+
buildName
+
"/"
+
buildNumber
+
" to "
+
request
.
getTargetRepo
());
logger
.
info
(
"Promoting "
+
buildName
+
"/"
+
buildNumber
+
" to "
+
request
.
getTargetRepo
());
RequestEntity
<
PromotionRequest
>
requestEntity
=
RequestEntity
.
post
(
URI
.
create
(
PROMOTION_URL
+
buildName
+
"/"
+
buildNumber
)).
contentType
(
MediaType
.
APPLICATION_JSON
)
.
body
(
request
);
try
{
this
.
restTemplate
.
exchange
(
requestEntity
,
String
.
class
);
logger
.
debug
(
"Promotion complete"
);
}
catch
(
HttpClientErrorException
ex
)
{
boolean
isAlreadyPromoted
=
isAlreadyPromoted
(
buildName
,
buildNumber
,
request
.
getTargetRepo
());
if
(
isAlreadyPromoted
)
{
console
.
log
(
"Already promoted."
);
logger
.
info
(
"Already promoted."
);
}
else
{
console
.
log
(
"Promotion failed."
);
logger
.
info
(
"Promotion failed."
);
throw
ex
;
}
}
...
...
@@ -99,12 +103,15 @@ public class ArtifactoryService {
private
boolean
isAlreadyPromoted
(
String
buildName
,
String
buildNumber
,
String
targetRepo
)
{
try
{
logger
.
debug
(
"Checking if alreay promoted"
);
ResponseEntity
<
BuildInfoResponse
>
entity
=
this
.
restTemplate
.
getForEntity
(
BUILD_INFO_URL
+
buildName
+
"/"
+
buildNumber
,
BuildInfoResponse
.
class
);
BuildInfoResponse
.
Status
status
=
entity
.
getBody
().
getBuildInfo
().
getStatuses
()[
0
];
logger
.
debug
(
"Reutned repository "
+
status
.
getRepository
()
+
" expecting "
+
targetRepo
);
return
status
.
getRepository
().
equals
(
targetRepo
);
}
catch
(
HttpClientErrorException
ex
)
{
logger
.
debug
(
"Client error, assuming not promoted"
);
return
false
;
}
}
...
...
@@ -112,20 +119,28 @@ public class ArtifactoryService {
/**
* Deploy builds from Artifactory to Bintray.
* @param sourceRepo the source repo in Artifactory.
* @param releaseInfo the resease info
* @param artifactDigests the artifact digests
*/
public
void
distribute
(
String
sourceRepo
,
ReleaseInfo
releaseInfo
)
{
public
void
distribute
(
String
sourceRepo
,
ReleaseInfo
releaseInfo
,
Set
<
String
>
artifactDigests
)
{
logger
.
debug
(
"Attempting distribute via Artifactory"
);
if
(
this
.
bintrayService
.
isDistributionComplete
(
releaseInfo
,
artifactDigests
,
Duration
.
ofMinutes
(
2
)))
{
logger
.
info
(
"Distribution already complete"
);
return
;
}
DistributionRequest
request
=
new
DistributionRequest
(
new
String
[]
{
sourceRepo
});
RequestEntity
<
DistributionRequest
>
requestEntity
=
RequestEntity
.
post
(
URI
.
create
(
DISTRIBUTION_URL
+
releaseInfo
.
getBuildName
()
+
"/"
+
releaseInfo
.
getBuildNumber
()))
.
contentType
(
MediaType
.
APPLICATION_JSON
).
body
(
request
);
try
{
this
.
restTemplate
.
exchange
(
requestEntity
,
Object
.
class
);
logger
.
debug
(
"Distribution call completed"
);
}
catch
(
HttpClientErrorException
ex
)
{
console
.
log
(
"Failed to distribute."
);
logger
.
info
(
"Failed to distribute."
);
throw
ex
;
}
if
(!
this
.
bintrayService
.
isDistributionComplete
(
releaseInfo
))
{
if
(!
this
.
bintrayService
.
isDistributionComplete
(
releaseInfo
,
artifactDigests
,
Duration
.
ofMinutes
(
60
)
))
{
throw
new
DistributionTimeoutException
(
"Distribution timed out."
);
}
...
...
ci/images/releasescripts/src/main/java/io/spring/concourse/releasescripts/artifactory/payload/BuildInfoResponse.java
View file @
209c5c40
...
...
@@ -16,6 +16,12 @@
package
io
.
spring
.
concourse
.
releasescripts
.
artifactory
.
payload
;
import
java.util.Arrays
;
import
java.util.Set
;
import
java.util.function.Predicate
;
import
java.util.stream.Collectors
;
import
java.util.stream.Stream
;
/**
* Represents the response from Artifactory's buildInfo endpoint.
*
...
...
@@ -54,7 +60,7 @@ public class BuildInfoResponse {
}
public
String
getName
()
{
return
name
;
return
this
.
name
;
}
public
void
setName
(
String
name
)
{
...
...
@@ -83,6 +89,14 @@ public class BuildInfoResponse {
public
void
setVersion
(
String
version
)
{
this
.
version
=
version
;
}
public
Set
<
String
>
getArtifactDigests
(
Predicate
<
Artifact
>
predicate
)
{
return
Arrays
.
stream
(
this
.
modules
).
flatMap
((
module
)
->
{
Artifact
[]
artifacts
=
module
.
getArtifacts
();
return
(
artifacts
!=
null
)
?
Arrays
.
stream
(
artifacts
)
:
Stream
.
empty
();
}).
filter
(
predicate
).
map
(
Artifact:
:
getSha256
).
collect
(
Collectors
.
toSet
());
}
}
...
...
@@ -105,6 +119,8 @@ public class BuildInfoResponse {
private
String
id
;
private
Artifact
[]
artifacts
;
public
String
getId
()
{
return
this
.
id
;
}
...
...
@@ -113,6 +129,38 @@ public class BuildInfoResponse {
this
.
id
=
id
;
}
public
Artifact
[]
getArtifacts
()
{
return
this
.
artifacts
;
}
public
void
setArtifacts
(
Artifact
[]
artifacts
)
{
this
.
artifacts
=
artifacts
;
}
}
public
static
class
Artifact
{
private
String
name
;
private
String
sha256
;
public
String
getName
()
{
return
this
.
name
;
}
public
void
setName
(
String
name
)
{
this
.
name
=
name
;
}
public
String
getSha256
()
{
return
this
.
sha256
;
}
public
void
setSha256
(
String
sha256
)
{
this
.
sha256
=
sha256
;
}
}
}
ci/images/releasescripts/src/main/java/io/spring/concourse/releasescripts/bintray/BintrayService.java
View file @
209c5c40
...
...
@@ -17,17 +17,18 @@
package
io
.
spring
.
concourse
.
releasescripts
.
bintray
;
import
java.net.URI
;
import
java.util.Objects
;
import
java.util.concurrent.TimeUnit
;
import
java.time.Duration
;
import
java.util.HashSet
;
import
java.util.Set
;
import
io.spring.concourse.releasescripts.ReleaseInfo
;
import
io.spring.concourse.releasescripts.sonatype.SonatypeProperties
;
import
io.spring.concourse.releasescripts.sonatype.SonatypeService
;
import
io.spring.concourse.releasescripts.system.ConsoleLogger
;
import
org.awaitility.core.ConditionTimeoutException
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.boot.web.client.RestTemplateBuilder
;
import
org.springframework.http.HttpStatus
;
import
org.springframework.http.MediaType
;
import
org.springframework.http.RequestEntity
;
import
org.springframework.stereotype.Component
;
...
...
@@ -45,6 +46,8 @@ import static org.awaitility.Awaitility.waitAtMost;
@Component
public
class
BintrayService
{
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
BintrayService
.
class
);
private
static
final
String
BINTRAY_URL
=
"https://api.bintray.com/"
;
private
static
final
String
GRADLE_PLUGIN_REQUEST
=
"[ { \"name\": \"gradle-plugin\", \"values\": [\"org.springframework.boot:org.springframework.boot:spring-boot-gradle-plugin\"] } ]"
;
...
...
@@ -57,8 +60,6 @@ public class BintrayService {
private
final
SonatypeService
sonatypeService
;
private
static
final
ConsoleLogger
console
=
new
ConsoleLogger
();
public
BintrayService
(
RestTemplateBuilder
builder
,
BintrayProperties
bintrayProperties
,
SonatypeProperties
sonatypeProperties
,
SonatypeService
sonatypeService
)
{
this
.
bintrayProperties
=
bintrayProperties
;
...
...
@@ -72,32 +73,48 @@ public class BintrayService {
this
.
restTemplate
=
builder
.
build
();
}
public
boolean
isDistributionComplete
(
ReleaseInfo
releaseInfo
)
{
RequestEntity
<
Void
>
allFilesRequest
=
getRequest
(
releaseInfo
,
1
);
Object
[]
allFiles
=
waitAtMost
(
5
,
TimeUnit
.
MINUTES
).
with
().
pollDelay
(
20
,
TimeUnit
.
SECONDS
).
until
(()
->
{
try
{
return
this
.
restTemplate
.
exchange
(
allFilesRequest
,
Object
[].
class
).
getBody
();
}
catch
(
HttpClientErrorException
ex
)
{
if
(
ex
.
getStatusCode
()
!=
HttpStatus
.
NOT_FOUND
)
{
throw
ex
;
}
return
null
;
}
},
Objects:
:
nonNull
);
RequestEntity
<
Void
>
publishedFilesRequest
=
getRequest
(
releaseInfo
,
0
);
public
boolean
isDistributionComplete
(
ReleaseInfo
releaseInfo
,
Set
<
String
>
requiredDigets
,
Duration
timeout
)
{
return
isDistributionComplete
(
releaseInfo
,
requiredDigets
,
timeout
,
Duration
.
ofSeconds
(
20
));
}
public
boolean
isDistributionComplete
(
ReleaseInfo
releaseInfo
,
Set
<
String
>
requiredDigets
,
Duration
timeout
,
Duration
pollInterval
)
{
logger
.
debug
(
"Checking if distribution is complete"
);
RequestEntity
<
Void
>
request
=
getRequest
(
releaseInfo
,
0
);
try
{
waitAtMost
(
40
,
TimeUnit
.
MINUTES
).
with
().
pollDelay
(
20
,
TimeUnit
.
SECONDS
).
until
(()
->
{
Object
[]
publishedFiles
=
this
.
restTemplate
.
exchange
(
publishedFilesRequest
,
Object
[].
class
).
getBody
();
return
allFiles
.
length
==
publishedFiles
.
length
;
waitAtMost
(
timeout
).
with
().
pollDelay
(
Duration
.
ZERO
).
pollInterval
(
pollInterval
).
until
(()
->
{
logger
.
debug
(
"Checking bintray"
);
PackageFile
[]
published
=
this
.
restTemplate
.
exchange
(
request
,
PackageFile
[].
class
).
getBody
();
return
hasPublishedAll
(
published
,
requiredDigets
);
});
}
catch
(
ConditionTimeoutException
ex
)
{
logger
.
debug
(
"Timeout checking bintray"
);
return
false
;
}
return
true
;
}
private
boolean
hasPublishedAll
(
PackageFile
[]
published
,
Set
<
String
>
requiredDigets
)
{
if
(
published
==
null
||
published
.
length
==
0
)
{
logger
.
debug
(
"Bintray returned no published files"
);
return
false
;
}
Set
<
String
>
remaining
=
new
HashSet
<>(
requiredDigets
);
for
(
PackageFile
publishedFile
:
published
)
{
logger
.
debug
(
"Found published file "
+
publishedFile
.
getName
()
+
" with digest "
+
publishedFile
.
getSha256
());
remaining
.
remove
(
publishedFile
.
getSha256
());
}
if
(
remaining
.
isEmpty
())
{
logger
.
debug
(
"Found all required digests"
);
return
true
;
}
logger
.
debug
(
"Some digests have not been published:"
);
remaining
.
forEach
(
logger:
:
debug
);
return
false
;
}
private
RequestEntity
<
Void
>
getRequest
(
ReleaseInfo
releaseInfo
,
int
includeUnpublished
)
{
return
RequestEntity
.
get
(
URI
.
create
(
BINTRAY_URL
+
"packages/"
+
this
.
bintrayProperties
.
getSubject
()
+
"/"
+
this
.
bintrayProperties
.
getRepo
()
+
"/"
+
releaseInfo
.
getGroupId
()
+
"/versions/"
...
...
@@ -109,6 +126,7 @@ public class BintrayService {
* @param releaseInfo the release information
*/
public
void
publishGradlePlugin
(
ReleaseInfo
releaseInfo
)
{
logger
.
debug
(
"Publishing Gradle Pluging"
);
RequestEntity
<
String
>
requestEntity
=
RequestEntity
.
post
(
URI
.
create
(
BINTRAY_URL
+
"packages/"
+
this
.
bintrayProperties
.
getSubject
()
+
"/"
+
this
.
bintrayProperties
.
getRepo
()
+
"/"
+
releaseInfo
.
getGroupId
()
+
"/versions/"
...
...
@@ -116,9 +134,10 @@ public class BintrayService {
.
contentType
(
MediaType
.
APPLICATION_JSON
).
body
(
GRADLE_PLUGIN_REQUEST
);
try
{
this
.
restTemplate
.
exchange
(
requestEntity
,
Object
.
class
);
logger
.
debug
(
"Publishing Gradle Pluging complete"
);
}
catch
(
HttpClientErrorException
ex
)
{
console
.
log
(
"Failed to add attribute to gradle plugin."
);
logger
.
info
(
"Failed to add attribute to gradle plugin."
);
throw
ex
;
}
}
...
...
@@ -128,8 +147,9 @@ public class BintrayService {
* @param releaseInfo the release information
*/
public
void
syncToMavenCentral
(
ReleaseInfo
releaseInfo
)
{
console
.
log
(
"Calling Bintray to sync to Sonatype"
);
logger
.
info
(
"Calling Bintray to sync to Sonatype"
);
if
(
this
.
sonatypeService
.
artifactsPublished
(
releaseInfo
))
{
logger
.
info
(
"Artifacts already published"
);
return
;
}
RequestEntity
<
SonatypeProperties
>
requestEntity
=
RequestEntity
...
...
@@ -139,9 +159,10 @@ public class BintrayService {
.
contentType
(
MediaType
.
APPLICATION_JSON
).
body
(
this
.
sonatypeProperties
);
try
{
this
.
restTemplate
.
exchange
(
requestEntity
,
Object
.
class
);
logger
.
debug
(
"Sync complete"
);
}
catch
(
HttpClientErrorException
ex
)
{
console
.
log
(
"Failed to sync."
);
logger
.
info
(
"Failed to sync."
);
throw
ex
;
}
}
...
...
ci/images/releasescripts/src/main/java/io/spring/concourse/releasescripts/
system/ConsoleLogger
.java
→
ci/images/releasescripts/src/main/java/io/spring/concourse/releasescripts/
bintray/PackageFile
.java
View file @
209c5c40
/*
* Copyright 20
12-2019
the original author or authors.
* Copyright 20
20
the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
...
...
@@ -14,19 +14,25 @@
* limitations under the License.
*/
package
io
.
spring
.
concourse
.
releasescripts
.
system
;
import
org.slf4j.helpers.MessageFormatter
;
package
io
.
spring
.
concourse
.
releasescripts
.
bintray
;
/**
*
Simple console logger used to output progress messages
.
*
Details for a single packaged file
.
*
* @author
Madhura Bhave
* @author
Phillip Webb
*/
public
class
ConsoleLogger
{
public
class
PackageFile
{
private
String
name
;
private
String
sha256
;
public
String
getName
()
{
return
this
.
name
;
}
public
void
log
(
String
message
,
Object
...
args
)
{
System
.
err
.
println
(
MessageFormatter
.
arrayFormat
(
message
,
args
).
getMessage
())
;
public
String
getSha256
(
)
{
return
this
.
sha256
;
}
}
ci/images/releasescripts/src/main/java/io/spring/concourse/releasescripts/command/CommandProcessor.java
View file @
209c5c40
...
...
@@ -19,6 +19,9 @@ package io.spring.concourse.releasescripts.command;
import
java.util.Collections
;
import
java.util.List
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.boot.ApplicationArguments
;
import
org.springframework.boot.ApplicationRunner
;
import
org.springframework.stereotype.Component
;
...
...
@@ -32,6 +35,8 @@ import org.springframework.util.Assert;
@Component
public
class
CommandProcessor
implements
ApplicationRunner
{
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
CommandProcessor
.
class
);
private
final
List
<
Command
>
commands
;
public
CommandProcessor
(
List
<
Command
>
commands
)
{
...
...
@@ -40,11 +45,14 @@ public class CommandProcessor implements ApplicationRunner {
@Override
public
void
run
(
ApplicationArguments
args
)
throws
Exception
{
logger
.
debug
(
"Running command processor"
);
List
<
String
>
nonOptionArgs
=
args
.
getNonOptionArgs
();
Assert
.
state
(!
nonOptionArgs
.
isEmpty
(),
"No command argument specified"
);
String
request
=
nonOptionArgs
.
get
(
0
);
this
.
commands
.
stream
().
filter
((
c
)
->
c
.
getName
().
equals
(
request
)).
findFirst
()
.
orElseThrow
(()
->
new
IllegalStateException
(
"Unknown command '"
+
request
+
"'"
)).
run
(
args
);
Command
command
=
this
.
commands
.
stream
().
filter
((
candidate
)
->
candidate
.
getName
().
equals
(
request
)).
findFirst
()
.
orElseThrow
(()
->
new
IllegalStateException
(
"Unknown command '"
+
request
+
"'"
));
logger
.
debug
(
"Found command "
+
command
.
getClass
().
getName
());
command
.
run
(
args
);
}
}
ci/images/releasescripts/src/main/java/io/spring/concourse/releasescripts/command/DistributeCommand.java
View file @
209c5c40
...
...
@@ -19,12 +19,18 @@ package io.spring.concourse.releasescripts.command;
import
java.io.File
;
import
java.nio.file.Files
;
import
java.util.List
;
import
java.util.Set
;
import
com.fasterxml.jackson.databind.ObjectMapper
;
import
io.spring.concourse.releasescripts.ReleaseInfo
;
import
io.spring.concourse.releasescripts.ReleaseType
;
import
io.spring.concourse.releasescripts.artifactory.ArtifactoryService
;
import
io.spring.concourse.releasescripts.artifactory.payload.BuildInfoResponse
;
import
io.spring.concourse.releasescripts.artifactory.payload.BuildInfoResponse.Artifact
;
import
io.spring.concourse.releasescripts.artifactory.payload.BuildInfoResponse.BuildInfo
;
import
io.spring.concourse.releasescripts.artifactory.payload.BuildInfoResponse.Module
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.boot.ApplicationArguments
;
import
org.springframework.stereotype.Component
;
...
...
@@ -38,30 +44,44 @@ import org.springframework.util.Assert;
@Component
public
class
DistributeCommand
implements
Command
{
private
final
ArtifactoryService
service
;
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
DistributeCommand
.
class
);
private
final
ArtifactoryService
artifactoryService
;
private
final
ObjectMapper
objectMapper
;
public
DistributeCommand
(
ArtifactoryService
s
ervice
,
ObjectMapper
objectMapper
)
{
this
.
service
=
s
ervice
;
public
DistributeCommand
(
ArtifactoryService
artifactoryS
ervice
,
ObjectMapper
objectMapper
)
{
this
.
artifactoryService
=
artifactoryS
ervice
;
this
.
objectMapper
=
objectMapper
;
}
@Override
public
void
run
(
ApplicationArguments
args
)
throws
Exception
{
logger
.
debug
(
"Running 'distribute' command"
);
List
<
String
>
nonOptionArgs
=
args
.
getNonOptionArgs
();
Assert
.
state
(!
nonOptionArgs
.
isEmpty
(),
"No command argument specified"
);
Assert
.
state
(
nonOptionArgs
.
size
()
==
3
,
"Release type or build info not specified"
);
String
releaseType
=
nonOptionArgs
.
get
(
1
);
ReleaseType
type
=
ReleaseType
.
from
(
releaseType
);
if
(!
ReleaseType
.
RELEASE
.
equals
(
type
))
{
logger
.
info
(
"Skipping distribution of "
+
type
+
" type"
);
return
;
}
String
buildInfoLocation
=
nonOptionArgs
.
get
(
2
);
logger
.
debug
(
"Loading build-info from "
+
buildInfoLocation
);
byte
[]
content
=
Files
.
readAllBytes
(
new
File
(
buildInfoLocation
).
toPath
());
BuildInfoResponse
buildInfoResponse
=
this
.
objectMapper
.
readValue
(
content
,
BuildInfoResponse
.
class
);
ReleaseInfo
releaseInfo
=
ReleaseInfo
.
from
(
buildInfoResponse
.
getBuildInfo
());
this
.
service
.
distribute
(
type
.
getRepo
(),
releaseInfo
);
BuildInfo
buildInfo
=
buildInfoResponse
.
getBuildInfo
();
logger
.
debug
(
"Loading build info:"
);
for
(
Module
module
:
buildInfo
.
getModules
())
{
logger
.
debug
(
module
.
getId
());
for
(
Artifact
artifact
:
module
.
getArtifacts
())
{
logger
.
debug
(
artifact
.
getSha256
()
+
" "
+
artifact
.
getName
());
}
}
ReleaseInfo
releaseInfo
=
ReleaseInfo
.
from
(
buildInfo
);
Set
<
String
>
artifactDigests
=
buildInfo
.
getArtifactDigests
((
artifact
)
->
!
artifact
.
getName
().
endsWith
(
".zip"
));
this
.
artifactoryService
.
distribute
(
type
.
getRepo
(),
releaseInfo
,
artifactDigests
);
}
}
ci/images/releasescripts/src/main/java/io/spring/concourse/releasescripts/command/PromoteCommand.java
View file @
209c5c40
...
...
@@ -25,6 +25,8 @@ import io.spring.concourse.releasescripts.ReleaseInfo;
import
io.spring.concourse.releasescripts.ReleaseType
;
import
io.spring.concourse.releasescripts.artifactory.ArtifactoryService
;
import
io.spring.concourse.releasescripts.artifactory.payload.BuildInfoResponse
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.boot.ApplicationArguments
;
import
org.springframework.stereotype.Component
;
...
...
@@ -38,6 +40,8 @@ import org.springframework.util.Assert;
@Component
public
class
PromoteCommand
implements
Command
{
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
PromoteCommand
.
class
);
private
final
ArtifactoryService
service
;
private
final
ObjectMapper
objectMapper
;
...
...
@@ -49,6 +53,7 @@ public class PromoteCommand implements Command {
@Override
public
void
run
(
ApplicationArguments
args
)
throws
Exception
{
logger
.
debug
(
"Running 'promote' command"
);
List
<
String
>
nonOptionArgs
=
args
.
getNonOptionArgs
();
Assert
.
state
(!
nonOptionArgs
.
isEmpty
(),
"No command argument specified"
);
Assert
.
state
(
nonOptionArgs
.
size
()
==
3
,
"Release type or build info location not specified"
);
...
...
ci/images/releasescripts/src/main/java/io/spring/concourse/releasescripts/command/PublishGradlePlugin.java
View file @
209c5c40
...
...
@@ -25,6 +25,8 @@ import io.spring.concourse.releasescripts.ReleaseInfo;
import
io.spring.concourse.releasescripts.ReleaseType
;
import
io.spring.concourse.releasescripts.artifactory.payload.BuildInfoResponse
;
import
io.spring.concourse.releasescripts.bintray.BintrayService
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.boot.ApplicationArguments
;
import
org.springframework.stereotype.Component
;
...
...
@@ -38,6 +40,8 @@ import org.springframework.util.Assert;
@Component
public
class
PublishGradlePlugin
implements
Command
{
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
PublishGradlePlugin
.
class
);
private
static
final
String
PUBLISH_GRADLE_PLUGIN_COMMAND
=
"publishGradlePlugin"
;
private
final
BintrayService
service
;
...
...
@@ -56,6 +60,7 @@ public class PublishGradlePlugin implements Command {
@Override
public
void
run
(
ApplicationArguments
args
)
throws
Exception
{
logger
.
debug
(
"Running 'publish gradle' command"
);
List
<
String
>
nonOptionArgs
=
args
.
getNonOptionArgs
();
Assert
.
state
(!
nonOptionArgs
.
isEmpty
(),
"No command argument specified"
);
Assert
.
state
(
nonOptionArgs
.
size
()
==
3
,
"Release type or build info not specified"
);
...
...
ci/images/releasescripts/src/main/java/io/spring/concourse/releasescripts/command/SyncToCentralCommand.java
View file @
209c5c40
...
...
@@ -25,6 +25,8 @@ import io.spring.concourse.releasescripts.ReleaseInfo;
import
io.spring.concourse.releasescripts.ReleaseType
;
import
io.spring.concourse.releasescripts.artifactory.payload.BuildInfoResponse
;
import
io.spring.concourse.releasescripts.bintray.BintrayService
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.boot.ApplicationArguments
;
import
org.springframework.stereotype.Component
;
...
...
@@ -38,6 +40,8 @@ import org.springframework.util.Assert;
@Component
public
class
SyncToCentralCommand
implements
Command
{
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
SyncToCentralCommand
.
class
);
private
static
final
String
SYNC_TO_CENTRAL_COMMAND
=
"syncToCentral"
;
private
final
BintrayService
service
;
...
...
@@ -56,6 +60,7 @@ public class SyncToCentralCommand implements Command {
@Override
public
void
run
(
ApplicationArguments
args
)
throws
Exception
{
logger
.
debug
(
"Running 'sync to central' command"
);
List
<
String
>
nonOptionArgs
=
args
.
getNonOptionArgs
();
Assert
.
state
(!
nonOptionArgs
.
isEmpty
(),
"No command argument specified"
);
Assert
.
state
(
nonOptionArgs
.
size
()
==
3
,
"Release type or build info not specified"
);
...
...
ci/images/releasescripts/src/main/java/io/spring/concourse/releasescripts/sonatype/SonatypeService.java
View file @
209c5c40
...
...
@@ -17,7 +17,8 @@
package
io
.
spring
.
concourse
.
releasescripts
.
sonatype
;
import
io.spring.concourse.releasescripts.ReleaseInfo
;
import
io.spring.concourse.releasescripts.system.ConsoleLogger
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.boot.web.client.RestTemplateBuilder
;
import
org.springframework.http.HttpStatus
;
...
...
@@ -35,12 +36,12 @@ import org.springframework.web.client.RestTemplate;
@Component
public
class
SonatypeService
{
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
SonatypeService
.
class
);
private
static
final
String
SONATYPE_REPOSITORY_URI
=
"https://oss.sonatype.org/service/local/repositories/releases/content/org/springframework/boot/spring-boot/"
;
private
final
RestTemplate
restTemplate
;
private
static
final
ConsoleLogger
console
=
new
ConsoleLogger
();
public
SonatypeService
(
RestTemplateBuilder
builder
,
SonatypeProperties
sonatypeProperties
)
{
String
username
=
sonatypeProperties
.
getUserToken
();
String
password
=
sonatypeProperties
.
getPasswordToken
();
...
...
@@ -57,11 +58,11 @@ public class SonatypeService {
*/
public
boolean
artifactsPublished
(
ReleaseInfo
releaseInfo
)
{
try
{
ResponseEntity
<
Object
>
entity
=
this
.
restTemplate
ResponseEntity
<
?
>
entity
=
this
.
restTemplate
.
getForEntity
(
String
.
format
(
SONATYPE_REPOSITORY_URI
+
"%s/spring-boot-%s.jar.sha1"
,
releaseInfo
.
getVersion
(),
releaseInfo
.
getVersion
()),
Object
.
class
);
releaseInfo
.
getVersion
(),
releaseInfo
.
getVersion
()),
byte
[]
.
class
);
if
(
HttpStatus
.
OK
.
equals
(
entity
.
getStatusCode
()))
{
console
.
log
(
"Already published to Sonatype."
);
logger
.
info
(
"Already published to Sonatype."
);
return
true
;
}
}
...
...
ci/images/releasescripts/src/main/resources/application.properties
View file @
209c5c40
spring.main.banner-mode
=
off
#
logging.level.io.spring.concourse
=
DEBUG
\ No newline at end of file
ci/images/releasescripts/src/test/java/io/spring/concourse/releasescripts/artifactory/ArtifactoryServiceTests.java
View file @
209c5c40
...
...
@@ -16,10 +16,15 @@
package
io
.
spring
.
concourse
.
releasescripts
.
artifactory
;
import
java.time.Duration
;
import
java.util.Collections
;
import
java.util.Set
;
import
io.spring.concourse.releasescripts.ReleaseInfo
;
import
io.spring.concourse.releasescripts.bintray.BintrayService
;
import
org.junit.jupiter.api.AfterEach
;
import
org.junit.jupiter.api.Test
;
import
org.mockito.InOrder
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.boot.context.properties.EnableConfigurationProperties
;
...
...
@@ -35,10 +40,13 @@ import org.springframework.util.Base64Utils;
import
org.springframework.web.client.HttpClientErrorException
;
import
static
org
.
assertj
.
core
.
api
.
Assertions
.
assertThatExceptionOfType
;
import
static
org
.
mockito
.
ArgumentMatchers
.
any
;
import
static
org
.
mockito
.
ArgumentMatchers
.
eq
;
import
static
org
.
mockito
.
BDDMockito
.
given
;
import
static
org
.
mockito
.
Mockito
.
inOrder
;
import
static
org
.
mockito
.
Mockito
.
times
;
import
static
org
.
mockito
.
Mockito
.
verify
;
import
static
org
.
mockito
.
Mockito
.
verifyNoInteractions
;
import
static
org
.
mockito
.
Mockito
.
verifyNo
More
Interactions
;
import
static
org
.
springframework
.
test
.
web
.
client
.
match
.
MockRestRequestMatchers
.
content
;
import
static
org
.
springframework
.
test
.
web
.
client
.
match
.
MockRestRequestMatchers
.
header
;
import
static
org
.
springframework
.
test
.
web
.
client
.
match
.
MockRestRequestMatchers
.
method
;
...
...
@@ -55,6 +63,10 @@ import static org.springframework.test.web.client.response.MockRestResponseCreat
@EnableConfigurationProperties
(
ArtifactoryProperties
.
class
)
class
ArtifactoryServiceTests
{
private
static
final
Duration
SHORT_TIMEOUT
=
Duration
.
ofMinutes
(
2
);
private
static
final
Duration
LONG_TIMEOUT
=
Duration
.
ofMinutes
(
60
);
@Autowired
private
ArtifactoryService
service
;
...
...
@@ -126,21 +138,24 @@ class ArtifactoryServiceTests {
}
@Test
@SuppressWarnings
(
"unchecked"
)
void
distributeWhenSuccessful
()
throws
Exception
{
ReleaseInfo
releaseInfo
=
getReleaseInfo
();
given
(
this
.
bintrayService
.
isDistributionComplete
(
releaseInfo
)).
willReturn
(
true
);
this
.
server
.
expect
(
requestTo
(
"https://repo.spring.io/api/build/distribute/"
+
"example-build"
+
"/"
+
"example-build-1"
))
given
(
this
.
bintrayService
.
isDistributionComplete
(
eq
(
releaseInfo
),
(
Set
<
String
>)
any
(),
any
())).
willReturn
(
false
,
true
);
this
.
server
.
expect
(
requestTo
(
"https://repo.spring.io/api/build/distribute/example-build/example-build-1"
))
.
andExpect
(
method
(
HttpMethod
.
POST
))
.
andExpect
(
content
().
json
(
"{\"sourceRepos\": [\"libs-release-local\"], \"targetRepo\" : \"spring-distributions\", \"async\":\"true\"}"
))
.
andExpect
(
header
(
"Authorization"
,
"Basic "
+
Base64Utils
.
encodeToString
(
String
.
format
(
"%s:%s"
,
this
.
properties
.
getUsername
(),
this
.
properties
.
getPassword
()).
getBytes
())))
.
andExpect
(
header
(
"Content-Type"
,
MediaType
.
APPLICATION_JSON
.
toString
())).
andRespond
(
withSuccess
());
this
.
service
.
distribute
(
"libs-release-local"
,
releaseInfo
);
Set
<
String
>
artifactDigests
=
Collections
.
singleton
(
"602e20176706d3cc7535f01ffdbe91b270ae5014"
);
this
.
service
.
distribute
(
"libs-release-local"
,
releaseInfo
,
artifactDigests
);
this
.
server
.
verify
();
verify
(
this
.
bintrayService
,
times
(
1
)).
isDistributionComplete
(
releaseInfo
);
InOrder
ordered
=
inOrder
(
this
.
bintrayService
);
ordered
.
verify
(
this
.
bintrayService
).
isDistributionComplete
(
releaseInfo
,
artifactDigests
,
SHORT_TIMEOUT
);
ordered
.
verify
(
this
.
bintrayService
).
isDistributionComplete
(
releaseInfo
,
artifactDigests
,
LONG_TIMEOUT
);
}
@Test
...
...
@@ -156,29 +171,36 @@ class ArtifactoryServiceTests {
.
format
(
"%s:%s"
,
this
.
properties
.
getUsername
(),
this
.
properties
.
getPassword
()).
getBytes
())))
.
andExpect
(
header
(
"Content-Type"
,
MediaType
.
APPLICATION_JSON
.
toString
()))
.
andRespond
(
withStatus
(
HttpStatus
.
FORBIDDEN
));
Set
<
String
>
artifactDigests
=
Collections
.
singleton
(
"602e20176706d3cc7535f01ffdbe91b270ae5014"
);
assertThatExceptionOfType
(
HttpClientErrorException
.
class
)
.
isThrownBy
(()
->
this
.
service
.
distribute
(
"libs-release-local"
,
releaseInfo
));
.
isThrownBy
(()
->
this
.
service
.
distribute
(
"libs-release-local"
,
releaseInfo
,
artifactDigests
));
this
.
server
.
verify
();
verifyNoInteractions
(
this
.
bintrayService
);
verify
(
this
.
bintrayService
,
times
(
1
)).
isDistributionComplete
(
releaseInfo
,
artifactDigests
,
SHORT_TIMEOUT
);
verifyNoMoreInteractions
(
this
.
bintrayService
);
}
@Test
@SuppressWarnings
(
"unchecked"
)
void
distributeWhenGettingPackagesTimesOut
()
throws
Exception
{
ReleaseInfo
releaseInfo
=
getReleaseInfo
();
given
(
this
.
bintrayService
.
isDistributionComplete
(
releaseInfo
)).
willReturn
(
false
);
this
.
server
.
expect
(
requestTo
(
"https://repo.spring.io/api/build/distribute/"
+
"example-build"
+
"/"
+
"example-build-1"
))
given
(
this
.
bintrayService
.
isDistributionComplete
(
eq
(
releaseInfo
),
(
Set
<
String
>)
any
(),
any
()))
.
willReturn
(
false
);
given
(
this
.
bintrayService
.
isDistributionComplete
(
eq
(
releaseInfo
),
(
Set
<
String
>)
any
(),
any
()))
.
willReturn
(
false
);
this
.
server
.
expect
(
requestTo
(
"https://repo.spring.io/api/build/distribute/example-build/example-build-1"
))
.
andExpect
(
method
(
HttpMethod
.
POST
))
.
andExpect
(
content
().
json
(
"{\"sourceRepos\": [\"libs-release-local\"], \"targetRepo\" : \"spring-distributions\", \"async\":\"true\"}"
))
.
andExpect
(
header
(
"Authorization"
,
"Basic "
+
Base64Utils
.
encodeToString
(
String
.
format
(
"%s:%s"
,
this
.
properties
.
getUsername
(),
this
.
properties
.
getPassword
()).
getBytes
())))
.
andExpect
(
header
(
"Content-Type"
,
MediaType
.
APPLICATION_JSON
.
toString
())).
andRespond
(
withSuccess
());
Set
<
String
>
artifactDigests
=
Collections
.
singleton
(
"602e20176706d3cc7535f01ffdbe91b270ae5014"
);
assertThatExceptionOfType
(
DistributionTimeoutException
.
class
)
.
isThrownBy
(()
->
this
.
service
.
distribute
(
"libs-release-local"
,
releaseInfo
));
.
isThrownBy
(()
->
this
.
service
.
distribute
(
"libs-release-local"
,
releaseInfo
,
artifactDigests
));
this
.
server
.
verify
();
verify
(
this
.
bintrayService
,
times
(
1
)).
isDistributionComplete
(
releaseInfo
);
InOrder
ordered
=
inOrder
(
this
.
bintrayService
);
ordered
.
verify
(
this
.
bintrayService
).
isDistributionComplete
(
releaseInfo
,
artifactDigests
,
SHORT_TIMEOUT
);
ordered
.
verify
(
this
.
bintrayService
).
isDistributionComplete
(
releaseInfo
,
artifactDigests
,
LONG_TIMEOUT
);
}
private
ReleaseInfo
getReleaseInfo
()
{
...
...
ci/images/releasescripts/src/test/java/io/spring/concourse/releasescripts/bintray/BintrayServiceTests.java
View file @
209c5c40
...
...
@@ -16,6 +16,10 @@
package
io
.
spring
.
concourse
.
releasescripts
.
bintray
;
import
java.time.Duration
;
import
java.util.LinkedHashSet
;
import
java.util.Set
;
import
io.spring.concourse.releasescripts.ReleaseInfo
;
import
io.spring.concourse.releasescripts.sonatype.SonatypeProperties
;
import
io.spring.concourse.releasescripts.sonatype.SonatypeService
;
...
...
@@ -28,7 +32,6 @@ import org.springframework.boot.test.autoconfigure.web.client.RestClientTest;
import
org.springframework.boot.test.mock.mockito.MockBean
;
import
org.springframework.core.io.ClassPathResource
;
import
org.springframework.http.HttpMethod
;
import
org.springframework.http.HttpStatus
;
import
org.springframework.http.MediaType
;
import
org.springframework.test.web.client.ExpectedCount
;
import
org.springframework.test.web.client.MockRestServiceServer
;
...
...
@@ -41,7 +44,6 @@ import static org.springframework.test.web.client.match.MockRestRequestMatchers.
import
static
org
.
springframework
.
test
.
web
.
client
.
match
.
MockRestRequestMatchers
.
header
;
import
static
org
.
springframework
.
test
.
web
.
client
.
match
.
MockRestRequestMatchers
.
method
;
import
static
org
.
springframework
.
test
.
web
.
client
.
match
.
MockRestRequestMatchers
.
requestTo
;
import
static
org
.
springframework
.
test
.
web
.
client
.
response
.
MockRestResponseCreators
.
withStatus
;
import
static
org
.
springframework
.
test
.
web
.
client
.
response
.
MockRestResponseCreators
.
withSuccess
;
/**
...
...
@@ -75,15 +77,15 @@ class BintrayServiceTests {
@Test
void
isDistributionComplete
()
throws
Exception
{
this
.
server
.
expect
(
requestTo
(
String
.
format
(
"https://api.bintray.com/packages/%s/%s/%s/versions/%s/files?include_unpublished=%s"
,
this
.
properties
.
getSubject
(),
this
.
properties
.
getRepo
(),
"example"
,
"1.1.0.RELEASE"
,
1
)))
.
andRespond
(
withStatus
(
HttpStatus
.
NOT_FOUND
));
setupGetPackageFiles
(
1
,
"all-package-files.json"
);
setupGetPackageFiles
(
0
,
"published-files.json"
);
setupGetPackageFiles
(
0
,
"no-package-files.json"
);
setupGetPackageFiles
(
0
,
"some-package-files.json"
);
setupGetPackageFiles
(
0
,
"all-package-files.json"
);
assertThat
(
this
.
service
.
isDistributionComplete
(
getReleaseInfo
())).
isTrue
();
Set
<
String
>
digests
=
new
LinkedHashSet
<>();
digests
.
add
(
"602e20176706d3cc7535f01ffdbe91b270ae5012"
);
digests
.
add
(
"602e20176706d3cc7535f01ffdbe91b270ae5013"
);
digests
.
add
(
"602e20176706d3cc7535f01ffdbe91b270ae5014"
);
assertThat
(
this
.
service
.
isDistributionComplete
(
getReleaseInfo
(),
digests
,
Duration
.
ofMinutes
(
1
),
Duration
.
ZERO
))
.
isTrue
();
this
.
server
.
verify
();
}
...
...
ci/images/releasescripts/src/test/java/io/spring/concourse/releasescripts/command/DistributeCommandTests.java
View file @
209c5c40
...
...
@@ -16,6 +16,8 @@
package
io
.
spring
.
concourse
.
releasescripts
.
command
;
import
java.util.Set
;
import
com.fasterxml.jackson.databind.DeserializationFeature
;
import
com.fasterxml.jackson.databind.ObjectMapper
;
import
io.spring.concourse.releasescripts.ReleaseInfo
;
...
...
@@ -54,7 +56,7 @@ class DistributeCommandTests {
void
setup
()
{
MockitoAnnotations
.
initMocks
(
this
);
this
.
objectMapper
=
new
ObjectMapper
().
disable
(
DeserializationFeature
.
FAIL_ON_UNKNOWN_PROPERTIES
);
this
.
command
=
new
DistributeCommand
(
this
.
service
,
objectMapper
);
this
.
command
=
new
DistributeCommand
(
this
.
service
,
this
.
objectMapper
);
}
@Test
...
...
@@ -76,15 +78,20 @@ class DistributeCommandTests {
}
@Test
@SuppressWarnings
(
"unchecked"
)
void
distributeWhenReleaseTypeReleaseShouldCallService
()
throws
Exception
{
ArgumentCaptor
<
ReleaseInfo
>
captor
=
ArgumentCaptor
.
forClass
(
ReleaseInfo
.
class
);
ArgumentCaptor
<
ReleaseInfo
>
releaseInfoCaptor
=
ArgumentCaptor
.
forClass
(
ReleaseInfo
.
class
);
ArgumentCaptor
<
Set
<
String
>>
artifactDigestCaptor
=
ArgumentCaptor
.
forClass
(
Set
.
class
);
this
.
command
.
run
(
new
DefaultApplicationArguments
(
"distribute"
,
"RELEASE"
,
getBuildInfoLocation
()));
verify
(
this
.
service
).
distribute
(
eq
(
ReleaseType
.
RELEASE
.
getRepo
()),
captor
.
capture
());
ReleaseInfo
releaseInfo
=
captor
.
getValue
();
verify
(
this
.
service
).
distribute
(
eq
(
ReleaseType
.
RELEASE
.
getRepo
()),
releaseInfoCaptor
.
capture
(),
artifactDigestCaptor
.
capture
());
ReleaseInfo
releaseInfo
=
releaseInfoCaptor
.
getValue
();
assertThat
(
releaseInfo
.
getBuildName
()).
isEqualTo
(
"example"
);
assertThat
(
releaseInfo
.
getBuildNumber
()).
isEqualTo
(
"example-build-1"
);
assertThat
(
releaseInfo
.
getGroupId
()).
isEqualTo
(
"org.example.demo"
);
assertThat
(
releaseInfo
.
getVersion
()).
isEqualTo
(
"2.2.0"
);
Set
<
String
>
artifactDigests
=
artifactDigestCaptor
.
getValue
();
assertThat
(
artifactDigests
).
containsExactly
(
"aaaaaaaaa85f5c5093721f3ed0edda8ff8290yyyyyyyyyy"
);
}
private
String
getBuildInfoLocation
()
throws
Exception
{
...
...
ci/images/releasescripts/src/test/java/io/spring/concourse/releasescripts/sonatype/SonatypeServiceTests.java
View file @
209c5c40
...
...
@@ -45,9 +45,6 @@ class SonatypeServiceTests {
@Autowired
private
SonatypeService
service
;
@Autowired
private
SonatypeProperties
properties
;
@Autowired
private
MockRestServiceServer
server
;
...
...
@@ -60,7 +57,8 @@ class SonatypeServiceTests {
void
artifactsPublishedWhenPublishedShouldReturnTrue
()
{
this
.
server
.
expect
(
requestTo
(
String
.
format
(
"https://oss.sonatype.org/service/local/repositories/releases/content/org/springframework/boot/spring-boot/%s/spring-boot-%s.jar.sha1"
,
"1.1.0.RELEASE"
,
"1.1.0.RELEASE"
))).
andExpect
(
method
(
HttpMethod
.
GET
)).
andRespond
(
withSuccess
());
"1.1.0.RELEASE"
,
"1.1.0.RELEASE"
))).
andExpect
(
method
(
HttpMethod
.
GET
))
.
andRespond
(
withSuccess
().
body
(
"ce8d8b6838ecceb68962b975b18682f4237ccf71"
.
getBytes
()));
boolean
published
=
this
.
service
.
artifactsPublished
(
getReleaseInfo
());
assertThat
(
published
).
isTrue
();
this
.
server
.
verify
();
...
...
ci/images/releasescripts/src/test/resources/io/spring/concourse/releasescripts/bintray/all-package-files.json
View file @
209c5c40
...
...
@@ -8,7 +8,7 @@
"owner"
:
"jfrog"
,
"created"
:
"ISO8601 (yyyy-MM-dd'T'HH:mm:ss.SSSZ)"
,
"size"
:
1234
,
"sha
1
"
:
"602e20176706d3cc7535f01ffdbe91b270ae5012"
"sha
256
"
:
"602e20176706d3cc7535f01ffdbe91b270ae5012"
},
{
"name"
:
"nutcracker-1.1.pom"
,
...
...
@@ -19,7 +19,7 @@
"owner"
:
"jfrog"
,
"created"
:
"ISO8601 (yyyy-MM-dd'T'HH:mm:ss.SSSZ)"
,
"size"
:
1234
,
"sha
1"
:
"602e20176706d3cc7535f01ffdbe91b270ae5012
"
"sha
256"
:
"602e20176706d3cc7535f01ffdbe91b270ae5013
"
},
{
"name"
:
"nutcracker-1.1.jar"
,
...
...
@@ -30,6 +30,6 @@
"owner"
:
"jfrog"
,
"created"
:
"ISO8601 (yyyy-MM-dd'T'HH:mm:ss.SSSZ)"
,
"size"
:
1234
,
"sha
1"
:
"602e20176706d3cc7535f01ffdbe91b270ae5012
"
"sha
256"
:
"602e20176706d3cc7535f01ffdbe91b270ae5014
"
}
]
\ No newline at end of file
ci/images/releasescripts/src/test/resources/io/spring/concourse/releasescripts/bintray/no-package-files.json
0 → 100644
View file @
209c5c40
[]
\ No newline at end of file
ci/images/releasescripts/src/test/resources/io/spring/concourse/releasescripts/bintray/
published
-files.json
→
ci/images/releasescripts/src/test/resources/io/spring/concourse/releasescripts/bintray/
some-package
-files.json
View file @
209c5c40
...
...
@@ -8,6 +8,6 @@
"owner"
:
"jfrog"
,
"created"
:
"ISO8601 (yyyy-MM-dd'T'HH:mm:ss.SSSZ)"
,
"size"
:
1234
,
"sha
1
"
:
"602e20176706d3cc7535f01ffdbe91b270ae5012"
"sha
256
"
:
"602e20176706d3cc7535f01ffdbe91b270ae5012"
}
]
\ No newline at end of file
ci/scripts/promote.sh
View file @
209c5c40
...
...
@@ -5,11 +5,11 @@ source $(dirname $0)/common.sh
version
=
$(
cat
artifactory-repo/build-info.json | jq
-r
'.buildInfo.modules[0].id'
|
sed
's/.*:.*:\(.*\)/\1/'
)
export
BUILD_INFO_LOCATION
=
$(
pwd
)
/artifactory-repo/build-info.json
java
-jar
/spring-boot-release-scripts.jar promote
$RELEASE_TYPE
$BUILD_INFO_LOCATION
>
/dev/null
||
{
exit
1
;
}
java
-jar
/spring-boot-release-scripts.jar promote
$RELEASE_TYPE
$BUILD_INFO_LOCATION
||
{
exit
1
;
}
java
-jar
/spring-boot-release-scripts.jar distribute
$RELEASE_TYPE
$BUILD_INFO_LOCATION
>
/dev/null
||
{
exit
1
;
}
java
-jar
/spring-boot-release-scripts.jar distribute
$RELEASE_TYPE
$BUILD_INFO_LOCATION
||
{
exit
1
;
}
java
-jar
/spring-boot-release-scripts.jar publishGradlePlugin
$RELEASE_TYPE
$BUILD_INFO_LOCATION
>
/dev/null
||
{
exit
1
;
}
java
-jar
/spring-boot-release-scripts.jar publishGradlePlugin
$RELEASE_TYPE
$BUILD_INFO_LOCATION
||
{
exit
1
;
}
echo
"Promotion complete"
echo
$version
>
version/version
ci/scripts/sync-to-maven-central.sh
View file @
209c5c40
...
...
@@ -2,7 +2,7 @@
export
BUILD_INFO_LOCATION
=
$(
pwd
)
/artifactory-repo/build-info.json
version
=
$(
cat
artifactory-repo/build-info.json | jq
-r
'.buildInfo.modules[0].id'
|
sed
's/.*:.*:\(.*\)/\1/'
)
java
-jar
/spring-boot-release-scripts.jar syncToCentral
"RELEASE"
$BUILD_INFO_LOCATION
>
/dev/null
||
{
exit
1
;
}
java
-jar
/spring-boot-release-scripts.jar syncToCentral
"RELEASE"
$BUILD_INFO_LOCATION
||
{
exit
1
;
}
echo
"Sync complete"
echo
$version
>
version/version
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment