Compare commits

...

120 Commits
2.5.6 ... 2.6.1

Author SHA1 Message Date
Eleftheria Stein
70e0c6d22d Update antora version 2021-12-21 15:44:58 +02:00
Eleftheria Stein
61bf2eca49 Release 2.6.1 2021-12-21 15:12:26 +02:00
Eleftheria Stein
59923121f0 Make gretty samples compatible with logback 1.2.9
Explicitly reference the logback.xml file to prevent gretty from configuring the defaults using groovy.
2021-12-21 11:10:33 +02:00
Eleftheria Stein
b5f8e29585 Upgrade test dependencies 2021-12-21 11:10:22 +02:00
Eleftheria Stein
307a1f0dde Upgrade Hazelcast 4 to 4.2.3
Closes gh-1979
2021-12-21 10:09:06 +02:00
Eleftheria Stein
ced2d8421c Upgrade Spring Security to 5.6.1
Closes gh-1978
2021-12-21 10:08:25 +02:00
Eleftheria Stein
d98ff97e1a Upgrade Spring Framework to 5.3.14
Closes gh-1977
2021-12-21 10:03:02 +02:00
Eleftheria Stein
757175516f Upgrade Reactor to 2020.0.14
Closes gh-1976
2021-12-21 10:02:30 +02:00
Eleftheria Stein
8ae55b7ee4 GitHub Actions uses spring-builds+github user
This is more clear than spring-builds user
2021-12-07 15:43:42 +01:00
Eleftheria Stein
1eb53ead9d Update README to include MongoDB
Issue gh-1901
2021-11-26 17:37:12 +01:00
Guillaume Husta
72159794f4 Doc : typo on Username _user-
user should be in italic
2021-11-19 14:56:56 +01:00
Eleftheria Stein
aaf122f3a6 Include 2.6.0 and 3.0 snapshots in reference docs 2021-11-17 11:28:54 +01:00
Eleftheria Stein
6f823805f2 Include 2.6.8 release in docs 2021-11-17 11:04:55 +01:00
Eleftheria Stein
7807aa9f3c Next development version 2021-11-16 18:56:49 +01:00
Eleftheria Stein
76924bc923 Release 2.6.0 2021-11-16 14:21:51 +01:00
Eleftheria Stein
134f89dd41 Upgrade test dependencies 2021-11-16 13:57:45 +01:00
Eleftheria Stein
33812f7197 Upgrade MongoDB to 4.4.0
Closes gh-1967
2021-11-16 13:56:44 +01:00
Eleftheria Stein
bcf17ba3b7 Upgrade samples to Spring Boot 2.5.6
Closes gh-1966
2021-11-16 13:37:41 +01:00
Eleftheria Stein
98f656ad46 Upgrade Jackson to 2.13.0
Closes gh-1965
2021-11-16 13:11:51 +01:00
Eleftheria Stein
7832942752 Upgrade Spring Security to 5.6.0
Closes gh-1964
2021-11-16 13:07:43 +01:00
Eleftheria Stein
722069a5f8 Upgrade Spring Data to 2021.1.0
Closes gh-1963
2021-11-16 13:06:41 +01:00
Eleftheria Stein
addbdbc1a2 Upgrade Spring Framework to 5.3.13
Closes gh-1962
2021-11-16 13:05:51 +01:00
Eleftheria Stein
004466ed07 Upgrade Reactor to 2020.0.13
Closes gh-1961
2021-11-16 13:04:32 +01:00
Eleftheria Stein
aeb5bc545c Update to Gradle 7.3
Closes gh-1959
2021-11-15 09:59:22 +01:00
Rob Winch
37451d945c Update Algolia index to uses reference 2021-11-11 10:06:13 -06:00
Rob Winch
9e5b1951d5 Antora /reference/ suffix to site URL 2021-11-11 09:48:38 -06:00
Rob Winch
406f11c9ab Antora Fix site url 2021-11-11 09:43:11 -06:00
Rob Winch
beeb8769a6 rsync --delete old files 2021-11-11 09:40:16 -06:00
Rob Winch
a60b54812a Fix Antora version
- 2.6.0
- prelease -SNAPSHOT
2021-11-11 09:32:18 -06:00
Rob Winch
59bfa6bbc7 Antora component name to ROOT 2021-11-11 09:31:42 -06:00
Rob Winch
353f635470 Use correct output directory for docs deploy 2021-11-10 17:40:23 -06:00
Rob Winch
dd63b760bc Use ALGOLIA_WRITE_API_KEY 2021-11-10 15:33:24 -06:00
Rob Winch
d8347bcdb1 Deploy Docs 2021-11-10 14:13:05 -06:00
Rob Winch
a51f1e1679 Add Algolia Index 2021-11-10 14:13:05 -06:00
Rob Winch
98a07a16d3 Generate and Request Reference Build 2021-11-10 14:13:05 -06:00
Rob Winch
d756446015 Add playbook to Spring Session 2021-11-10 14:13:05 -06:00
Eleftheria Stein
147ea82a43 Use BDD mockito style
Issue gh-1946
2021-11-09 14:36:53 +01:00
Eleftheria Stein
b4bbbe8bd6 Fix Javadoc tag order
Issue gh-1946
2021-11-09 14:36:53 +01:00
Eleftheria Stein
ea1c619918 Fix whitespace
Issue gh-1946
2021-11-09 14:36:53 +01:00
Eleftheria Stein
5c2eb3af1c Remove unnecessary non-Javadoc keyword
Issue gh-1946
2021-11-09 14:36:53 +01:00
Eleftheria Stein
09a74bf165 Upgrade checkstyle to 0.0.29
Closes gh-1946
2021-11-09 13:41:50 +01:00
Rob Winch
619ad95ef7 Add spring-boot-version to docs 2021-11-08 13:46:27 -06:00
Rob Winch
6e6695bad9 Direct Mapping of Documentation Version 2021-11-08 09:51:54 -06:00
Eleftheria Stein
5fdbfce4c2 Update Gradle to 7.2
Closes gh-1944
2021-11-02 14:28:31 +01:00
Eleftheria Stein
a5033f721c Use local propdeps plugin
Issue gh-1944
2021-11-02 14:12:19 +01:00
Eleftheria Stein
23882acf97 Remove dependency on JUnit 4
Closes gh-1879
2021-11-01 10:37:18 +01:00
Eleftheria Stein
2110ef0c2d Fix scm attributes in maven pom.xml
Closes gh-1897
2021-10-29 15:40:06 +02:00
Eleftheria Stein
e5bc746e37 Update GitHub Actions to use publishArtifacts
Closes gh-1943
2021-10-29 14:10:24 +02:00
Eleftheria Stein
84fab2e2a9 Add buildSrc including build conventions plugins
Closes gh-1942
2021-10-29 13:30:29 +02:00
Eleftheria Stein
b6f90640a6 Use updated version names in docs
Issue gh-1942
2021-10-29 13:27:12 +02:00
Eleftheria Stein
327e7fb9b7 Add missing method for docs
Issue gh-1942
2021-10-28 11:19:48 +02:00
Eleftheria Stein
d3a19efb89 Resolve versions in docs from classpath
Issue gh-1942
2021-10-28 10:56:24 +02:00
Rob Winch
0004664603 Fix symlink to not end in / 2021-10-27 16:05:13 -05:00
Rob Winch
1cdf77330c Fix missing attribute
- Use spring-session-data-mongodb-dir
- Update example to use symlink location
2021-10-26 20:50:57 -05:00
Rob Winch
517c767bf6 Use dynamic version 2021-10-26 16:36:37 -05:00
Eleftheria Stein
b79b069178 Fix API link in docs
Closes gh-1940
2021-10-26 10:17:36 +02:00
Rob Winch
fee6878ef1 Extract the branch name for generated docs 2021-10-25 16:10:56 -05:00
Rob Winch
31caeb24f7 Fix version to have space in yml 2021-10-21 12:07:40 -05:00
Rob Winch
7798d6bbf2 Use version in URLs 2021-10-21 11:07:31 -05:00
Eleftheria Stein
cb16e2ff9e Next development version 2021-10-20 13:40:30 +02:00
Eleftheria Stein
e02a38965f Release 2.5.0-RC2 2021-10-20 12:56:36 +02:00
Greg L. Turnquist
bf139dbbb3 Introduce Spring Session MongoDB
* Migrate the module's code back into this project.
* Fold the documentation in.
* Update to current Gradle conventions.
* Reformat to match styling.
2021-10-20 11:57:27 +02:00
Eleftheria Stein
d10c18eb88 Next development version 2021-10-19 11:51:02 +02:00
Eleftheria Stein
8af09781a0 Release 2.6.0-RC1 2021-10-19 11:38:25 +02:00
Eleftheria Stein
845c7aca84 Upgrade test dependencies 2021-10-19 11:14:03 +02:00
Eleftheria Stein
b05575722c Upgrade samples to Spring Boot 2.5.5
Closes gh-1929
2021-10-19 10:54:01 +02:00
Eleftheria Stein
ee0e03b91e Upgrade Spring Security to 5.6.0-RC1
Closes gh-1928
2021-10-19 10:39:06 +02:00
Eleftheria Stein
7864f9c4cc Upgrade Spring Framework to 5.3.11
Closes gh-1927
2021-10-19 10:37:19 +02:00
Eleftheria Stein
227aee8e3a Upgrade Reactor to 2020.0.12
Closes gh-1925
2021-10-19 10:36:09 +02:00
Eleftheria Stein
bf2aaa0033 Upgrade Spring Data to 2021.1.0-RC1
Closes gh-1926
2021-10-19 10:35:39 +02:00
Eleftheria Stein
eb9f62a437 Update principal index on session ID change
Closes gh-1791
2021-10-14 17:49:56 +02:00
Rob Winch
418cb60f39 Add antora gradle plugin
You can now run the following to generate the antora site

./gradlew antora

It will appear at build/site/index.html
2021-10-11 09:17:50 -05:00
Rob Winch
4339b8ae9d Fix local-antora-playbook.yml
- Point to generated content
- Point to remote antora-ui-spring
2021-10-11 09:16:55 -05:00
Eleftheria Stein
63f706dbf9 Fix Hazelcast session with flush mode immediate
Closes gh-1921
2021-10-05 10:59:06 +02:00
Eleftheria Stein
beb7b334c4 Fix link to Spring Security remember-me docs
Closes gh-1915
2021-10-04 16:34:52 +02:00
Eleftheria Stein
a64a11ba03 Tests for Hazelcast flush mode immediate
Closes gh-1801
2021-10-01 17:02:33 +02:00
slondono
661ecaf371 Store Principal Name Index in the Hazelcast Session delta
Issue gh-1801
2021-10-01 17:02:33 +02:00
Rob Winch
378ba6db2c Use GH_ACTIONS_REPO_TOKEN 2021-09-27 13:22:20 -05:00
zhaokai
9659f1f571 Modify to support negative numbers 2021-09-27 14:40:16 +02:00
Eleftheria Stein
919a2a5c49 Upgrade back to Spring Boot 2.5.3 2021-09-24 16:46:32 +02:00
Rob Winch
4dee8063c6 Use Antora
Closes gh-1237
2021-09-23 16:44:39 -05:00
Eleftheria Stein
9ad871a30b Add setter for autowired field in SpringWebSessionConfiguration
Closes gh-1918
2021-09-23 14:54:22 +02:00
Eleftheria Stein
e7d58f6b03 Increase session timeout in Hazelcast tests
It's possible that the session is expiring before the assertions can be made in the tests, causing them to fail.

Issue gh-1912
2021-09-08 12:04:26 +02:00
Rob Winch
3d118242ee Better hiearchy with Samples nav 2021-08-31 10:38:54 -05:00
Rob Winch
0c00ff0598 Fix Samples nav 2021-08-30 19:12:50 -05:00
Rob Winch
3d93bfc28b Fix Boot Samples Nav 2021-08-30 19:08:46 -05:00
Rob Winch
297ff83775 Added missing versions 2021-08-30 19:07:17 -05:00
Rob Winch
1fc2c430f1 Fix antora name 2021-08-30 19:01:52 -05:00
Rob Winch
5757e94658 Generated antora.yml 2021-08-30 18:55:11 -05:00
Rob Winch
8cc22a1712 Use versionless URL 2021-08-30 17:17:34 -05:00
Vedran Pavic
79fbca24eb Make Hazelcast session repository bean factory return type more specific
The declared return type of Hazelcast session repository bean factory method (i.e. HazelcastHttpSessionConfiguration#sessionRepository) was changed to SessionRepository<?> when support for Hazelcast 4 was added. This breaks Spring Boot's ability to auto-configure sessions endpoint, which is @ConditionalOnBean(FindByIndexNameSessionRepository.class), as the current return type is not specific enough to satisfy this condition.

This commit changes the return type of Hazelcast session repository bean factory method to FindByIndexNameSessionRepository<?>.

Closes: gh-1905
2021-08-27 01:51:55 +02:00
Vedran Pavic
5b7aee7199 Fix Spring Boot based Hazelcast samples
This commit removes unused Hazelcast client dependencies and test support from Spring Boot based Hazelcast samples.

Closes: gh-1902
2021-08-27 00:46:23 +02:00
Andreas Kasparek
c5bffde790 Always set time-to-live within entry processor
Closes gh-1899
2021-08-25 13:16:08 +02:00
Rob Winch
aee65ffec8 Remove :toc: left
This causes an extra toc that covers the left navigation
2021-08-20 14:29:21 -05:00
Rob Winch
00abd345ac Add Dispatch to build reference 2021-08-18 11:27:45 -05:00
Rob Winch
0864140dda Clean up introduction 2021-08-18 11:19:21 -05:00
Rob Winch
7babddf15f Fix default xref text 2021-08-18 11:16:36 -05:00
Rob Winch
764fc4eea6 <<>> to xref 2021-08-18 11:15:27 -05:00
Rob Winch
26419e2149 Cleanup Antora 2021-08-18 11:10:33 -05:00
Eleftheria Stein
585d3695ad Point to spring-session tag in GitHub issue template
Issue: gh-1897
2021-08-18 14:06:12 +02:00
Eleftheria Stein
db8a3aa604 Next development version 2021-08-17 15:52:29 +02:00
Eleftheria Stein
d0fabc0a35 Release 2.6.0-M1 2021-08-17 15:50:52 +02:00
Eleftheria Stein
cae8b51eab Upgrade test dependencies 2021-08-17 15:14:03 +02:00
Eleftheria Stein
2236449635 Revert "Upgrade test dependencies"
This reverts commit 9fde87c11b.
2021-08-17 14:07:13 +02:00
Eleftheria Stein
d862836d41 Upgrade Hazelcast 4 to 4.2.2
Closes gh-1887
2021-08-17 13:45:48 +02:00
Eleftheria Stein
4008afe47b Upgrade Spring Security to 5.6.0-M2
Closes gh-1884
2021-08-17 13:29:58 +02:00
Eleftheria Stein
9fde87c11b Upgrade test dependencies 2021-08-17 13:23:08 +02:00
Rob Winch
faa6c441fa Antora 2021-08-16 15:44:15 -05:00
Eleftheria Stein
93c62104ee Make Websocket sample compatible with Spring Boot 2.5.3
Closes gh-1886
2021-08-16 15:08:38 +02:00
Eleftheria Stein
8fdcfc28bc Upgrade samples to Spring Boot 2.5.3
Closes gh-1885
2021-08-16 15:08:09 +02:00
Eleftheria Stein
1f6445999f Upgrade Spring Framework to 5.3.9
Closes gh-1882
2021-08-16 14:00:02 +02:00
Eleftheria Stein
cf4aeae02a Upgrade Spring Data to 2021.1.0-M2
Closes gh-1883
2021-08-16 13:59:25 +02:00
Eleftheria Stein
f8dcee7304 Upgrade Reactor to 2020.0.10
Closes gh-1881
2021-08-16 13:57:00 +02:00
Eleftheria Stein
971a2d17d9 Set cookie path to context path without trailing slash
Closes gh-1863
2021-07-20 10:00:53 +02:00
Ellie Bahadori
8b5b3701da Prevent builds from running on forks
Resolves gh-1678
2021-07-06 17:19:30 +02:00
Eleftheria Stein
21c9fb0cfa Point "What's New" section to Wiki
Closes gh-1878
2021-06-29 16:08:03 +02:00
Jay Bryant
33993b2ff6 Add links to Mongo and Geode docs
Spring Session for MongoDB and Geodo have their own reference guides.
This PR adds links to them.
2021-06-14 13:34:36 +02:00
Jay Bryant
9f4a723160 Add links to the other documentation format
Add a link from the HTML to the PDF and vice-versa.
2021-06-04 08:55:57 +02:00
Eleftheria Stein
25032fbd61 Use GPG_PRIVATE_KEY directly in build
Closes gh-1861
2021-05-31 15:42:16 +03:00
Eleftheria Stein
d195579ced Next development version 2021-05-19 00:41:23 +02:00
346 changed files with 17452 additions and 2127 deletions

17
.github/ISSUE_TEMPLATE.md vendored Normal file
View File

@@ -0,0 +1,17 @@
<!--
!!! For Security Vulnerabilities, please go to https://spring.io/security-policy !!!
-->
**Affects:** \<Spring Framework version>
---
<!--
Thanks for taking the time to create an issue. Please read the following:
- Questions should be asked on Stack Overflow.
- For bugs, specify affected versions and explain what you are trying to do.
- For enhancements, provide context and describe the problem.
Issue or Pull Request? Create only one, not both. GitHub treats them as the same.
If unsure, start with an issue, and if you submit a pull request later, the
issue will be closed as superseded.
-->

View File

@@ -1,5 +1,5 @@
blank_issues_enabled: false
contact_links:
- name: Community Support
url: https://stackoverflow.com/questions/tagged/spring-security
url: https://stackoverflow.com/questions/tagged/spring-session
about: Please ask and answer questions on StackOverflow with the tag spring-session

20
.github/actions/algolia-config.json vendored Normal file
View File

@@ -0,0 +1,20 @@
{
"index_name": "session-docs",
"start_urls": [
"https://docs.spring.io/spring-session/reference/"
],
"selectors": {
"lvl0": {
"selector": "//nav[@class='crumbs']//li[@class='crumb'][last()-1]",
"type": "xpath",
"global": true,
"default_value": "Home"
},
"lvl1": ".doc h1",
"lvl2": ".doc h2",
"lvl3": ".doc h3",
"lvl4": ".doc h4",
"text": ".doc p, .doc td.content, .doc th.tableblock"
}
}

20
.github/actions/algolia-deploy.sh vendored Executable file
View File

@@ -0,0 +1,20 @@
#!/bin/bash
HOST="$1"
HOST_PATH="$2"
SSH_PRIVATE_KEY="$3"
SSH_KNOWN_HOST="$4"
if [ "$#" -ne 4 ]; then
echo -e "not enough arguments USAGE:\n\n$0 \$HOST \$HOST_PATH \$SSH_PRIVATE_KEY \$SSH_KNOWN_HOSTS \n\n" >&2
exit 1
fi
# Use a non-default path to avoid overriding when testing locally
SSH_PRIVATE_KEY_PATH=~/.ssh/github-actions-docs
install -m 600 -D /dev/null "$SSH_PRIVATE_KEY_PATH"
echo "$SSH_PRIVATE_KEY" > "$SSH_PRIVATE_KEY_PATH"
echo "$SSH_KNOWN_HOST" > ~/.ssh/known_hosts
rsync --delete -avze "ssh -i $SSH_PRIVATE_KEY_PATH" spring-session-docs/build/site/ "$HOST:$HOST_PATH"
rm -f "$SSH_PRIVATE_KEY_PATH"

21
.github/actions/algolia-docsearch-scraper.sh vendored Executable file
View File

@@ -0,0 +1,21 @@
#!/bin/bash
###
# Docs
# config.json https://docsearch.algolia.com/docs/config-file
# Run the crawler https://docsearch.algolia.com/docs/run-your-own/#run-the-crawl-from-the-docker-image
### USAGE
if [ "$#" -ne 3 ]; then
echo -e "not enough arguments USAGE:\n\n$0 \$ALGOLIA_APPLICATION_ID \$ALGOLIA_API_KEY \$CONFIG_FILE\n\n" >&2
exit 1
fi
# Script Parameters
APPLICATION_ID=$1
API_KEY=$2
CONFIG_FILE=$3
#### Script
script_dir=$(dirname $0)
docker run -e "APPLICATION_ID=$APPLICATION_ID" -e "API_KEY=$API_KEY" -e "CONFIG=$(cat $CONFIG_FILE | jq -r tostring)" algolia/docsearch-scraper

5
.github/actions/dispatch.sh vendored Executable file
View File

@@ -0,0 +1,5 @@
REPOSITORY_REF="$1"
TOKEN="$2"
curl -H "Accept: application/vnd.github.everest-preview+json" -H "Authorization: token ${TOKEN}" --request POST --data '{"event_type": "request-build-reference"}' https://api.github.com/repos/${REPOSITORY_REF}/dispatches
echo "Requested Build for $REPOSITORY_REF"

16
.github/workflows/algolia-index.yml vendored Normal file
View File

@@ -0,0 +1,16 @@
name: Update Algolia Index
on:
schedule:
- cron: '0 10 * * *' # Once per day at 10am UTC
workflow_dispatch: # Manual trigger
jobs:
update:
name: Update Algolia Index
runs-on: ubuntu-latest
steps:
- name: Checkout Source
uses: actions/checkout@v2
- name: Update Index
run: ${GITHUB_WORKSPACE}/.github/actions/algolia-docsearch-scraper.sh "${{ secrets.ALGOLIA_APPLICATION_ID }}" "${{ secrets.ALGOLIA_WRITE_API_KEY }}" "${GITHUB_WORKSPACE}/.github/actions/algolia-config.json"

30
.github/workflows/antora-generate.yml vendored Normal file
View File

@@ -0,0 +1,30 @@
name: Generate Antora Files and Request Build
on:
push:
branches-ignore:
- 'gh-pages'
env:
GH_ACTIONS_REPO_TOKEN: ${{ secrets.GH_ACTIONS_REPO_TOKEN }}
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout Source
uses: actions/checkout@v2
- name: Generate antora.yml
run: ./gradlew :spring-session-docs:generateAntora
- name: Extract Branch Name
id: extract_branch_name
run: echo "##[set-output name=generated_branch_name;]$(echo ${GITHUB_REPOSITORY}/${GITHUB_REF##*/})"
- name: Push generated antora files to the spring-generated-docs
uses: JamesIves/github-pages-deploy-action@4.1.4
with:
branch: ${{ steps.extract_branch_name.outputs.generated_branch_name }} # The branch the action should deploy to.
folder: "spring-session-docs/build/generateAntora" # The folder the action should deploy.
repository-name: "spring-io/spring-generated-docs"
token: ${{ secrets.GH_ACTIONS_REPO_TOKEN }}
- name: Dispatch Build Request
run: ${GITHUB_WORKSPACE}/.github/actions/dispatch.sh 'spring-projects/spring-session' "$GH_ACTIONS_REPO_TOKEN"

View File

@@ -19,6 +19,7 @@ jobs:
build:
name: Build
runs-on: ubuntu-latest
if: github.repository == 'spring-projects/spring-session'
strategy:
matrix:
jdk: [8, 11]
@@ -32,7 +33,7 @@ jobs:
- name: Setup gradle user name
run: |
mkdir -p ~/.gradle
echo 'systemProp.user.name=spring-builds' >> ~/.gradle/gradle.properties
echo 'systemProp.user.name=spring-builds+github' >> ~/.gradle/gradle.properties
- name: Cache Gradle packages
uses: actions/cache@v2
with:
@@ -48,6 +49,7 @@ jobs:
name: Deploy Artifacts
needs: [build]
runs-on: ubuntu-latest
if: github.repository == 'spring-projects/spring-session'
steps:
- uses: actions/checkout@v2
- name: Set up JDK
@@ -57,28 +59,25 @@ jobs:
- name: Setup gradle user name
run: |
mkdir -p ~/.gradle
echo 'systemProp.user.name=spring-builds' >> ~/.gradle/gradle.properties
echo 'systemProp.user.name=spring-builds+github' >> ~/.gradle/gradle.properties
- name: Deploy artifacts
run: |
export GRADLE_ENTERPRISE_CACHE_USERNAME="$GRADLE_ENTERPRISE_CACHE_USER"
export GRADLE_ENTERPRISE_CACHE_PASSWORD="$GRADLE_ENTERPRISE_CACHE_PASSWORD"
export GRADLE_ENTERPRISE_ACCESS_KEY="$GRADLE_ENTERPRISE_SECRET_ACCESS_KEY"
export VERSION_HEADER=$'Version: GnuPG v2\n\n'
export ORG_GRADLE_PROJECT_signingKey=${GPG_PRIVATE_KEY#"$VERSION_HEADER"}
export ORG_GRADLE_PROJECT_signingPassword="$GPG_PASSPHRASE"
./gradlew deployArtifacts -PossrhUsername="$OSSRH_TOKEN_USERNAME" -PossrhPassword="$OSSRH_TOKEN_PASSWORD" -PartifactoryUsername="$ARTIFACTORY_USERNAME" -PartifactoryPassword="$ARTIFACTORY_PASSWORD" --stacktrace --no-parallel
./gradlew finalizeDeployArtifacts -PossrhUsername="$OSSRH_TOKEN_USERNAME" -PossrhPassword="$OSSRH_TOKEN_PASSWORD" -PartifactoryUsername="$ARTIFACTORY_USERNAME" -PartifactoryPassword="$ARTIFACTORY_PASSWORD" --stacktrace --no-parallel
./gradlew publishArtifacts finalizeDeployArtifacts -PossrhUsername="$OSSRH_TOKEN_USERNAME" -PossrhPassword="$OSSRH_TOKEN_PASSWORD" -PartifactoryUsername="$ARTIFACTORY_USERNAME" -PartifactoryPassword="$ARTIFACTORY_PASSWORD" --stacktrace
env:
GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY_NO_HEADER }}
GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
OSSRH_TOKEN_USERNAME: ${{ secrets.OSSRH_TOKEN_USERNAME }}
OSSRH_TOKEN_PASSWORD: ${{ secrets.OSSRH_TOKEN_PASSWORD }}
ORG_GRADLE_PROJECT_signingKey: ${{ secrets.GPG_PRIVATE_KEY }}
ORG_GRADLE_PROJECT_signingPassword: ${{ secrets.GPG_PASSPHRASE }}
OSSRH_TOKEN_USERNAME: ${{ secrets.OSSRH_S01_TOKEN_USERNAME }}
OSSRH_TOKEN_PASSWORD: ${{ secrets.OSSRH_S01_TOKEN_PASSWORD }}
ARTIFACTORY_USERNAME: ${{ secrets.ARTIFACTORY_USERNAME }}
ARTIFACTORY_PASSWORD: ${{ secrets.ARTIFACTORY_PASSWORD }}
docs:
name: Deploy Docs
needs: [build]
runs-on: ubuntu-latest
if: github.repository == 'spring-projects/spring-session'
steps:
- uses: actions/checkout@v2
- name: Set up JDK
@@ -88,7 +87,7 @@ jobs:
- name: Setup gradle user name
run: |
mkdir -p ~/.gradle
echo 'systemProp.user.name=spring-builds' >> ~/.gradle/gradle.properties
echo 'systemProp.user.name=spring-builds+github' >> ~/.gradle/gradle.properties
- name: Deploy Docs
run: |
export GRADLE_ENTERPRISE_CACHE_USERNAME="$GRADLE_ENTERPRISE_CACHE_USER"

33
.github/workflows/deploy-reference.yml vendored Normal file
View File

@@ -0,0 +1,33 @@
name: Build & Deploy Reference
on:
repository_dispatch:
types: request-build-reference
schedule:
- cron: '0 10 * * *' # Once per day at 10am UTC
workflow_dispatch: # Manual trigger
jobs:
deploy:
name: deploy
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up JDK 11
uses: actions/setup-java@v2
with:
java-version: '11'
distribution: 'adopt'
cache: gradle
- name: Validate Gradle wrapper
uses: gradle/wrapper-validation-action@e6e38bacfdf1a337459f332974bb2327a31aaf4b
- name: Build with Gradle
run: ./gradlew :spring-session-docs:antora --stacktrace
- name: Cleanup Gradle Cache
# Remove some files from the Gradle cache, so they aren't cached by GitHub Actions.
# Restoring these files from a GitHub Actions cache might cause problems for future builds.
run: |
rm -f ~/.gradle/caches/modules-2/modules-2.lock
rm -f ~/.gradle/caches/modules-2/gc.properties
- name: Deploy
run: ${GITHUB_WORKSPACE}/.github/actions/algolia-deploy.sh "${{ secrets.DOCS_USERNAME }}@${{ secrets.DOCS_HOST }}" "/opt/www/domains/spring.io/docs/htdocs/spring-session/reference/" "${{ secrets.DOCS_SSH_KEY }}" "${{ secrets.DOCS_SSH_HOST_KEY }}"

View File

@@ -0,0 +1,10 @@
name: "Validate Gradle Wrapper"
on: [push, pull_request]
jobs:
validation:
name: "Validation"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: gradle/wrapper-validation-action@v1

View File

@@ -6,6 +6,7 @@ jobs:
build:
name: Build
runs-on: ubuntu-latest
if: github.repository == 'spring-projects/spring-session'
strategy:
matrix:
jdk: [8, 11]

View File

@@ -19,9 +19,9 @@ This Spring Session repository consists of the following modules:
* Spring Session Data Redis - provides `SessionRepository` and `ReactiveSessionRepository` implementation backed by Redis and configuration support
* Spring Session JDBC - provides `SessionRepository` implementation backed by a relational database and configuration support
* Spring Session Hazelcast - provides `SessionRepository` implementation backed by Hazelcast and configuration support
* Spring Session MongoDB - provides `SessionRepository` implementation backed by MongoDB and configuration support
Additional Spring Session modules can be found in the https://github.com/spring-projects/spring-session-data-mongodb[spring-session-data-mongodb] repository
and https://github.com/spring-projects/spring-session-data-geode[spring-session-data-geode] repository.
Additional Spring Session modules can be found in the https://github.com/spring-projects/spring-session-data-geode[spring-session-data-geode] repository.
== Getting Started

View File

@@ -4,7 +4,7 @@ buildscript {
snapshotBuild = version.endsWith('SNAPSHOT')
milestoneBuild = !(releaseBuild || snapshotBuild)
springBootVersion = '2.4.5'
springBootVersion = '2.5.6'
}
repositories {
@@ -22,7 +22,6 @@ buildscript {
}
dependencies {
classpath 'io.spring.gradle:spring-build-conventions:0.0.37'
classpath "org.springframework.boot:spring-boot-gradle-plugin:$springBootVersion"
}
}
@@ -43,3 +42,7 @@ subprojects {
useJUnitPlatform()
}
}
nohttp {
source.exclude "buildSrc/build/**"
}

87
buildSrc/build.gradle Normal file
View File

@@ -0,0 +1,87 @@
plugins {
id "java-gradle-plugin"
id "java"
id "groovy"
}
sourceCompatibility = 1.8
repositories {
jcenter()
gradlePluginPortal()
mavenCentral()
maven { url 'https://repo.spring.io/plugins-release/' }
}
sourceSets {
main {
java {
srcDirs = []
}
groovy {
srcDirs += ["src/main/java"]
}
}
}
gradlePlugin {
plugins {
managementConfiguration {
id = "io.spring.convention.management-configuration"
implementationClass = "io.spring.gradle.convention.ManagementConfigurationPlugin"
}
sagan {
id = "org.springframework.security.sagan"
implementationClass = "org.springframework.gradle.sagan.SaganPlugin"
}
githubMilestone {
id = "org.springframework.github.milestone"
implementationClass = "org.springframework.gradle.github.milestones.GitHubMilestonePlugin"
}
propdeps {
id = "org.springframework.propdeps"
implementationClass = "org.springframework.gradle.propdeps.PropDepsPlugin"
}
}
}
configurations {
implementation {
exclude module: 'groovy-all'
}
}
dependencies {
implementation 'com.google.code.gson:gson:2.8.8'
implementation 'net.sourceforge.saxon:saxon:9.1.0.8'
implementation localGroovy()
implementation 'io.github.gradle-nexus:publish-plugin:1.1.0'
implementation 'io.spring.gradle:dependency-management-plugin:1.0.10.RELEASE'
implementation 'io.projectreactor:reactor-core:3.4.11'
implementation 'com.apollographql.apollo:apollo-runtime:2.4.5'
implementation 'com.github.ben-manes:gradle-versions-plugin:0.38.0'
implementation 'com.github.spullara.mustache.java:compiler:0.9.10'
implementation 'io.spring.javaformat:spring-javaformat-gradle-plugin:0.0.15'
implementation 'io.spring.nohttp:nohttp-gradle:0.0.9'
implementation 'net.sourceforge.htmlunit:htmlunit:2.55.0'
implementation 'org.hidetake:gradle-ssh-plugin:2.10.1'
implementation 'org.jfrog.buildinfo:build-info-extractor-gradle:4.24.20'
implementation 'org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:2.7.1'
testImplementation platform('org.junit:junit-bom:5.8.1')
testImplementation "org.junit.jupiter:junit-jupiter-api"
testImplementation "org.junit.jupiter:junit-jupiter-params"
testImplementation "org.junit.jupiter:junit-jupiter-engine"
testImplementation 'org.apache.commons:commons-io:1.3.2'
testImplementation 'org.assertj:assertj-core:3.21.0'
testImplementation 'org.mockito:mockito-core:3.12.4'
testImplementation 'org.mockito:mockito-junit-jupiter:3.12.4'
testImplementation 'com.squareup.okhttp3:mockwebserver:3.14.9'
}
test {
onlyIf { !project.hasProperty("buildSrc.skipTests") }
useJUnitPlatform()
}

Binary file not shown.

View File

@@ -0,0 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

View File

@@ -0,0 +1,104 @@
/*
* Copyright 2002-2021 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. You may obtain a copy of
* the License at
*
* https://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 io.spring.gradle
import groovy.transform.CompileStatic
import groovy.transform.TypeChecked
import groovy.transform.TypeCheckingMode
import org.gradle.api.DefaultTask
import org.gradle.api.Task
import org.gradle.api.provider.Property
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.OutputDirectory
import org.gradle.api.tasks.TaskAction
/**
* Checkout a project template from a git repository.
*
* @author Marcus Da Coregio
*/
@CompileStatic
abstract class IncludeRepoTask extends DefaultTask {
private static final String DEFAULT_URI_PREFIX = 'https://github.com/'
/**
* Git repository to use. Will be prefixed with {@link #DEFAULT_URI_PREFIX} if it isn't already
* @return
*/
@Input
abstract Property<String> getRepository();
/**
* Git reference to use.
*/
@Input
abstract Property<String> getRef()
/**
* Directory where the project template should be copied.
*/
@OutputDirectory
final File outputDirectory = project.file("$project.buildDir/$name")
@TaskAction
void checkoutAndCopy() {
outputDirectory.deleteDir()
File checkoutDir = checkout(this, getRemoteUri(), ref.get())
moveToOutputDir(checkoutDir, outputDirectory)
}
private static File cleanTemporaryDir(Task task, File tmpDir) {
if (tmpDir.exists()) {
task.project.delete(tmpDir)
}
return tmpDir
}
static File checkout(Task task, String remoteUri, String ref) {
checkout(task, remoteUri, ref, task.getTemporaryDir())
}
@TypeChecked(TypeCheckingMode.SKIP)
static File checkout(Task task, String remoteUri, String ref, File checkoutDir) {
cleanTemporaryDir(task, checkoutDir)
task.project.exec {
commandLine = ["git", "clone", "--no-checkout", remoteUri, checkoutDir.absolutePath]
errorOutput = System.err
}
task.project.exec {
commandLine = ["git", "checkout", ref]
workingDir = checkoutDir
errorOutput = System.err
}
return checkoutDir
}
private static void moveToOutputDir(File tmpDir, File outputDirectory) {
File baseDir = tmpDir
baseDir.renameTo(outputDirectory)
}
private String getRemoteUri() {
String remoteUri = this.repository.get()
if (remoteUri.startsWith(DEFAULT_URI_PREFIX)) {
return remoteUri
}
return DEFAULT_URI_PREFIX + remoteUri
}
}

View File

@@ -0,0 +1,73 @@
/*
* Copyright 2002-2016 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. You may obtain a copy of
* the License at
*
* https://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 io.spring.gradle.convention;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.plugins.GroovyPlugin;
import org.gradle.api.plugins.JavaPlugin
import org.gradle.api.plugins.PluginManager;
import org.gradle.plugins.ide.eclipse.EclipseWtpPlugin;
import org.gradle.plugins.ide.idea.IdeaPlugin;
import org.springframework.gradle.CopyPropertiesPlugin
import org.springframework.gradle.propdeps.PropDepsEclipsePlugin
import org.springframework.gradle.propdeps.PropDepsIdeaPlugin
import org.springframework.gradle.propdeps.PropDepsPlugin;
/**
* @author Rob Winch
*/
public abstract class AbstractSpringJavaPlugin implements Plugin<Project> {
@Override
public final void apply(Project project) {
PluginManager pluginManager = project.getPluginManager();
pluginManager.apply(JavaPlugin.class);
pluginManager.apply(ManagementConfigurationPlugin.class)
if (project.file("src/main/groovy").exists()
|| project.file("src/test/groovy").exists()
|| project.file("src/integration-test/groovy").exists()) {
pluginManager.apply(GroovyPlugin.class);
}
pluginManager.apply("io.spring.convention.repository");
pluginManager.apply(EclipseWtpPlugin);
pluginManager.apply(IdeaPlugin);
pluginManager.apply(PropDepsPlugin);
pluginManager.apply(PropDepsEclipsePlugin);
pluginManager.apply(PropDepsIdeaPlugin);
pluginManager.apply("io.spring.convention.tests-configuration");
pluginManager.apply("io.spring.convention.integration-test");
pluginManager.apply("io.spring.convention.springdependencymangement");
pluginManager.apply("io.spring.convention.javadoc-options");
pluginManager.apply("io.spring.convention.checkstyle");
pluginManager.apply(CopyPropertiesPlugin);
project.jar {
manifest.attributes["Created-By"] =
"${System.getProperty("java.version")} (${System.getProperty("java.specification.vendor")})"
manifest.attributes["Implementation-Title"] = project.name
manifest.attributes["Implementation-Version"] = project.version
manifest.attributes["Automatic-Module-Name"] = project.name.replace('-', '.')
}
project.test {
useJUnitPlatform()
}
additionalPlugins(project);
}
protected abstract void additionalPlugins(Project project);
}

View File

@@ -0,0 +1,46 @@
/*
* Copyright 2002-2017 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. You may obtain a copy of
* the License at
*
* https://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 io.spring.gradle.convention
import org.gradle.api.Plugin
import org.gradle.api.Project
class ArtifactoryPlugin implements Plugin<Project> {
@Override
void apply(Project project) {
project.plugins.apply('com.jfrog.artifactory')
String name = Utils.getProjectName(project);
boolean isSnapshot = Utils.isSnapshot(project);
boolean isMilestone = Utils.isMilestone(project);
project.artifactory {
contextUrl = 'https://repo.spring.io'
publish {
repository {
repoKey = isSnapshot ? 'libs-snapshot-local' : isMilestone ? 'libs-milestone-local' : 'libs-release-local'
if(project.hasProperty('artifactoryUsername')) {
username = artifactoryUsername
password = artifactoryPassword
}
}
defaults {
publications('mavenJava')
}
}
}
}
}

View File

@@ -0,0 +1,49 @@
/*
* Copyright 2016-2021 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. You may obtain a copy of
* the License at
*
* https://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 io.spring.gradle.convention
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.plugins.JavaPlugin
/**
* Adds and configures Checkstyle plugin.
*
* @author Vedran Pavic
*/
class CheckstylePlugin implements Plugin<Project> {
final CHECKSTYLE_DIR = 'etc/checkstyle'
@Override
void apply(Project project) {
project.plugins.withType(JavaPlugin) {
def checkstyleDir = project.rootProject.file(CHECKSTYLE_DIR)
if (checkstyleDir.exists() && checkstyleDir.directory) {
project.getPluginManager().apply('checkstyle')
project.dependencies.add('checkstyle', 'io.spring.javaformat:spring-javaformat-checkstyle:0.0.29')
project.dependencies.add('checkstyle', 'io.spring.nohttp:nohttp-checkstyle:0.0.3.RELEASE')
project.checkstyle {
configDirectory = checkstyleDir
toolVersion = '8.21'
}
}
}
}
}

View File

@@ -0,0 +1,61 @@
package io.spring.gradle.convention
import org.gradle.api.Project
import org.gradle.api.artifacts.component.ModuleComponentSelector
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.Internal;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Map;
import java.util.Properties;
import org.gradle.api.DefaultTask;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.tasks.TaskAction;
import io.spring.gradle.dependencymanagement.dsl.DependencyManagementExtension;
public class DependencyManagementExportTask extends DefaultTask {
@Internal
def projects;
@Input
String getProjectNames() {
return projects*.name
}
@TaskAction
public void dependencyManagementExport() throws IOException {
def projects = this.projects ?: project.subprojects + project
def configurations = projects*.configurations*.findAll { ['testRuntime','integrationTestRuntime','grettyRunnerTomcat8','ajtools'].contains(it.name) }
def dependencyResults = configurations*.incoming*.resolutionResult*.allDependencies.flatten()
def moduleVersionVersions = dependencyResults.findAll { r -> r.requested instanceof ModuleComponentSelector }.collect { r-> r.selected.moduleVersion }
def projectDependencies = projects.collect { p-> "${p.group}:${p.name}:${p.version}".toString() } as Set
def dependencies = moduleVersionVersions.collect { d ->
"${d.group}:${d.name}:${d.version}".toString()
}.sort() as Set
println ''
println ''
println 'dependencyManagement {'
println '\tdependencies {'
dependencies.findAll { d-> !projectDependencies.contains(d)}.each {
println "\t\tdependency '$it'"
}
println '\t}'
println '}'
println ''
println ''
println 'TIP Use this to find duplicates:\n$ sort gradle/dependency-management.gradle| uniq -c | grep -v \'^\\s*1\''
println ''
println ''
}
void setOutputFile(File file) throws IOException {
this.output = new FileOutputStream(file);
}
}

View File

@@ -0,0 +1,83 @@
/*
* Copyright 2002-2017 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. You may obtain a copy of
* the License at
*
* https://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 io.spring.gradle.convention
import org.gradle.api.plugins.JavaPlugin
import org.gradle.api.tasks.bundling.Zip
import org.gradle.api.Plugin
import org.gradle.api.Project
public class DeployDocsPlugin implements Plugin<Project> {
@Override
public void apply(Project project) {
project.getPluginManager().apply('org.hidetake.ssh')
project.ssh.settings {
knownHosts = allowAnyHosts
}
project.remotes {
docs {
role 'docs'
if (project.hasProperty('deployDocsHost')) {
host = project.findProperty('deployDocsHost')
} else {
host = 'docs.af.pivotal.io'
}
retryCount = 5 // retry 5 times (default is 0)
retryWaitSec = 10 // wait 10 seconds between retries (default is 0)
user = project.findProperty('deployDocsSshUsername')
if (project.hasProperty('deployDocsSshKeyPath')) {
identity = project.file(project.findProperty('deployDocsSshKeyPath'))
} else if (project.hasProperty('deployDocsSshKey')) {
identity = project.findProperty('deployDocsSshKey')
}
if(project.hasProperty('deployDocsSshPassphrase')) {
passphrase = project.findProperty('deployDocsSshPassphrase')
}
}
}
project.task('deployDocs') {
dependsOn 'docsZip'
doFirst {
project.ssh.run {
session(project.remotes.docs) {
def now = System.currentTimeMillis()
def name = project.rootProject.name
def version = project.rootProject.version
def tempPath = "/tmp/${name}-${now}-docs/".replaceAll(' ', '_')
execute "mkdir -p $tempPath"
project.tasks.docsZip.outputs.each { o ->
put from: o.files, into: tempPath
}
execute "unzip $tempPath*.zip -d $tempPath"
def extractPath = "/var/www/domains/spring.io/docs/htdocs/autorepo/docs/${name}/${version}/"
execute "rm -rf $extractPath"
execute "mkdir -p $extractPath"
execute "mv $tempPath/docs/* $extractPath"
execute "chmod -R g+w $extractPath"
}
}
}
}
}
}

View File

@@ -0,0 +1,45 @@
package io.spring.gradle.convention
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.Task
import org.gradle.api.plugins.BasePlugin
import org.gradle.api.plugins.PluginManager
import org.gradle.api.tasks.bundling.Zip
/**
* Aggregates asciidoc, javadoc, and deploying of the docs into a single plugin
*/
public class DocsPlugin implements Plugin<Project> {
@Override
public void apply(Project project) {
PluginManager pluginManager = project.getPluginManager();
pluginManager.apply(BasePlugin);
pluginManager.apply(DeployDocsPlugin);
pluginManager.apply(JavadocApiPlugin);
Task docsZip = project.tasks.create('docsZip', Zip) {
dependsOn 'api'
group = 'Distribution'
archiveBaseName = project.rootProject.name
archiveClassifier = 'docs'
description = "Builds -${classifier} archive containing all " +
"Docs for deployment at docs.spring.io"
from(project.tasks.api.outputs) {
into 'api'
}
into 'docs'
duplicatesStrategy 'exclude'
}
Task docs = project.tasks.create("docs") {
group = 'Documentation'
description 'An aggregator task to generate all the documentation'
dependsOn docsZip
}
project.tasks.assemble.dependsOn docs
}
}

View File

@@ -0,0 +1,65 @@
/*
* Copyright 2002-2021 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. You may obtain a copy of
* the License at
*
* https://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 io.spring.gradle.convention
import io.spring.gradle.IncludeRepoTask
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.provider.Property
import org.gradle.api.tasks.GradleBuild
import org.gradle.api.tasks.TaskProvider
/**
* Adds a set of tasks that make easy to clone a remote repository and perform some task
*
* @author Marcus Da Coregio
*/
class IncludeCheckRemotePlugin implements Plugin<Project> {
@Override
void apply(Project project) {
IncludeCheckRemoteExtension extension = project.extensions.create('includeCheckRemote', IncludeCheckRemoteExtension)
TaskProvider<IncludeRepoTask> includeRepoTask = project.tasks.register('includeRepo', IncludeRepoTask) { IncludeRepoTask it ->
it.repository = extension.repository
it.ref = extension.ref
}
project.tasks.register('checkRemote', GradleBuild) {
it.dependsOn 'includeRepo'
it.dir = includeRepoTask.get().outputDirectory
it.tasks = extension.getTasks()
}
}
abstract static class IncludeCheckRemoteExtension {
/**
* Git repository to clone
*/
String repository;
/**
* Git ref to checkout
*/
String ref
/**
* Task to run in the repository
*/
List<String> tasks = ['check']
}
}

View File

@@ -0,0 +1,123 @@
/*
* Copyright 2016-2018 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. You may obtain a copy of
* the License at
*
* https://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 io.spring.gradle.convention
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.Task
import org.gradle.api.plugins.GroovyPlugin
import org.gradle.api.plugins.JavaPlugin
import org.gradle.api.tasks.testing.Test
import org.gradle.plugins.ide.eclipse.EclipsePlugin
import org.gradle.plugins.ide.idea.IdeaPlugin
import org.springframework.gradle.propdeps.PropDepsPlugin
/**
*
* Adds support for integration tests to java projects.
*
* <ul>
* <li>Adds integrationTestCompile and integrationTestRuntime configurations</li>
* <li>A new source test folder of src/integration-test/java has been added</li>
* <li>A task to run integration tests named integrationTest is added</li>
* <li>If Groovy plugin is added a new source test folder src/integration-test/groovy is added</li>
* </ul>
*
* @author Rob Winch
*/
public class IntegrationTestPlugin implements Plugin<Project> {
@Override
public void apply(Project project) {
project.plugins.withType(JavaPlugin.class) {
applyJava(project)
}
}
private applyJava(Project project) {
if(!project.file('src/integration-test/').exists()) {
// ensure we don't add if no tests to avoid adding Gretty
return
}
project.configurations {
integrationTestCompile {
extendsFrom testImplementation
}
integrationTestRuntime {
extendsFrom integrationTestCompile, testRuntime, testRuntimeOnly
}
}
project.sourceSets {
integrationTest {
java.srcDir project.file('src/integration-test/java')
resources.srcDir project.file('src/integration-test/resources')
compileClasspath = project.sourceSets.main.output + project.sourceSets.test.output + project.configurations.integrationTestCompile
runtimeClasspath = output + compileClasspath + project.configurations.integrationTestRuntime
}
}
Task integrationTestTask = project.tasks.create("integrationTest", Test) {
group = 'Verification'
description = 'Runs the integration tests.'
dependsOn 'jar'
testClassesDirs = project.sourceSets.integrationTest.output.classesDirs
classpath = project.sourceSets.integrationTest.runtimeClasspath
shouldRunAfter project.tasks.test
useJUnitPlatform()
}
project.tasks.check.dependsOn integrationTestTask
project.plugins.withType(IdeaPlugin) {
project.idea {
module {
testSourceDirs += project.file('src/integration-test/java')
scopes.TEST.plus += [ project.configurations.integrationTestCompile ]
}
}
}
project.plugins.withType(GroovyPlugin) {
project.sourceSets {
integrationTest {
groovy.srcDirs project.file('src/integration-test/groovy')
}
}
project.plugins.withType(IdeaPlugin) {
project.idea {
module {
testSourceDirs += project.file('src/integration-test/groovy')
}
}
}
}
project.plugins.withType(PropDepsPlugin) {
project.configurations {
integrationTestCompile {
extendsFrom optional, provided
}
}
}
project.plugins.withType(EclipsePlugin) {
project.eclipse.classpath {
plusConfigurations += [ project.configurations.integrationTestCompile ]
}
}
}
}

View File

@@ -0,0 +1,41 @@
/*
* Copyright 2016-2018 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. You may obtain a copy of
* the License at
*
* https://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 io.spring.gradle.convention
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.plugins.JavaPlugin
/**
* Adds a version of jacoco to use and makes check depend on jacocoTestReport.
*
* @author Rob Winch
*/
class JacocoPlugin implements Plugin<Project> {
@Override
void apply(Project project) {
project.plugins.withType(JavaPlugin) {
project.getPluginManager().apply("jacoco")
project.tasks.check.dependsOn project.tasks.jacocoTestReport
project.jacoco {
toolVersion = '0.8.2'
}
}
}
}

View File

@@ -0,0 +1,116 @@
/*
* Copyright 2002-2016 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. You may obtain a copy of
* the License at
*
* https://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 io.spring.gradle.convention;
import java.io.File;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Pattern;
import org.gradle.api.Action;
import org.gradle.api.JavaVersion
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.plugins.JavaPluginConvention;
import org.gradle.api.tasks.SourceSet;
import org.gradle.api.tasks.javadoc.Javadoc;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author Rob Winch
*/
public class JavadocApiPlugin implements Plugin<Project> {
Logger logger = LoggerFactory.getLogger(getClass());
Set<Pattern> excludes = Collections.singleton(Pattern.compile("test"));
@Override
public void apply(Project project) {
logger.info("Applied");
Project rootProject = project.getRootProject();
//Task docs = project.getTasks().findByPath("docs") ?: project.getTasks().create("docs");
Javadoc api = project.getTasks().create("api", Javadoc);
api.setGroup("Documentation");
api.setDescription("Generates aggregated Javadoc API documentation.");
api.doLast {
if (JavaVersion.current().isJava11Compatible()) {
project.copy({ copy -> copy
.from(api.destinationDir)
.into(api.destinationDir)
.include("element-list")
.rename("element-list", "package-list")
});
}
}
Set<Project> subprojects = rootProject.getSubprojects();
for (Project subproject : subprojects) {
addProject(api, subproject);
}
if (subprojects.isEmpty()) {
addProject(api, project);
}
api.setMaxMemory("1024m");
api.setDestinationDir(new File(project.getBuildDir(), "api"));
project.getPluginManager().apply("io.spring.convention.javadoc-options");
}
public void setExcludes(String... excludes) {
if(excludes == null) {
this.excludes = Collections.emptySet();
}
this.excludes = new HashSet<Pattern>(excludes.length);
for(String exclude : excludes) {
this.excludes.add(Pattern.compile(exclude));
}
}
private void addProject(final Javadoc api, final Project project) {
for(Pattern exclude : excludes) {
if(exclude.matcher(project.getName()).matches()) {
logger.info("Skipping {} because it is excluded by {}", project, exclude);
return;
}
}
logger.info("Try add sources for {}", project);
project.getPlugins().withType(SpringModulePlugin.class).all(new Action<SpringModulePlugin>() {
@Override
public void execute(SpringModulePlugin plugin) {
logger.info("Added sources for {}", project);
JavaPluginConvention java = project.getConvention().getPlugin(JavaPluginConvention.class);
SourceSet mainSourceSet = java.getSourceSets().getByName("main");
api.setSource(api.getSource().plus(mainSourceSet.getAllJava()));
project.getTasks().withType(Javadoc.class).all(new Action<Javadoc>() {
@Override
public void execute(Javadoc projectJavadoc) {
api.setClasspath(api.getClasspath().plus(projectJavadoc.getClasspath()));
}
});
}
});
}
}

View File

@@ -0,0 +1,15 @@
package io.spring.gradle.convention
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.tasks.javadoc.Javadoc
public class JavadocOptionsPlugin implements Plugin<Project> {
@Override
public void apply(Project project) {
project.getTasks().withType(Javadoc).all { t->
t.options.addStringOption('Xdoclint:none', '-quiet')
}
}
}

View File

@@ -0,0 +1,74 @@
/*
* Copyright 2002-2021 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.
* You may obtain a copy of the License at
*
* https://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 io.spring.gradle.convention;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.artifacts.ConfigurationContainer;
import org.gradle.api.plugins.JavaPlugin;
import org.gradle.api.plugins.JavaTestFixturesPlugin;
import org.gradle.api.plugins.PluginContainer;
import org.gradle.api.publish.PublishingExtension;
import org.gradle.api.publish.maven.MavenPublication;
import org.gradle.api.publish.maven.plugins.MavenPublishPlugin;
import org.springframework.gradle.propdeps.PropDepsPlugin;
/**
* Creates a Management configuration that is appropriate for adding a platform to that is not exposed externally. If
* the JavaPlugin is applied, the compileClasspath, runtimeClasspath, testCompileClasspath, and testRuntimeClasspath
* will extend from it.
* @author Rob Winch
*/
public class ManagementConfigurationPlugin implements Plugin<Project> {
public static final String MANAGEMENT_CONFIGURATION_NAME = "management";
@Override
public void apply(Project project) {
ConfigurationContainer configurations = project.getConfigurations();
configurations.create(MANAGEMENT_CONFIGURATION_NAME, (management) -> {
management.setVisible(false);
management.setCanBeConsumed(false);
management.setCanBeResolved(false);
PluginContainer plugins = project.getPlugins();
plugins.withType(JavaPlugin.class, (javaPlugin) -> {
configurations.getByName(JavaPlugin.COMPILE_CLASSPATH_CONFIGURATION_NAME).extendsFrom(management);
configurations.getByName(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME).extendsFrom(management);
configurations.getByName(JavaPlugin.TEST_COMPILE_CLASSPATH_CONFIGURATION_NAME).extendsFrom(management);
configurations.getByName(JavaPlugin.TEST_RUNTIME_CLASSPATH_CONFIGURATION_NAME).extendsFrom(management);
});
plugins.withType(JavaTestFixturesPlugin.class, (javaTestFixturesPlugin) -> {
configurations.getByName("testFixturesCompileClasspath").extendsFrom(management);
configurations.getByName("testFixturesRuntimeClasspath").extendsFrom(management);
});
plugins.withType(MavenPublishPlugin.class, (mavenPublish) -> {
PublishingExtension publishing = project.getExtensions().getByType(PublishingExtension.class);
publishing.getPublications().withType(MavenPublication.class, (mavenPublication -> {
mavenPublication.versionMapping((versions) ->
versions.allVariants(versionMapping -> versionMapping.fromResolutionResult())
);
}));
});
plugins.withType(PropDepsPlugin.class, (propDepsPlugin -> {
configurations.getByName("optional").extendsFrom(management);
configurations.getByName("provided").extendsFrom(management);
}));
});
}
}

View File

@@ -0,0 +1,18 @@
package io.spring.gradle.convention
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.plugins.JavaPlatformPlugin
import org.sonarqube.gradle.SonarQubePlugin
import org.springframework.gradle.CopyPropertiesPlugin
import org.springframework.gradle.maven.SpringMavenPlugin
public class MavenBomPlugin implements Plugin<Project> {
static String MAVEN_BOM_TASK_NAME = "mavenBom"
public void apply(Project project) {
project.plugins.apply(JavaPlatformPlugin)
project.plugins.apply(SpringMavenPlugin)
project.plugins.apply(CopyPropertiesPlugin)
}
}

View File

@@ -0,0 +1,84 @@
/*
* Copyright 2016-2018 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. You may obtain a copy of
* the License at
*
* https://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 io.spring.gradle.convention;
import org.gradle.api.Plugin
import org.gradle.api.Project
class RepositoryConventionPlugin implements Plugin<Project> {
@Override
void apply(Project project) {
String[] forceMavenRepositories = ((String) project.findProperty("forceMavenRepositories"))?.split(',')
boolean isImplicitSnapshotRepository = forceMavenRepositories == null && Utils.isSnapshot(project)
boolean isImplicitMilestoneRepository = forceMavenRepositories == null && Utils.isMilestone(project)
boolean isSnapshot = isImplicitSnapshotRepository || forceMavenRepositories?.contains('snapshot')
boolean isMilestone = isImplicitMilestoneRepository || forceMavenRepositories?.contains('milestone')
project.repositories {
if (forceMavenRepositories?.contains('local')) {
mavenLocal()
}
mavenCentral()
jcenter() {
content {
includeGroup "org.gretty"
}
}
if (isSnapshot) {
maven {
name = 'artifactory-snapshot'
if (project.hasProperty('artifactoryUsername')) {
credentials {
username project.artifactoryUsername
password project.artifactoryPassword
}
}
url = 'https://repo.spring.io/snapshot/'
}
}
if (isSnapshot || isMilestone) {
maven {
name = 'artifactory-milestone'
if (project.hasProperty('artifactoryUsername')) {
credentials {
username project.artifactoryUsername
password project.artifactoryPassword
}
}
url = 'https://repo.spring.io/milestone/'
}
}
maven {
name = 'artifactory-release'
if (project.hasProperty('artifactoryUsername')) {
credentials {
username project.artifactoryUsername
password project.artifactoryPassword
}
}
url = 'https://repo.spring.io/release/'
}
maven {
name = 'shibboleth'
url = 'https://build.shibboleth.net/nexus/content/repositories/releases/'
}
}
}
}

View File

@@ -0,0 +1,70 @@
/*
* Copyright 2016-2019 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. You may obtain a copy of
* the License at
*
* https://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 io.spring.gradle.convention
import io.spring.nohttp.gradle.NoHttpPlugin
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.plugins.BasePlugin
import org.gradle.api.plugins.PluginManager
import org.springframework.gradle.maven.SpringNexusPublishPlugin
class RootProjectPlugin implements Plugin<Project> {
@Override
void apply(Project project) {
PluginManager pluginManager = project.getPluginManager()
pluginManager.apply(BasePlugin)
pluginManager.apply(SchemaPlugin)
pluginManager.apply(NoHttpPlugin)
pluginManager.apply(SpringNexusPublishPlugin)
pluginManager.apply("org.sonarqube")
project.repositories.mavenCentral()
project.allprojects {
configurations.all {
resolutionStrategy {
cacheChangingModulesFor 0, "seconds"
cacheDynamicVersionsFor 0, "seconds"
}
}
}
String projectName = Utils.getProjectName(project)
project.sonarqube {
properties {
property "sonar.java.coveragePlugin", "jacoco"
property "sonar.projectName", projectName
property "sonar.jacoco.reportPath", "${project.buildDir.name}/jacoco.exec"
property "sonar.links.homepage", "https://spring.io/${projectName}"
property "sonar.links.ci", "https://jenkins.spring.io/job/${projectName}/"
property "sonar.links.issue", "https://github.com/spring-projects/${projectName}/issues"
property "sonar.links.scm", "https://github.com/spring-projects/${projectName}"
property "sonar.links.scm_dev", "https://github.com/spring-projects/${projectName}.git"
}
}
project.tasks.create("dependencyManagementExport", DependencyManagementExportTask)
def finalizeDeployArtifacts = project.task("finalizeDeployArtifacts")
if (Utils.isRelease(project) && project.hasProperty("ossrhUsername")) {
finalizeDeployArtifacts.dependsOn project.tasks.closeAndReleaseOssrhStagingRepository
}
}
}

View File

@@ -0,0 +1,71 @@
package io.spring.gradle.convention
import org.gradle.api.plugins.JavaPlugin
import org.gradle.api.tasks.bundling.Zip
import org.gradle.api.Plugin
import org.gradle.api.Project
public class SchemaDeployPlugin implements Plugin<Project> {
@Override
public void apply(Project project) {
project.getPluginManager().apply('org.hidetake.ssh')
project.ssh.settings {
knownHosts = allowAnyHosts
}
project.remotes {
docs {
role 'docs'
if (project.hasProperty('deployDocsHost')) {
host = project.findProperty('deployDocsHost')
} else {
host = 'docs.af.pivotal.io'
}
retryCount = 5 // retry 5 times (default is 0)
retryWaitSec = 10 // wait 10 seconds between retries (default is 0)
user = project.findProperty('deployDocsSshUsername')
if(project.hasProperty('deployDocsSshKeyPath')) {
identity = project.file(project.findProperty('deployDocsSshKeyPath'))
} else if (project.hasProperty('deployDocsSshKey')) {
identity = project.findProperty('deployDocsSshKey')
}
if(project.hasProperty('deployDocsSshPassphrase')) {
passphrase = project.findProperty('deployDocsSshPassphrase')
}
}
}
project.task('deploySchema') {
dependsOn 'schemaZip'
doFirst {
project.ssh.run {
session(project.remotes.docs) {
def now = System.currentTimeMillis()
def name = project.rootProject.name
def version = project.rootProject.version
def tempPath = "/tmp/${name}-${now}-schema/".replaceAll(' ', '_')
execute "mkdir -p $tempPath"
project.tasks.schemaZip.outputs.each { o ->
println "Putting $o.files"
put from: o.files, into: tempPath
}
execute "unzip $tempPath*.zip -d $tempPath"
def extractPath = "/var/www/domains/spring.io/docs/htdocs/autorepo/schema/${name}/${version}/"
execute "rm -rf $extractPath"
execute "mkdir -p $extractPath"
execute "rm -f $tempPath*.zip"
execute "rm -rf $extractPath*"
execute "mv $tempPath/* $extractPath"
execute "chmod -R g+w $extractPath"
}
}
}
}
}
}

View File

@@ -0,0 +1,15 @@
package io.spring.gradle.convention
import org.gradle.api.plugins.JavaPlugin
import org.gradle.api.tasks.bundling.Zip
import org.gradle.api.Plugin
import org.gradle.api.Project
public class SchemaPlugin implements Plugin<Project> {
@Override
public void apply(Project project) {
project.getPluginManager().apply(SchemaZipPlugin)
project.getPluginManager().apply(SchemaDeployPlugin)
}
}

View File

@@ -0,0 +1,43 @@
package io.spring.gradle.convention
import org.gradle.api.plugins.JavaPlugin
import org.gradle.api.tasks.bundling.Zip
import org.gradle.api.Plugin
import org.gradle.api.Project
public class SchemaZipPlugin implements Plugin<Project> {
@Override
public void apply(Project project) {
Zip schemaZip = project.tasks.create('schemaZip', Zip)
schemaZip.group = 'Distribution'
schemaZip.archiveBaseName = project.rootProject.name
schemaZip.archiveClassifier = 'schema'
schemaZip.description = "Builds -${schemaZip.archiveClassifier} archive containing all " +
"XSDs for deployment at static.springframework.org/schema."
project.rootProject.subprojects.each { module ->
module.getPlugins().withType(JavaPlugin.class).all {
def Properties schemas = new Properties();
module.sourceSets.main.resources.find {
it.path.endsWith('META-INF/spring.schemas')
}?.withInputStream { schemas.load(it) }
for (def key : schemas.keySet()) {
def shortName = key.replaceAll(/http.*schema.(.*).spring-.*/, '$1')
assert shortName != key
File xsdFile = module.sourceSets.main.resources.find {
it.path.endsWith(schemas.get(key))
}
assert xsdFile != null
schemaZip.into (shortName) {
duplicatesStrategy 'exclude'
from xsdFile.path
}
}
}
}
}
}

View File

@@ -0,0 +1,53 @@
/*
* Copyright 2002-2017 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.
* You may obtain a copy of the License at
*
* https://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 io.spring.gradle.convention;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.List;
import java.util.Properties;
/**
* A Properties which sorts they keys so that they can be written to a File with
* the keys sorted.
*
* @author Rob Winch
*
*/
class SortedProperties extends Properties {
private static final long serialVersionUID = -6199017589626540836L;
public Enumeration<Object> keys() {
Enumeration<Object> keysEnum = super.keys();
List<Object> keyList = new ArrayList<Object>();
while (keysEnum.hasMoreElements()) {
keyList.add(keysEnum.nextElement());
}
Collections.sort(keyList, new Comparator<Object>() {
@Override
public int compare(Object o1, Object o2) {
return o1.toString().compareTo(o2.toString());
}
});
return Collections.enumeration(keyList);
}
}

View File

@@ -0,0 +1,54 @@
/*
* Copyright 2016-2021 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. You may obtain a copy of
* the License at
*
* https://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 io.spring.gradle.convention
import io.spring.gradle.dependencymanagement.DependencyManagementPlugin
import org.gradle.api.Plugin
import org.gradle.api.Project
/**
* Adds and configures {@link DependencyManagementPlugin}.
* <p>
* Additionally, if 'gradle/dependency-management.gradle' file is present it will be
* automatically applied file for configuring the dependencies.
*/
class SpringDependencyManagementConventionPlugin implements Plugin<Project> {
static final String DEPENDENCY_MANAGEMENT_RESOURCE = "gradle/dependency-management.gradle"
@Override
void apply(Project project) {
project.getPluginManager().apply(ManagementConfigurationPlugin)
project.getPluginManager().apply(DependencyManagementPlugin)
project.dependencyManagement {
resolutionStrategy {
cacheChangingModulesFor 0, "seconds"
}
}
File rootDir = project.rootDir
List<File> dependencyManagementFiles = [project.rootProject.file(DEPENDENCY_MANAGEMENT_RESOURCE)]
for (File dir = project.projectDir; dir != rootDir; dir = dir.parentFile) {
dependencyManagementFiles.add(new File(dir, DEPENDENCY_MANAGEMENT_RESOURCE))
}
dependencyManagementFiles.each { f ->
if (f.exists()) {
project.apply from: f.absolutePath
}
}
}
}

View File

@@ -0,0 +1,45 @@
/*
* Copyright 2016-2019 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. You may obtain a copy of
* the License at
*
* https://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 io.spring.gradle.convention;
import org.gradle.api.Project
import org.gradle.api.plugins.JavaLibraryPlugin;
import org.gradle.api.plugins.MavenPlugin;
import org.gradle.api.plugins.PluginManager
import org.springframework.gradle.maven.SpringMavenPlugin;
/**
* @author Rob Winch
*/
class SpringModulePlugin extends AbstractSpringJavaPlugin {
@Override
void additionalPlugins(Project project) {
PluginManager pluginManager = project.getPluginManager();
pluginManager.apply(JavaLibraryPlugin.class)
pluginManager.apply(SpringMavenPlugin.class);
pluginManager.apply("io.spring.convention.jacoco");
def deployArtifacts = project.task("deployArtifacts")
deployArtifacts.group = 'Deploy tasks'
deployArtifacts.description = "Deploys the artifacts to either Artifactory or Maven Central"
if (!Utils.isRelease(project)) {
deployArtifacts.dependsOn project.tasks.artifactoryPublish
}
}
}

View File

@@ -0,0 +1,40 @@
/*
* Copyright 2002-2021 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. You may obtain a copy of
* the License at
*
* https://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 io.spring.gradle.convention
import org.gradle.api.Project
import org.gradle.api.plugins.PluginManager
/**
* @author Rob Winch
*/
public class SpringSampleBootPlugin extends SpringSamplePlugin {
@Override
public void additionalPlugins(Project project) {
super.additionalPlugins(project);
PluginManager pluginManager = project.getPluginManager();
pluginManager.apply("org.springframework.boot");
project.repositories {
maven { url 'https://repo.spring.io/snapshot' }
maven { url 'https://repo.spring.io/milestone' }
}
}
}

View File

@@ -0,0 +1,33 @@
/*
* Copyright 2002-2021 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. You may obtain a copy of
* the License at
*
* https://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 io.spring.gradle.convention;
import org.gradle.api.Project
import org.sonarqube.gradle.SonarQubePlugin;
/**
* @author Rob Winch
*/
public class SpringSamplePlugin extends AbstractSpringJavaPlugin {
@Override
public void additionalPlugins(Project project) {
project.plugins.withType(SonarQubePlugin) {
project.sonarqube.skipProject = true
}
}
}

View File

@@ -0,0 +1,98 @@
/*
* Copyright 2016-2021 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. You may obtain a copy of
* the License at
*
* https://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 io.spring.gradle.convention
import org.gradle.api.Project
import org.gradle.api.Task
import org.gradle.api.plugins.PluginManager
import org.gradle.api.tasks.testing.Test
/**
* @author Rob Winch
*/
public class SpringSampleWarPlugin extends SpringSamplePlugin {
@Override
public void additionalPlugins(Project project) {
super.additionalPlugins(project);
PluginManager pluginManager = project.getPluginManager();
pluginManager.apply("war");
pluginManager.apply("org.gretty");
project.gretty {
servletContainer = 'tomcat85'
contextPath = '/'
fileLogEnabled = false
}
Task prepareAppServerForIntegrationTests = project.tasks.create('prepareAppServerForIntegrationTests') {
group = 'Verification'
description = 'Prepares the app server for integration tests'
doFirst {
project.gretty {
httpPort = getRandomFreePort()
httpsPort = getRandomPort()
}
}
}
project.tasks.matching { it.name == "appBeforeIntegrationTest" }.all { task ->
task.dependsOn prepareAppServerForIntegrationTests
}
project.tasks.withType(Test).all { task ->
if("integrationTest".equals(task.name)) {
applyForIntegrationTest(project, task)
}
}
}
def applyForIntegrationTest(Project project, Task integrationTest) {
project.gretty.integrationTestTask = integrationTest.name
integrationTest.doFirst {
def gretty = project.gretty
String host = project.gretty.host ?: 'localhost'
boolean isHttps = gretty.httpsEnabled
Integer httpPort = integrationTest.systemProperties['gretty.httpPort']
Integer httpsPort = integrationTest.systemProperties['gretty.httpsPort']
int port = isHttps ? httpsPort : httpPort
String contextPath = project.gretty.contextPath
String httpBaseUrl = "http://${host}:${httpPort}${contextPath}"
String httpsBaseUrl = "https://${host}:${httpsPort}${contextPath}"
String baseUrl = isHttps ? httpsBaseUrl : httpBaseUrl
integrationTest.systemProperty 'app.port', port
integrationTest.systemProperty 'app.httpPort', httpPort
integrationTest.systemProperty 'app.httpsPort', httpsPort
integrationTest.systemProperty 'app.baseURI', baseUrl
integrationTest.systemProperty 'app.httpBaseURI', httpBaseUrl
integrationTest.systemProperty 'app.httpsBaseURI', httpsBaseUrl
integrationTest.systemProperty 'geb.build.baseUrl', baseUrl
integrationTest.systemProperty 'geb.build.reportsDir', 'build/geb-reports'
}
}
def getRandomPort() {
ServerSocket ss = new ServerSocket(0)
int port = ss.localPort
ss.close()
return port
}
}

View File

@@ -0,0 +1,30 @@
/*
* Copyright 2002-2016 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. You may obtain a copy of
* the License at
*
* https://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 io.spring.gradle.convention;
import org.gradle.api.Project;
/**
* @author Rob Winch
*/
public class SpringTestPlugin extends AbstractSpringJavaPlugin {
@Override
public void additionalPlugins(Project project) {
project.sonarqube.skipProject = true
}
}

View File

@@ -0,0 +1,55 @@
/*
* Copyright 2002-2021 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. You may obtain a copy of
* the License at
*
* https://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 io.spring.gradle.convention;
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.plugins.JavaPlugin
import org.gradle.jvm.tasks.Jar
/**
* Adds the ability to depends on the test jar within other projects using:
*
* <code>
* testImplementation project(path: ':foo', configuration: 'tests')
* </code>
*
* @author Rob Winch
*/
public class TestsConfigurationPlugin implements Plugin<Project> {
@Override
public void apply(Project project) {
project.plugins.withType(JavaPlugin) {
applyJavaProject(project)
}
}
private void applyJavaProject(Project project) {
project.configurations {
tests.extendsFrom testRuntime, testRuntimeClasspath
}
project.tasks.create('testJar', Jar) {
classifier = 'test'
from project.sourceSets.test.output
}
project.artifacts {
tests project.testJar
}
}
}

View File

@@ -0,0 +1,34 @@
package io.spring.gradle.convention;
import org.gradle.api.Project;
public class Utils {
static String getProjectName(Project project) {
String projectName = project.getRootProject().getName();
if(projectName.endsWith("-build")) {
projectName = projectName.substring(0, projectName.length() - "-build".length());
}
return projectName;
}
static boolean isSnapshot(Project project) {
String projectVersion = projectVersion(project)
return projectVersion.matches('^.*([.-]BUILD)?-SNAPSHOT$')
}
static boolean isMilestone(Project project) {
String projectVersion = projectVersion(project)
return projectVersion.matches('^.*[.-]M\\d+$') || projectVersion.matches('^.*[.-]RC\\d+$')
}
static boolean isRelease(Project project) {
return !(isSnapshot(project) || isMilestone(project))
}
private static String projectVersion(Project project) {
return String.valueOf(project.getVersion());
}
private Utils() {}
}

View File

@@ -0,0 +1,38 @@
/*
* Copyright 2002-2021 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.
* You may obtain a copy of the License at
*
* https://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 org.springframework.gradle;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
public class CopyPropertiesPlugin implements Plugin<Project> {
@Override
public void apply(Project project) {
copyPropertyFromRootProjectTo("group", project);
copyPropertyFromRootProjectTo("version", project);
copyPropertyFromRootProjectTo("description", project);
}
private void copyPropertyFromRootProjectTo(String propertyName, Project project) {
Project rootProject = project.getRootProject();
Object property = rootProject.findProperty(propertyName);
if(property != null) {
project.setProperty(propertyName, property);
}
}
}

View File

@@ -0,0 +1,110 @@
/*
* Copyright 2019-2020 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.
* You may obtain a copy of the License at
*
* https://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 org.springframework.gradle.github.milestones;
import com.google.common.reflect.TypeToken;
import com.google.gson.Gson;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import java.io.IOException;
import java.util.List;
public class GitHubMilestoneApi {
private String baseUrl = "https://api.github.com";
private OkHttpClient client;
private Gson gson = new Gson();
public GitHubMilestoneApi() {
this.client = new OkHttpClient.Builder().build();
}
public GitHubMilestoneApi(String gitHubToken) {
this.client = new OkHttpClient.Builder()
.addInterceptor(new AuthorizationInterceptor(gitHubToken))
.build();
}
public void setBaseUrl(String baseUrl) {
this.baseUrl = baseUrl;
}
public long findMilestoneNumberByTitle(RepositoryRef repositoryRef, String milestoneTitle) {
String url = this.baseUrl + "/repos/" + repositoryRef.getOwner() + "/" + repositoryRef.getName() + "/milestones?per_page=100";
Request request = new Request.Builder().get().url(url)
.build();
try {
Response response = this.client.newCall(request).execute();
if (!response.isSuccessful()) {
throw new RuntimeException("Could not find milestone with title " + milestoneTitle + " for repository " + repositoryRef + ". Response " + response);
}
List<Milestone> milestones = this.gson.fromJson(response.body().charStream(), new TypeToken<List<Milestone>>(){}.getType());
for (Milestone milestone : milestones) {
if (milestoneTitle.equals(milestone.getTitle())) {
return milestone.getNumber();
}
}
if (milestones.size() <= 100) {
throw new RuntimeException("Could not find open milestone with title " + milestoneTitle + " for repository " + repositoryRef + " Got " + milestones);
}
throw new RuntimeException("It is possible there are too many open milestones open (only 100 are supported). Could not find open milestone with title " + milestoneTitle + " for repository " + repositoryRef + " Got " + milestones);
} catch (IOException e) {
throw new RuntimeException("Could not find open milestone with title " + milestoneTitle + " for repository " + repositoryRef, e);
}
}
public boolean isOpenIssuesForMilestoneNumber(RepositoryRef repositoryRef, long milestoneNumber) {
String url = this.baseUrl + "/repos/" + repositoryRef.getOwner() + "/" + repositoryRef.getName() + "/issues?per_page=1&milestone=" + milestoneNumber;
Request request = new Request.Builder().get().url(url)
.build();
try {
Response response = this.client.newCall(request).execute();
if (!response.isSuccessful()) {
throw new RuntimeException("Could not find issues for milestone number " + milestoneNumber + " for repository " + repositoryRef + ". Response " + response);
}
List<Object> issues = this.gson.fromJson(response.body().charStream(), new TypeToken<List<Object>>(){}.getType());
return !issues.isEmpty();
} catch (IOException e) {
throw new RuntimeException("Could not find issues for milestone number " + milestoneNumber + " for repository " + repositoryRef, e);
}
}
// public boolean isOpenIssuesForMilestoneName(String owner, String repository, String milestoneName) {
//
// }
private static class AuthorizationInterceptor implements Interceptor {
private final String token;
public AuthorizationInterceptor(String token) {
this.token = token;
}
@Override
public okhttp3.Response intercept(Chain chain) throws IOException {
Request request = chain.request().newBuilder()
.addHeader("Authorization", "Bearer " + this.token).build();
return chain.proceed(request);
}
}
}

View File

@@ -0,0 +1,75 @@
/*
* Copyright 2019-2020 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.
* You may obtain a copy of the License at
*
* https://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 org.springframework.gradle.github.milestones;
import org.gradle.api.Action;
import org.gradle.api.DefaultTask;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.Optional;
import org.gradle.api.tasks.TaskAction;
public class GitHubMilestoneHasNoOpenIssuesTask extends DefaultTask {
@Input
private RepositoryRef repository = new RepositoryRef();
@Input
private String milestoneTitle;
@Input @Optional
private String gitHubAccessToken;
private GitHubMilestoneApi milestones = new GitHubMilestoneApi();
@TaskAction
public void checkHasNoOpenIssues() {
long milestoneNumber = this.milestones.findMilestoneNumberByTitle(this.repository, this.milestoneTitle);
boolean isOpenIssues = this.milestones.isOpenIssuesForMilestoneNumber(this.repository, milestoneNumber);
if (isOpenIssues) {
throw new IllegalStateException("The repository " + this.repository + " has open issues for milestone with the title " + this.milestoneTitle + " and number " + milestoneNumber);
}
System.out.println("The repository " + this.repository + " has no open issues for milestone with the title " + this.milestoneTitle + " and number " + milestoneNumber);
}
public RepositoryRef getRepository() {
return repository;
}
public void repository(Action<RepositoryRef> repository) {
repository.execute(this.repository);
}
public void setRepository(RepositoryRef repository) {
this.repository = repository;
}
public String getMilestoneTitle() {
return milestoneTitle;
}
public void setMilestoneTitle(String milestoneTitle) {
this.milestoneTitle = milestoneTitle;
}
public String getGitHubAccessToken() {
return gitHubAccessToken;
}
public void setGitHubAccessToken(String gitHubAccessToken) {
this.gitHubAccessToken = gitHubAccessToken;
this.milestones = new GitHubMilestoneApi(gitHubAccessToken);
}
}

View File

@@ -0,0 +1,38 @@
/*
* Copyright 2019-2020 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.
* You may obtain a copy of the License at
*
* https://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 org.springframework.gradle.github.milestones;
import org.gradle.api.Action;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
public class GitHubMilestonePlugin implements Plugin<Project> {
@Override
public void apply(Project project) {
project.getTasks().register("gitHubCheckMilestoneHasNoOpenIssues", GitHubMilestoneHasNoOpenIssuesTask.class, new Action<GitHubMilestoneHasNoOpenIssuesTask>() {
@Override
public void execute(GitHubMilestoneHasNoOpenIssuesTask githubCheckMilestoneHasNoOpenIssues) {
githubCheckMilestoneHasNoOpenIssues.setGroup("Release");
githubCheckMilestoneHasNoOpenIssues.setDescription("Checks if there are any open issues for the specified repository and milestone");
githubCheckMilestoneHasNoOpenIssues.setMilestoneTitle((String) project.findProperty("nextVersion"));
if (project.hasProperty("githubAccessToken")) {
githubCheckMilestoneHasNoOpenIssues.setGitHubAccessToken((String) project.findProperty("gitHubAccessToken"));
}
}
});
}
}

View File

@@ -0,0 +1,31 @@
package org.springframework.gradle.github.milestones;
public class Milestone {
private String title;
private long number;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public long getNumber() {
return number;
}
public void setNumber(long number) {
this.number = number;
}
@Override
public String toString() {
return "Milestone{" +
"title='" + title + '\'' +
", number=" + number +
'}';
}
}

View File

@@ -0,0 +1,65 @@
package org.springframework.gradle.github.milestones;
public class RepositoryRef {
private String owner;
private String name;
RepositoryRef() {
}
public RepositoryRef(String owner, String name) {
this.owner = owner;
this.name = name;
}
public String getOwner() {
return owner;
}
public void setOwner(String owner) {
this.owner = owner;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "RepositoryRef{" +
"owner='" + owner + '\'' +
", name='" + name + '\'' +
'}';
}
public static RepositoryRefBuilder owner(String owner) {
return new RepositoryRefBuilder().owner(owner);
}
public static final class RepositoryRefBuilder {
private String owner;
private String repository;
private RepositoryRefBuilder() {
}
private RepositoryRefBuilder owner(String owner) {
this.owner = owner;
return this;
}
public RepositoryRefBuilder repository(String repository) {
this.repository = repository;
return this;
}
public RepositoryRef build() {
return new RepositoryRef(owner, repository);
}
}
}

View File

@@ -0,0 +1,98 @@
/*
* Copyright 2016-2021 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. You may obtain a copy of
* the License at
*
* https://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 org.springframework.gradle.maven;
import org.gradle.api.Action;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.plugins.JavaPlugin;
import org.gradle.api.plugins.JavaPluginExtension;
import org.gradle.api.publish.PublishingExtension;
import org.gradle.api.publish.maven.MavenPom;
import org.gradle.api.publish.maven.MavenPomDeveloperSpec;
import org.gradle.api.publish.maven.MavenPomIssueManagement;
import org.gradle.api.publish.maven.MavenPomLicenseSpec;
import org.gradle.api.publish.maven.MavenPomOrganization;
import org.gradle.api.publish.maven.MavenPomScm;
import org.gradle.api.publish.maven.MavenPublication;
import org.gradle.api.publish.maven.plugins.MavenPublishPlugin;
public class MavenPublishingConventionsPlugin implements Plugin<Project> {
@Override
public void apply(Project project) {
project.getPlugins().withType(MavenPublishPlugin.class).all(new Action<MavenPublishPlugin>() {
@Override
public void execute(MavenPublishPlugin mavenPublish) {
PublishingExtension publishing = project.getExtensions().getByType(PublishingExtension.class);
publishing.getPublications().withType(MavenPublication.class)
.all((mavenPublication) -> MavenPublishingConventionsPlugin.this.customizePom(mavenPublication.getPom(), project));
MavenPublishingConventionsPlugin.this.customizeJavaPlugin(project);
}
});
}
private void customizePom(MavenPom pom, Project project) {
pom.getUrl().set("https://spring.io/projects/spring-session");
pom.getName().set(project.provider(project::getName));
pom.getDescription().set(project.provider(project::getDescription));
pom.organization(this::customizeOrganization);
pom.licenses(this::customizeLicences);
pom.developers(this::customizeDevelopers);
pom.scm(this::customizeScm);
pom.issueManagement(this::customizeIssueManagement);
}
private void customizeOrganization(MavenPomOrganization organization) {
organization.getName().set("Pivotal Software, Inc.");
organization.getUrl().set("https://spring.io");
}
private void customizeLicences(MavenPomLicenseSpec licences) {
licences.license((licence) -> {
licence.getName().set("Apache License, Version 2.0");
licence.getUrl().set("https://www.apache.org/licenses/LICENSE-2.0");
});
}
private void customizeDevelopers(MavenPomDeveloperSpec developers) {
developers.developer((developer) -> {
developer.getName().set("Pivotal");
developer.getEmail().set("info@pivotal.io");
developer.getOrganization().set("Pivotal Software, Inc.");
developer.getOrganizationUrl().set("https://www.spring.io");
});
}
private void customizeScm(MavenPomScm scm) {
scm.getConnection().set("scm:git:git://github.com/spring-projects/spring-session.git");
scm.getDeveloperConnection().set("scm:git:ssh://git@github.com/spring-projects/spring-session.git");
scm.getUrl().set("https://github.com/spring-projects/spring-session");
}
private void customizeIssueManagement(MavenPomIssueManagement issueManagement) {
issueManagement.getSystem().set("GitHub");
issueManagement.getUrl().set("https://github.com/spring-projects/spring-session/issues");
}
private void customizeJavaPlugin(Project project) {
project.getPlugins().withType(JavaPlugin.class).all((javaPlugin) -> {
JavaPluginExtension extension = project.getExtensions().getByType(JavaPluginExtension.class);
extension.withJavadocJar();
extension.withSourcesJar();
});
}
}

View File

@@ -0,0 +1,33 @@
package org.springframework.gradle.maven;
import org.gradle.api.Action;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.plugins.JavaPlatformPlugin;
import org.gradle.api.plugins.JavaPlugin;
import org.gradle.api.publish.PublishingExtension;
import org.gradle.api.publish.VariantVersionMappingStrategy;
import org.gradle.api.publish.VersionMappingStrategy;
import org.gradle.api.publish.maven.MavenPublication;
import org.gradle.api.publish.maven.plugins.MavenPublishPlugin;
public class PublishAllJavaComponentsPlugin implements Plugin<Project> {
@Override
public void apply(Project project) {
project.getPlugins().withType(MavenPublishPlugin.class).all((mavenPublish) -> {
PublishingExtension publishing = project.getExtensions().getByType(PublishingExtension.class);
publishing.getPublications().create("mavenJava", MavenPublication.class, new Action<MavenPublication>() {
@Override
public void execute(MavenPublication maven) {
project.getPlugins().withType(JavaPlugin.class, (plugin) -> {
maven.from(project.getComponents().getByName("java"));
});
project.getPlugins().withType(JavaPlatformPlugin.class, (plugin) -> {
maven.from(project.getComponents().getByName("javaPlatform"));
});
}
});
});
}
}

View File

@@ -0,0 +1,26 @@
package org.springframework.gradle.maven;
import io.spring.gradle.convention.Utils;
import org.gradle.api.Action;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.Task;
public class PublishArtifactsPlugin implements Plugin<Project> {
@Override
public void apply(Project project) {
project.getTasks().register("publishArtifacts", new Action<Task>() {
@Override
public void execute(Task publishArtifacts) {
publishArtifacts.setGroup("Publishing");
publishArtifacts.setDescription("Publish the artifacts to either Artifactory or Maven Central based on the version");
if (Utils.isRelease(project)) {
publishArtifacts.dependsOn("publishToOssrh");
}
else {
publishArtifacts.dependsOn("artifactoryPublish");
}
}
});
}
}

View File

@@ -0,0 +1,29 @@
package org.springframework.gradle.maven;
import org.gradle.api.Action;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.artifacts.repositories.MavenArtifactRepository;
import org.gradle.api.publish.PublishingExtension;
import org.gradle.api.publish.maven.plugins.MavenPublishPlugin;
import java.io.File;
public class PublishLocalPlugin implements Plugin<Project> {
@Override
public void apply(Project project) {
project.getPlugins().withType(MavenPublishPlugin.class).all(new Action<MavenPublishPlugin>() {
@Override
public void execute(MavenPublishPlugin mavenPublish) {
PublishingExtension publishing = project.getExtensions().getByType(PublishingExtension.class);
publishing.getRepositories().maven(new Action<MavenArtifactRepository>() {
@Override
public void execute(MavenArtifactRepository maven) {
maven.setName("local");
maven.setUrl(new File(project.getRootProject().getBuildDir(), "publications/repos"));
}
});
}
});
}
}

View File

@@ -0,0 +1,21 @@
package org.springframework.gradle.maven;
import io.spring.gradle.convention.ArtifactoryPlugin;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.plugins.PluginManager;
import org.gradle.api.publish.maven.plugins.MavenPublishPlugin;
public class SpringMavenPlugin implements Plugin<Project> {
@Override
public void apply(Project project) {
PluginManager pluginManager = project.getPluginManager();
pluginManager.apply(MavenPublishPlugin.class);
pluginManager.apply(SpringSigningPlugin.class);
pluginManager.apply(MavenPublishingConventionsPlugin.class);
pluginManager.apply(PublishAllJavaComponentsPlugin.class);
pluginManager.apply(PublishLocalPlugin.class);
pluginManager.apply(PublishArtifactsPlugin.class);
pluginManager.apply(ArtifactoryPlugin.class);
}
}

View File

@@ -0,0 +1,28 @@
package org.springframework.gradle.maven;
import io.github.gradlenexus.publishplugin.NexusPublishExtension;
import io.github.gradlenexus.publishplugin.NexusPublishPlugin;
import io.github.gradlenexus.publishplugin.NexusRepository;
import org.gradle.api.Action;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import java.net.URI;
import java.time.Duration;
public class SpringNexusPublishPlugin implements Plugin<Project> {
@Override
public void apply(Project project) {
project.getPlugins().apply(NexusPublishPlugin.class);
NexusPublishExtension nexusPublishing = project.getExtensions().findByType(NexusPublishExtension.class);
nexusPublishing.getRepositories().create("ossrh", new Action<NexusRepository>() {
@Override
public void execute(NexusRepository nexusRepository) {
nexusRepository.getNexusUrl().set(URI.create("https://s01.oss.sonatype.org/service/local/"));
nexusRepository.getSnapshotRepositoryUrl().set(URI.create("https://s01.oss.sonatype.org/content/repositories/snapshots/"));
}
});
nexusPublishing.getConnectTimeout().set(Duration.ofMinutes(3));
nexusPublishing.getClientTimeout().set(Duration.ofMinutes(3));
}
}

View File

@@ -0,0 +1,70 @@
/*
* Copyright 2016-2019 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. You may obtain a copy of
* the License at
*
* https://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 org.springframework.gradle.maven;
import org.gradle.api.Action;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.publish.Publication;
import org.gradle.api.publish.PublishingExtension;
import org.gradle.api.publish.plugins.PublishingPlugin;
import org.gradle.plugins.signing.SigningExtension;
import org.gradle.plugins.signing.SigningPlugin;
import java.util.concurrent.Callable;
public class SpringSigningPlugin implements Plugin<Project> {
@Override
public void apply(Project project) {
project.getPluginManager().apply(SigningPlugin.class);
project.getPlugins().withType(SigningPlugin.class).all(new Action<SigningPlugin>() {
@Override
public void execute(SigningPlugin signingPlugin) {
boolean hasSigningKey = project.hasProperty("signing.keyId") || project.hasProperty("signingKey");
if (hasSigningKey) {
sign(project);
}
}
});
}
private void sign(Project project) {
SigningExtension signing = project.getExtensions().findByType(SigningExtension.class);
signing.setRequired(new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
return project.getGradle().getTaskGraph().hasTask("publishArtifacts");
}
});
String signingKeyId = (String) project.findProperty("signingKeyId");
String signingKey = (String) project.findProperty("signingKey");
String signingPassword = (String) project.findProperty("signingPassword");
if (signingKeyId != null) {
signing.useInMemoryPgpKeys(signingKeyId, signingKey, signingPassword);
} else {
signing.useInMemoryPgpKeys(signingKey, signingPassword);
}
project.getPlugins().withType(PublishAllJavaComponentsPlugin.class).all(new Action<PublishAllJavaComponentsPlugin>() {
@Override
public void execute(PublishAllJavaComponentsPlugin publishingPlugin) {
PublishingExtension publishing = project.getExtensions().findByType(PublishingExtension.class);
Publication maven = publishing.getPublications().getByName("mavenJava");
signing.sign(maven);
}
});
}
}

View File

@@ -0,0 +1,43 @@
/*
* Copyright 2002-2021 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.
* You may obtain a copy of the License at
*
* https://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 org.springframework.gradle.propdeps
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.plugins.ide.eclipse.EclipsePlugin
/**
* Plugin to allow optional and provided dependency configurations to work with the
* standard gradle 'eclipse' plugin
*
* @author Phillip Webb
*/
class PropDepsEclipsePlugin implements Plugin<Project> {
public void apply(Project project) {
project.plugins.apply(PropDepsPlugin)
project.plugins.apply(EclipsePlugin)
project.eclipse {
classpath {
plusConfigurations += [project.configurations.provided, project.configurations.optional]
}
}
}
}

View File

@@ -0,0 +1,46 @@
/*
* Copyright 2002-2021 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.
* You may obtain a copy of the License at
*
* https://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 org.springframework.gradle.propdeps
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.plugins.ide.idea.IdeaPlugin
/**
* Plugin to allow optional and provided dependency configurations to work with the
* standard gradle 'idea' plugin
*
* @author Phillip Webb
* @author Brian Clozel
* @link https://youtrack.jetbrains.com/issue/IDEA-107046
* @link https://youtrack.jetbrains.com/issue/IDEA-117668
*/
class PropDepsIdeaPlugin implements Plugin<Project> {
public void apply(Project project) {
project.plugins.apply(PropDepsPlugin)
project.plugins.apply(IdeaPlugin)
project.idea.module {
// IDEA internally deals with 4 scopes : COMPILE, TEST, PROVIDED, RUNTIME
// but only PROVIDED seems to be picked up
scopes.PROVIDED.plus += [project.configurations.provided]
scopes.PROVIDED.plus += [project.configurations.optional]
}
}
}

View File

@@ -0,0 +1,76 @@
/*
* Copyright 2002-2021 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.
* You may obtain a copy of the License at
*
* https://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 org.springframework.gradle.propdeps
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.artifacts.Configuration
import org.gradle.api.plugins.JavaLibraryPlugin
import org.gradle.api.plugins.JavaPlugin
import org.gradle.api.tasks.javadoc.Javadoc
/**
* Plugin to allow 'optional' and 'provided' dependency configurations
*
* As stated in the maven documentation, provided scope "is only available on the compilation and test classpath,
* and is not transitive".
*
* This plugin creates two new configurations, and each one:
* <ul>
* <li>is a parent of the compile configuration</li>
* <li>is not visible, not transitive</li>
* <li>all dependencies are excluded from the default configuration</li>
* </ul>
*
* @author Phillip Webb
* @author Brian Clozel
* @author Rob Winch
*
* @see <a href="https://www.gradle.org/docs/current/userguide/java_plugin.html#N121CF">Maven documentation</a>
* @see <a href="https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html#Dependency_Scope">Gradle configurations</a>
* @see PropDepsEclipsePlugin
* @see PropDepsIdeaPlugin
*/
class PropDepsPlugin implements Plugin<Project> {
public void apply(Project project) {
project.plugins.apply(JavaPlugin)
Configuration provided = addConfiguration(project, "provided")
Configuration optional = addConfiguration(project, "optional")
Javadoc javadoc = project.tasks.getByName(JavaPlugin.JAVADOC_TASK_NAME)
javadoc.classpath = javadoc.classpath.plus(provided).plus(optional)
}
private Configuration addConfiguration(Project project, String name) {
Configuration configuration = project.configurations.create(name)
configuration.extendsFrom(project.configurations.implementation)
project.plugins.withType(JavaLibraryPlugin, {
configuration.extendsFrom(project.configurations.api)
})
project.sourceSets.all {
compileClasspath += configuration
runtimeClasspath += configuration
}
return configuration
}
}

View File

@@ -0,0 +1,123 @@
/*
* Copyright 2019-2020 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.
* You may obtain a copy of the License at
*
* https://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 org.springframework.gradle.sagan;
import java.util.regex.Pattern;
/**
* Domain object for creating a new release version.
*/
public class Release {
private String version;
private ReleaseStatus status;
private boolean current;
private String referenceDocUrl;
private String apiDocUrl;
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
public ReleaseStatus getStatus() {
return status;
}
public void setStatus(ReleaseStatus status) {
this.status = status;
}
public boolean isCurrent() {
return current;
}
public void setCurrent(boolean current) {
this.current = current;
}
public String getReferenceDocUrl() {
return referenceDocUrl;
}
public void setReferenceDocUrl(String referenceDocUrl) {
this.referenceDocUrl = referenceDocUrl;
}
public String getApiDocUrl() {
return apiDocUrl;
}
public void setApiDocUrl(String apiDocUrl) {
this.apiDocUrl = apiDocUrl;
}
@Override
public String toString() {
return "Release{" +
"version='" + version + '\'' +
", status=" + status +
", current=" + current +
", referenceDocUrl='" + referenceDocUrl + '\'' +
", apiDocUrl='" + apiDocUrl + '\'' +
'}';
}
public enum ReleaseStatus {
/**
* Unstable version with limited support
*/
SNAPSHOT,
/**
* Pre-Release version meant to be tested by the community
*/
PRERELEASE,
/**
* Release Generally Available on public artifact repositories and enjoying full support from maintainers
*/
GENERAL_AVAILABILITY;
private static final Pattern PRERELEASE_PATTERN = Pattern.compile("[A-Za-z0-9\\.\\-]+?(M|RC)\\d+");
private static final String SNAPSHOT_SUFFIX = "SNAPSHOT";
/**
* Parse the ReleaseStatus from a String
* @param version a project version
* @return the release status for this version
*/
public static ReleaseStatus parse(String version) {
if (version == null) {
throw new IllegalArgumentException("version cannot be null");
}
if (version.endsWith(SNAPSHOT_SUFFIX)) {
return SNAPSHOT;
}
if (PRERELEASE_PATTERN.matcher(version).matches()) {
return PRERELEASE;
}
return GENERAL_AVAILABILITY;
}
}
}

View File

@@ -0,0 +1,93 @@
/*
* Copyright 2019-2020 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.
* You may obtain a copy of the License at
*
* https://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 org.springframework.gradle.sagan;
import com.google.gson.Gson;
import okhttp3.*;
import java.io.IOException;
import java.util.Base64;
/**
* Implements necessary calls to the Sagan API See https://spring.io/restdocs/index.html
*/
public class SaganApi {
private String baseUrl = "https://spring.io/api";
private OkHttpClient client;
private Gson gson = new Gson();
public SaganApi(String gitHubToken) {
this.client = new OkHttpClient.Builder()
.addInterceptor(new BasicInterceptor("not-used", gitHubToken))
.build();
}
public void setBaseUrl(String baseUrl) {
this.baseUrl = baseUrl;
}
public void createReleaseForProject(Release release, String projectName) {
String url = this.baseUrl + "/projects/" + projectName + "/releases";
String releaseJsonString = gson.toJson(release);
RequestBody body = RequestBody.create(MediaType.parse("application/json"), releaseJsonString);
Request request = new Request.Builder()
.url(url)
.post(body)
.build();
try {
Response response = this.client.newCall(request).execute();
if (!response.isSuccessful()) {
throw new RuntimeException("Could not create release " + release + ". Got response " + response);
}
} catch (IOException fail) {
throw new RuntimeException("Could not create release " + release, fail);
}
}
public void deleteReleaseForProject(String release, String projectName) {
String url = this.baseUrl + "/projects/" + projectName + "/releases/" + release;
Request request = new Request.Builder()
.url(url)
.delete()
.build();
try {
Response response = this.client.newCall(request).execute();
if (!response.isSuccessful()) {
throw new RuntimeException("Could not delete release " + release + ". Got response " + response);
}
} catch (IOException fail) {
throw new RuntimeException("Could not delete release " + release, fail);
}
}
private static class BasicInterceptor implements Interceptor {
private final String token;
public BasicInterceptor(String username, String token) {
this.token = Base64.getEncoder().encodeToString((username + ":" + token).getBytes());
}
@Override
public okhttp3.Response intercept(Chain chain) throws IOException {
Request request = chain.request().newBuilder()
.addHeader("Authorization", "Basic " + this.token).build();
return chain.proceed(request);
}
}
}

View File

@@ -0,0 +1,86 @@
/*
* Copyright 2019-2020 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.
* You may obtain a copy of the License at
*
* https://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 org.springframework.gradle.sagan;
import org.gradle.api.DefaultTask;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.TaskAction;
public class SaganCreateReleaseTask extends DefaultTask {
@Input
private String gitHubAccessToken;
@Input
private String version;
@Input
private String apiDocUrl;
@Input
private String referenceDocUrl;
@Input
private String projectName;
@TaskAction
public void saganCreateRelease() {
SaganApi sagan = new SaganApi(this.gitHubAccessToken);
Release release = new Release();
release.setVersion(this.version);
release.setApiDocUrl(this.apiDocUrl);
release.setReferenceDocUrl(this.referenceDocUrl);
sagan.createReleaseForProject(release, this.projectName);
}
public String getGitHubAccessToken() {
return gitHubAccessToken;
}
public void setGitHubAccessToken(String gitHubAccessToken) {
this.gitHubAccessToken = gitHubAccessToken;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
public String getApiDocUrl() {
return apiDocUrl;
}
public void setApiDocUrl(String apiDocUrl) {
this.apiDocUrl = apiDocUrl;
}
public String getReferenceDocUrl() {
return referenceDocUrl;
}
public void setReferenceDocUrl(String referenceDocUrl) {
this.referenceDocUrl = referenceDocUrl;
}
public String getProjectName() {
return projectName;
}
public void setProjectName(String projectName) {
this.projectName = projectName;
}
}

View File

@@ -0,0 +1,62 @@
/*
* Copyright 2019-2020 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.
* You may obtain a copy of the License at
*
* https://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 org.springframework.gradle.sagan;
import org.gradle.api.DefaultTask;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.TaskAction;
public class SaganDeleteReleaseTask extends DefaultTask {
@Input
private String gitHubAccessToken;
@Input
private String version;
@Input
private String projectName;
@TaskAction
public void saganCreateRelease() {
SaganApi sagan = new SaganApi(this.gitHubAccessToken);
sagan.deleteReleaseForProject(this.version, this.projectName);
}
public String getGitHubAccessToken() {
return gitHubAccessToken;
}
public void setGitHubAccessToken(String gitHubAccessToken) {
this.gitHubAccessToken = gitHubAccessToken;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
public String getProjectName() {
return projectName;
}
public void setProjectName(String projectName) {
this.projectName = projectName;
}
}

View File

@@ -0,0 +1,47 @@
/*
* Copyright 2019-2020 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.
* You may obtain a copy of the License at
*
* https://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 org.springframework.gradle.sagan;
import io.spring.gradle.convention.Utils;
import org.gradle.api.*;
public class SaganPlugin implements Plugin<Project> {
@Override
public void apply(Project project) {
project.getTasks().register("saganCreateRelease", SaganCreateReleaseTask.class, new Action<SaganCreateReleaseTask>() {
@Override
public void execute(SaganCreateReleaseTask saganCreateVersion) {
saganCreateVersion.setGroup("Release");
saganCreateVersion.setDescription("Creates a new version for the specified project on spring.io");
saganCreateVersion.setVersion((String) project.findProperty("nextVersion"));
saganCreateVersion.setProjectName(Utils.getProjectName(project));
saganCreateVersion.setGitHubAccessToken((String) project.findProperty("gitHubAccessToken"));
}
});
project.getTasks().register("saganDeleteRelease", SaganDeleteReleaseTask.class, new Action<SaganDeleteReleaseTask>() {
@Override
public void execute(SaganDeleteReleaseTask saganDeleteVersion) {
saganDeleteVersion.setGroup("Release");
saganDeleteVersion.setDescription("Delete a version for the specified project on spring.io");
saganDeleteVersion.setVersion((String) project.findProperty("previousVersion"));
saganDeleteVersion.setProjectName(Utils.getProjectName(project));
saganDeleteVersion.setGitHubAccessToken((String) project.findProperty("gitHubAccessToken"));
}
});
}
}

View File

@@ -0,0 +1 @@
implementation-class=io.spring.gradle.convention.ArtifactoryPlugin

View File

@@ -0,0 +1 @@
implementation-class=io.spring.gradle.convention.MavenBomPlugin

View File

@@ -0,0 +1 @@
implementation-class=io.spring.gradle.convention.CheckstylePlugin

View File

@@ -0,0 +1 @@
implementation-class=io.spring.gradle.convention.DocsPlugin

View File

@@ -0,0 +1 @@
implementation-class=io.spring.gradle.convention.IncludeCheckRemotePlugin

View File

@@ -0,0 +1 @@
implementation-class=io.spring.gradle.convention.IntegrationTestPlugin

View File

@@ -0,0 +1 @@
implementation-class=io.spring.gradle.convention.JacocoPlugin

View File

@@ -0,0 +1 @@
implementation-class=io.spring.gradle.convention.JavadocApiPlugin

View File

@@ -0,0 +1 @@
implementation-class=io.spring.gradle.convention.JavadocOptionsPlugin

View File

@@ -0,0 +1 @@
implementation-class=io.spring.gradle.convention.RepositoryConventionPlugin

View File

@@ -0,0 +1 @@
implementation-class=io.spring.gradle.convention.RootProjectPlugin

View File

@@ -0,0 +1 @@
implementation-class=io.spring.gradle.convention.SpringModulePlugin

View File

@@ -0,0 +1 @@
implementation-class=io.spring.gradle.convention.SpringSampleBootPlugin

View File

@@ -0,0 +1 @@
implementation-class=io.spring.gradle.convention.SpringSampleWarPlugin

View File

@@ -0,0 +1 @@
implementation-class=io.spring.gradle.convention.SpringSamplePlugin

View File

@@ -0,0 +1 @@
implementation-class=io.spring.gradle.convention.SpringTestPlugin

View File

@@ -0,0 +1 @@
implementation-class=io.spring.gradle.convention.SpringDependencyManagementConventionPlugin

View File

@@ -0,0 +1 @@
implementation-class=io.spring.gradle.convention.TestsConfigurationPlugin

View File

@@ -0,0 +1,59 @@
/*
* Copyright 2002-2017 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. You may obtain a copy of
* the License at
*
* https://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 io.spring.gradle;
import org.apache.commons.io.FileUtils;
import org.gradle.testkit.runner.GradleRunner;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Paths;
import java.util.Enumeration;
public class TestKit {
final File buildDir;
public TestKit(File buildDir) {
this.buildDir = buildDir;
}
public File getRootDir() {
return buildDir;
}
public GradleRunner withProjectDir(File projectDir) throws IOException {
FileUtils.copyDirectory(projectDir, buildDir);
return GradleRunner.create()
.withProjectDir(buildDir)
.withPluginClasspath();
}
public GradleRunner withProjectResource(String projectResourceName) throws IOException, URISyntaxException {
ClassLoader classLoader = getClass().getClassLoader();
Enumeration<URL> resources = classLoader.getResources(projectResourceName);
if(!resources.hasMoreElements()) {
throw new IOException("Cannot find resource " + projectResourceName + " with " + classLoader);
}
URL resourceUrl = resources.nextElement();
File projectDir = Paths.get(resourceUrl.toURI()).toFile();
return withProjectDir(projectDir);
}
}

View File

@@ -0,0 +1,111 @@
/*
* Copyright 2002-2021 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. You may obtain a copy of
* the License at
*
* https://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 io.spring.gradle.convention;
import io.spring.gradle.IncludeRepoTask;
import org.apache.commons.io.FileUtils;
import org.gradle.api.Project;
import org.gradle.api.tasks.GradleBuild;
import org.gradle.testfixtures.ProjectBuilder;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import java.util.Arrays;
import static org.assertj.core.api.Assertions.assertThat;
class IncludeCheckRemotePluginTest {
Project rootProject;
@AfterEach
public void cleanup() throws Exception {
if (rootProject != null) {
FileUtils.deleteDirectory(rootProject.getProjectDir());
}
}
@Test
void applyWhenExtensionPropertiesNoTasksThenCreateCheckRemoteTaskWithDefaultTask() {
this.rootProject = ProjectBuilder.builder().build();
this.rootProject.getPluginManager().apply(IncludeCheckRemotePlugin.class);
this.rootProject.getExtensions().configure(IncludeCheckRemotePlugin.IncludeCheckRemoteExtension.class,
(includeCheckRemoteExtension) -> {
includeCheckRemoteExtension.setProperty("repository", "my-project/my-repository");
includeCheckRemoteExtension.setProperty("ref", "main");
});
GradleBuild checkRemote = (GradleBuild) this.rootProject.getTasks().named("checkRemote").get();
assertThat(checkRemote.getTasks()).containsExactly("check");
}
@Test
void applyWhenExtensionPropertiesTasksThenCreateCheckRemoteWithProvidedTasks() {
this.rootProject = ProjectBuilder.builder().build();
this.rootProject.getPluginManager().apply(IncludeCheckRemotePlugin.class);
this.rootProject.getExtensions().configure(IncludeCheckRemotePlugin.IncludeCheckRemoteExtension.class,
(includeCheckRemoteExtension) -> {
includeCheckRemoteExtension.setProperty("repository", "my-project/my-repository");
includeCheckRemoteExtension.setProperty("ref", "main");
includeCheckRemoteExtension.setProperty("tasks", Arrays.asList("clean", "build", "test"));
});
GradleBuild checkRemote = (GradleBuild) this.rootProject.getTasks().named("checkRemote").get();
assertThat(checkRemote.getTasks()).containsExactly("clean", "build", "test");
}
@Test
void applyWhenExtensionPropertiesThenRegisterIncludeRepoTaskWithExtensionProperties() {
this.rootProject = ProjectBuilder.builder().build();
this.rootProject.getPluginManager().apply(IncludeCheckRemotePlugin.class);
this.rootProject.getExtensions().configure(IncludeCheckRemotePlugin.IncludeCheckRemoteExtension.class,
(includeCheckRemoteExtension) -> {
includeCheckRemoteExtension.setProperty("repository", "my-project/my-repository");
includeCheckRemoteExtension.setProperty("ref", "main");
});
IncludeRepoTask includeRepo = (IncludeRepoTask) this.rootProject.getTasks().named("includeRepo").get();
assertThat(includeRepo).isNotNull();
assertThat(includeRepo.getRepository().get()).isEqualTo("my-project/my-repository");
assertThat(includeRepo.getRef().get()).isEqualTo("main");
}
@Test
void applyWhenRegisterTasksThenCheckRemoteDirSameAsIncludeRepoOutputDir() {
this.rootProject = ProjectBuilder.builder().build();
this.rootProject.getPluginManager().apply(IncludeCheckRemotePlugin.class);
this.rootProject.getExtensions().configure(IncludeCheckRemotePlugin.IncludeCheckRemoteExtension.class,
(includeCheckRemoteExtension) -> {
includeCheckRemoteExtension.setProperty("repository", "my-project/my-repository");
includeCheckRemoteExtension.setProperty("ref", "main");
});
IncludeRepoTask includeRepo = (IncludeRepoTask) this.rootProject.getTasks().named("includeRepo").get();
GradleBuild checkRemote = (GradleBuild) this.rootProject.getTasks().named("checkRemote").get();
assertThat(checkRemote.getDir()).isEqualTo(includeRepo.getOutputDirectory());
}
@Test
void applyWhenNoExtensionPropertiesThenRegisterTasks() {
this.rootProject = ProjectBuilder.builder().build();
this.rootProject.getPluginManager().apply(IncludeCheckRemotePlugin.class);
IncludeRepoTask includeRepo = (IncludeRepoTask) this.rootProject.getTasks().named("includeRepo").get();
GradleBuild checkRemote = (GradleBuild) this.rootProject.getTasks().named("checkRemote").get();
assertThat(includeRepo).isNotNull();
assertThat(checkRemote).isNotNull();
}
}

View File

@@ -0,0 +1,52 @@
/*
* Copyright 2002-2016 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. You may obtain a copy of
* the License at
*
* https://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 io.spring.gradle.convention;
import org.apache.commons.io.FileUtils;
import org.gradle.api.Project;
import org.gradle.api.plugins.JavaPlugin;
import org.gradle.testfixtures.ProjectBuilder;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import java.io.File;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Rob Winch
*/
public class IntegrationPluginTest {
Project rootProject;
@AfterEach
public void cleanup() throws Exception {
if (rootProject != null) {
FileUtils.deleteDirectory(rootProject.getProjectDir());
}
}
@Test
public void applyWhenNoSourceThenIntegrationTestTaskNull() {
rootProject = ProjectBuilder.builder().build();
rootProject.getPlugins().apply(JavaPlugin.class);
rootProject.getPlugins().apply(IntegrationTestPlugin.class);
assertThat(rootProject.getTasks().findByPath("integrationTest")).isNull();
}
}

View File

@@ -0,0 +1,52 @@
package io.spring.gradle.convention;
import io.spring.gradle.TestKit;
import org.gradle.testkit.runner.BuildResult;
import org.gradle.testkit.runner.TaskOutcome;
import org.junit.Test;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.io.TempDir;
import java.io.File;
import java.nio.file.Path;
import static org.assertj.core.api.Assertions.assertThat;
public class IntegrationTestPluginITest {
private io.spring.gradle.TestKit testKit;
@BeforeEach
void setup(@TempDir Path tempDir) {
this.testKit = new TestKit(tempDir.toFile());
}
@Test
public void checkWithJavaPlugin() throws Exception {
BuildResult result = this.testKit.withProjectResource("samples/integrationtest/withjava/")
.withArguments("check")
.build();
assertThat(result.task(":check").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
assertThat(new File(testKit.getRootDir(), "build/test-results/integrationTest/")).exists();
assertThat(new File(testKit.getRootDir(), "build/reports/tests/integrationTest/")).exists();
}
@Test
public void checkWithPropdeps() throws Exception {
BuildResult result = this.testKit.withProjectResource("samples/integrationtest/withpropdeps/")
.withArguments("check")
.build();
assertThat(result.task(":check").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
assertThat(new File(testKit.getRootDir(), "build/test-results/integrationTest/")).exists();
assertThat(new File(testKit.getRootDir(), "build/reports/tests/integrationTest/")).exists();
}
@Test
public void checkWithGroovy() throws Exception {
BuildResult result = this.testKit.withProjectResource("samples/integrationtest/withgroovy/")
.withArguments("check")
.build();
assertThat(result.task(":check").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
assertThat(new File(testKit.getRootDir(), "build/test-results/integrationTest/")).exists();
assertThat(new File(testKit.getRootDir(), "build/reports/tests/integrationTest/")).exists();
}
}

View File

@@ -0,0 +1,31 @@
package io.spring.gradle.convention;
import org.gradle.testkit.runner.BuildResult;
import org.gradle.testkit.runner.TaskOutcome;
import org.junit.Test;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.io.TempDir;
import java.io.File;
import java.nio.file.Path;
import static org.assertj.core.api.Assertions.assertThat;
public class JacocoPluginITest{
private io.spring.gradle.TestKit testKit;
@BeforeEach
void setup(@TempDir Path tempDir) {
this.testKit = new io.spring.gradle.TestKit(tempDir.toFile());
}
@Test
public void checkWithJavaPlugin() throws Exception {
BuildResult result = this.testKit.withProjectResource("samples/jacoco/java/")
.withArguments("check")
.build();
assertThat(result.task(":check").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
assertThat(new File(testKit.getRootDir(), "build/jacoco")).exists();
assertThat(new File(testKit.getRootDir(), "build/reports/jacoco/test/html/")).exists();
}
}

View File

@@ -0,0 +1,38 @@
package io.spring.gradle.convention;
import io.spring.gradle.TestKit;
import org.apache.commons.io.FileUtils;
import org.gradle.testkit.runner.BuildResult;
import org.gradle.testkit.runner.TaskOutcome;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import java.io.File;
import java.nio.file.Path;
import static org.assertj.core.api.Assertions.assertThat;
public class JavadocApiPluginITest {
private TestKit testKit;
@BeforeEach
void setup(@TempDir Path tempDir) {
this.testKit = new TestKit(tempDir.toFile());
}
@Test
public void multiModuleApi() throws Exception {
BuildResult result = this.testKit.withProjectResource("samples/javadocapi/multimodule/")
.withArguments("api")
.build();
assertThat(result.task(":api").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
File allClasses = new File(testKit.getRootDir(), "build/api/allclasses-noframe.html");
File index = new File(testKit.getRootDir(), "build/api/allclasses.html");
File listing = allClasses.exists() ? allClasses : index;
String listingText = FileUtils.readFileToString(listing);
assertThat(listingText).contains("sample/Api.html");
assertThat(listingText).contains("sample/Impl.html");
assertThat(listingText).doesNotContain("sample/Sample.html");
}
}

View File

@@ -0,0 +1,56 @@
/*
* Copyright 2002-2016 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. You may obtain a copy of
* the License at
*
* https://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 io.spring.gradle.convention;
import java.io.File;
import org.apache.commons.io.FileUtils;
import static org.assertj.core.api.Assertions.assertThat;
import org.gradle.api.Project;
import org.gradle.api.tasks.javadoc.Javadoc;
import org.gradle.testfixtures.ProjectBuilder;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
/**
* @author Rob Winch
*/
public class JavadocApiPluginTest {
Project rootProject;
@AfterEach
public void cleanup() throws Exception {
if (rootProject != null) {
FileUtils.deleteDirectory(rootProject.getProjectDir());
}
}
@Test
public void applyWhenNotOverrideThenPropertiesDefaulted() {
rootProject = ProjectBuilder.builder().build();
rootProject.getPlugins().apply(JavadocApiPlugin.class);
Javadoc apiTask = (Javadoc) rootProject.getTasks().getByPath("api");
assertThat(apiTask).isNotNull();
assertThat(apiTask.getGroup()).isEqualTo("Documentation");
assertThat(apiTask.getDescription()).isEqualTo("Generates aggregated Javadoc API documentation.");
assertThat(apiTask.getMaxMemory()).isEqualTo("1024m");
assertThat(apiTask.getDestinationDir()).isEqualTo(new File(rootProject.getBuildDir(), "api"));
}
}

View File

@@ -0,0 +1,158 @@
/*
* Copyright 2016-2018 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. You may obtain a copy of
* the License at
*
* https://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 io.spring.gradle.convention;
import org.gradle.api.Project;
import org.gradle.api.artifacts.dsl.RepositoryHandler;
import org.gradle.api.artifacts.repositories.ArtifactRepository;
import org.gradle.api.artifacts.repositories.MavenArtifactRepository;
import org.gradle.api.plugins.ExtraPropertiesExtension;
import org.gradle.testfixtures.ProjectBuilder;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link RepositoryConventionPlugin}.
*/
public class RepositoryConventionPluginTests {
private Project project = ProjectBuilder.builder().build();
@BeforeEach
public void setUp() {
this.project.getProperties().clear();
}
@Test
public void applyWhenIsReleaseThenShouldIncludeReleaseRepo() {
this.project.setVersion("1.0.0.RELEASE");
this.project.getPluginManager().apply(RepositoryConventionPlugin.class);
RepositoryHandler repositories = this.project.getRepositories();
assertReleaseRepository(repositories);
}
@Test
public void applyWhenIsMilestoneThenShouldIncludeMilestoneRepo() {
this.project.setVersion("1.0.0.M1");
this.project.getPluginManager().apply(RepositoryConventionPlugin.class);
RepositoryHandler repositories = this.project.getRepositories();
assertMilestoneRepository(repositories); // milestone
}
@Test
public void applyWhenIsSnapshotThenShouldIncludeSnapshotRepo() {
this.project.setVersion("1.0.0.BUILD-SNAPSHOT");
this.project.getPluginManager().apply(RepositoryConventionPlugin.class);
RepositoryHandler repositories = this.project.getRepositories();
assertSnapshotRepository(repositories);
}
@Test
public void applyWhenIsSnapshotWithForceReleaseThenShouldOnlyIncludeReleaseRepo() {
this.project.getExtensions().getByType(ExtraPropertiesExtension.class)
.set("forceMavenRepositories", "release");
this.project.setVersion("1.0.0.RELEASE");
this.project.getPluginManager().apply(RepositoryConventionPlugin.class);
RepositoryHandler repositories = this.project.getRepositories();
assertReleaseRepository(repositories);
}
@Test
public void applyWhenIsReleaseWithForceMilestoneThenShouldIncludeMilestoneRepo() {
this.project.getExtensions().getByType(ExtraPropertiesExtension.class)
.set("forceMavenRepositories", "milestone");
this.project.setVersion("1.0.0.RELEASE");
this.project.getPluginManager().apply(RepositoryConventionPlugin.class);
RepositoryHandler repositories = this.project.getRepositories();
assertMilestoneRepository(repositories);
}
@Test
public void applyWhenIsReleaseWithForceSnapshotThenShouldIncludeSnapshotRepo() {
this.project.getExtensions().getByType(ExtraPropertiesExtension.class)
.set("forceMavenRepositories", "snapshot");
this.project.setVersion("1.0.0.RELEASE");
this.project.getPluginManager().apply(RepositoryConventionPlugin.class);
RepositoryHandler repositories = this.project.getRepositories();
assertSnapshotRepository(repositories);
}
@Test
public void applyWhenIsReleaseWithForceLocalThenShouldIncludeReleaseAndLocalRepos() {
this.project.getExtensions().getByType(ExtraPropertiesExtension.class)
.set("forceMavenRepositories", "local");
this.project.setVersion("1.0.0.RELEASE");
this.project.getPluginManager().apply(RepositoryConventionPlugin.class);
RepositoryHandler repositories = this.project.getRepositories();
assertThat(repositories).hasSize(5);
assertThat((repositories.get(0)).getName()).isEqualTo("MavenLocal");
}
@Test
public void applyWhenIsReleaseWithForceMilestoneAndLocalThenShouldIncludeMilestoneAndLocalRepos() {
this.project.getExtensions().getByType(ExtraPropertiesExtension.class)
.set("forceMavenRepositories", "milestone,local");
this.project.setVersion("1.0.0.RELEASE");
this.project.getPluginManager().apply(RepositoryConventionPlugin.class);
RepositoryHandler repositories = this.project.getRepositories();
assertThat(repositories).hasSize(6);
assertThat((repositories.get(0)).getName()).isEqualTo("MavenLocal");
}
private void assertSnapshotRepository(RepositoryHandler repositories) {
assertThat(repositories).extracting(ArtifactRepository::getName).hasSize(6);
assertThat(((MavenArtifactRepository) repositories.get(0)).getUrl().toString())
.isEqualTo("https://repo.maven.apache.org/maven2/");
assertThat(((MavenArtifactRepository) repositories.get(1)).getUrl().toString())
.isEqualTo("https://jcenter.bintray.com/");
assertThat(((MavenArtifactRepository) repositories.get(2)).getUrl().toString())
.isEqualTo("https://repo.spring.io/snapshot/");
assertThat(((MavenArtifactRepository) repositories.get(3)).getUrl().toString())
.isEqualTo("https://repo.spring.io/milestone/");
}
private void assertMilestoneRepository(RepositoryHandler repositories) {
assertThat(repositories).extracting(ArtifactRepository::getName).hasSize(5);
assertThat(((MavenArtifactRepository) repositories.get(0)).getUrl().toString())
.isEqualTo("https://repo.maven.apache.org/maven2/");
assertThat(((MavenArtifactRepository) repositories.get(1)).getUrl().toString())
.isEqualTo("https://jcenter.bintray.com/");
assertThat(((MavenArtifactRepository) repositories.get(2)).getUrl().toString())
.isEqualTo("https://repo.spring.io/milestone/");
}
private void assertReleaseRepository(RepositoryHandler repositories) {
assertThat(repositories).extracting(ArtifactRepository::getName).hasSize(4);
assertThat(((MavenArtifactRepository) repositories.get(0)).getUrl().toString())
.isEqualTo("https://repo.maven.apache.org/maven2/");
assertThat(((MavenArtifactRepository) repositories.get(1)).getUrl().toString())
.isEqualTo("https://jcenter.bintray.com/");
assertThat(((MavenArtifactRepository) repositories.get(2)).getUrl().toString())
.isEqualTo("https://repo.spring.io/release/");
}
}

View File

@@ -0,0 +1,70 @@
package io.spring.gradle.convention;
import io.spring.gradle.TestKit;
import org.gradle.testkit.runner.BuildResult;
import org.gradle.testkit.runner.TaskOutcome;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import static org.assertj.core.api.Assertions.assertThat;
public class ShowcaseITest {
private TestKit testKit;
@BeforeEach
void setup(@TempDir Path tempDir) {
this.testKit = new TestKit(tempDir.toFile());
}
@Test
public void build() throws Exception {
BuildResult result = this.testKit.withProjectResource("samples/showcase/")
.withArguments("build", "--stacktrace")
.forwardOutput()
.build();
assertThat(result.getOutput()).contains("BUILD SUCCESSFUL");
}
@Test
@Disabled
public void install() throws Exception {
BuildResult result = this.testKit
.withProjectResource("samples/showcase/")
.withArguments("install", "--stacktrace")
.build();
assertThat(result.getOutput()).contains("SUCCESS");
File pom = new File(testKit.getRootDir(), "sgbcs-core/build/poms/pom-default.xml");
assertThat(pom).exists();
String pomText = new String(Files.readAllBytes(pom.toPath()));
String pomTextNoSpace = pomText.replaceAll("\\s", "");
assertThat(pomText).doesNotContain("<dependencyManagement>");
assertThat(pomTextNoSpace).contains("<dependency>\n <groupId>org.springframework</groupId>\n <artifactId>spring-test</artifactId>\n <scope>test</scope>\n <version>4.3.6.RELEASE</version>\n </dependency>".replaceAll("\\s", ""));
assertThat(pomTextNoSpace).contains("<developers>\n <developer>\n <id>rwinch</id>\n <name>Rob Winch</name>\n <email>rwinch@pivotal.io</email>\n </developer>\n <developer>\n <id>jgrandja</id>\n <name>Joe Grandja</name>\n <email>jgrandja@pivotal.io</email>\n </developer>\n </developers>".replaceAll("\\s", ""));
assertThat(pomTextNoSpace).contains("<scm>\n <connection>scm:git:git://github.com/spring-projects/spring-security</connection>\n <developerConnection>scm:git:git://github.com/spring-projects/spring-security</developerConnection>\n <url>https://github.com/spring-projects/spring-security</url>\n </scm>".replaceAll("\\s", ""));
assertThat(pomTextNoSpace).contains("<description>sgbcs-core</description>");
assertThat(pomTextNoSpace).contains("<url>https://spring.io/spring-security</url>");
assertThat(pomTextNoSpace).contains("<organization>\n <name>spring.io</name>\n <url>https://spring.io/</url>\n </organization>".replaceAll("\\s", ""));
assertThat(pomTextNoSpace).contains(" <licenses>\n <license>\n <name>The Apache Software License, Version 2.0</name>\n <url>https://www.apache.org/licenses/LICENSE-2.0.txt</url>\n <distribution>repo</distribution>\n </license>\n </licenses>".replaceAll("\\s", ""));
assertThat(pomTextNoSpace).contains("<scm>\n <connection>scm:git:git://github.com/spring-projects/spring-security</connection>\n <developerConnection>scm:git:git://github.com/spring-projects/spring-security</developerConnection>\n <url>https://github.com/spring-projects/spring-security</url>\n </scm>".replaceAll("\\s", ""));
File bom = new File(testKit.getRootDir(), "bom/build/poms/pom-default.xml");
assertThat(bom).exists();
assertThat(bom).hasContent("<artifactId>sgbcs-core</artifactId>");
BuildResult secondBuild = this.testKit.withProjectResource("samples/showcase/").withArguments("mavenBom", "--stacktrace").build();
// mavenBom is not up to date since install is never up to date
assertThat(result.task(":bom:mavenBom").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
}
}

View File

@@ -0,0 +1,61 @@
package io.spring.gradle.convention;
import io.spring.gradle.TestKit;
import org.apache.commons.io.IOUtils;
import org.gradle.testkit.runner.BuildResult;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.LinkedHashMap;
import static org.assertj.core.api.Assertions.assertThat;
public class SpringMavenPluginITest {
private TestKit testKit;
@BeforeEach
void setup(@TempDir Path tempDir) {
this.testKit = new TestKit(tempDir.toFile());
}
@Disabled
@Test
public void install() throws Exception {
BuildResult result = this.testKit.withProjectResource("samples/maven/install")
.withArguments("install")
.build();
assertThat(result.getOutput()).contains("SUCCESS");
File pom = new File(testKit.getRootDir(), "build/poms/pom-default.xml");
assertThat(pom).exists();
String pomText = new String(Files.readAllBytes(pom.toPath()));
assertThat(pomText.replaceAll("\\s", "")).contains("<dependency>\n <groupId>aopalliance</groupId>\n <artifactId>aopalliance</artifactId>\n <version>1.0</version>\n <scope>compile</scope>\n <optional>true</optional>\n </dependency>".replaceAll("\\s", ""));
}
@Disabled
@Test
public void signArchivesWhenInMemory() throws Exception {
LinkedHashMap<String, String> map = new LinkedHashMap<String, String>(2);
map.put("ORG_GRADLE_PROJECT_signingKey", getSigningKey());
map.put("ORG_GRADLE_PROJECT_signingPassword", "password");
BuildResult result = this.testKit.withProjectResource("samples/maven/signing")
.withArguments("signArchives")
.withEnvironment(map)
.forwardOutput()
.build();
assertThat(result.getOutput()).contains("SUCCESS");
final File jar = new File(testKit.getRootDir(), "build/libs/signing-1.0.0.RELEASE.jar");
assertThat(jar).exists();
File signature = new File(jar.getAbsolutePath() + ".asc");
assertThat(signature).exists();
}
public String getSigningKey() throws Exception {
return IOUtils.toString(getClass().getResource("/test-private.pgp"));
}
}

View File

@@ -0,0 +1,31 @@
package io.spring.gradle.convention;
import io.spring.gradle.TestKit;
import org.gradle.testkit.runner.BuildResult;
import org.gradle.testkit.runner.TaskOutcome;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import java.nio.file.Path;
import static org.assertj.core.api.Assertions.assertThat;
public class TestsConfigurationPluginITest {
private TestKit testKit;
@BeforeEach
void setup(@TempDir Path tempDir) {
this.testKit = new TestKit(tempDir.toFile());
}
@Test
public void canFindDepencency() throws Exception {
BuildResult result = this.testKit.withProjectResource("samples/testsconfiguration")
.withArguments("check")
.build();
assertThat(result.task(":web:check").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
}
}

View File

@@ -0,0 +1,147 @@
package io.spring.gradle.convention;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.when;
import org.gradle.api.Project;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
@ExtendWith(MockitoExtension.class)
public class UtilsTest {
@Mock
Project project;
@Mock
Project rootProject;
@Test
public void getProjectName() {
when(project.getRootProject()).thenReturn(rootProject);
when(rootProject.getName()).thenReturn("spring-security");
assertThat(Utils.getProjectName(project)).isEqualTo("spring-security");
}
@Test
public void getProjectNameWhenEndsWithBuildThenStrippedOut() {
when(project.getRootProject()).thenReturn(rootProject);
when(rootProject.getName()).thenReturn("spring-security-build");
assertThat(Utils.getProjectName(project)).isEqualTo("spring-security");
}
@Test
public void isSnapshotValidWithDot() {
when(project.getVersion()).thenReturn("1.0.0.BUILD-SNAPSHOT");
assertThat(Utils.isSnapshot(project)).isTrue();
}
@Test
public void isSnapshotValidWithNoBuild() {
when(project.getVersion()).thenReturn("1.0.0-SNAPSHOT");
assertThat(Utils.isSnapshot(project)).isTrue();
}
@Test
public void isSnapshotValidWithDash() {
when(project.getVersion()).thenReturn("Theme-BUILD-SNAPSHOT");
assertThat(Utils.isSnapshot(project)).isTrue();
}
@Test
public void isSnapshotInvalid() {
when(project.getVersion()).thenReturn("1.0.0.SNAPSHOT");
assertThat(Utils.isSnapshot(project)).isFalse();
}
@Test
public void isMilestoneValidWithDot() {
when(project.getVersion()).thenReturn("1.0.0.M1");
assertThat(Utils.isMilestone(project)).isTrue();
}
@Test
public void isMilestoneValidWithDash() {
when(project.getVersion()).thenReturn("Theme-M1");
assertThat(Utils.isMilestone(project)).isTrue();
}
@Test
public void isMilestoneValidWithNumberDash() {
when(project.getVersion()).thenReturn("1.0.0-M1");
assertThat(Utils.isMilestone(project)).isTrue();
}
@Test
public void isMilestoneInvalid() {
when(project.getVersion()).thenReturn("1.0.0.M");
assertThat(Utils.isMilestone(project)).isFalse();
}
@Test
public void isReleaseCandidateValidWithDot() {
when(project.getVersion()).thenReturn("1.0.0.RC1");
assertThat(Utils.isMilestone(project)).isTrue();
}
@Test
public void isReleaseCandidateValidWithNumberDash() {
when(project.getVersion()).thenReturn("1.0.0-RC1");
assertThat(Utils.isMilestone(project)).isTrue();
}
@Test
public void isReleaseCandidateValidWithDash() {
when(project.getVersion()).thenReturn("Theme-RC1");
assertThat(Utils.isMilestone(project)).isTrue();
}
@Test
public void isReleaseCandidateInvalid() {
when(project.getVersion()).thenReturn("1.0.0.RC");
assertThat(Utils.isMilestone(project)).isFalse();
}
@Test
public void isReleaseValidWithDot() {
when(project.getVersion()).thenReturn("1.0.0.RELEASE");
assertThat(Utils.isRelease(project)).isTrue();
}
@Test
public void isReleaseValidWithNoRelease() {
when(project.getVersion()).thenReturn("1.0.0");
assertThat(Utils.isRelease(project)).isTrue();
}
@Test
public void isReleaseValidWithDash() {
when(project.getVersion()).thenReturn("Theme-RELEASE");
assertThat(Utils.isRelease(project)).isTrue();
}
@Test
public void isServiceReleaseValid() {
when(project.getVersion()).thenReturn("Theme-SR1");
assertThat(Utils.isRelease(project)).isTrue();
}
}

View File

@@ -0,0 +1,85 @@
/*
* Copyright 2019-2020 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.
* You may obtain a copy of the License at
*
* https://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 io.spring.gradle.convention.sagan;
import okhttp3.mockwebserver.MockResponse;
import okhttp3.mockwebserver.MockWebServer;
import okhttp3.mockwebserver.RecordedRequest;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.gradle.sagan.Release;
import org.springframework.gradle.sagan.SaganApi;
import java.nio.charset.Charset;
import java.util.concurrent.TimeUnit;
import static org.assertj.core.api.Assertions.assertThat;
public class SaganApiTests {
private MockWebServer server;
private SaganApi sagan;
private String baseUrl;
@BeforeEach
public void setup() throws Exception {
this.server = new MockWebServer();
this.server.start();
this.sagan = new SaganApi("mock-oauth-token");
this.baseUrl = this.server.url("/api").toString();
this.sagan.setBaseUrl(this.baseUrl);
}
@AfterEach
public void cleanup() throws Exception {
this.server.shutdown();
}
@Test
public void createWhenValidThenNoException() throws Exception {
this.server.enqueue(new MockResponse());
Release release = new Release();
release.setVersion("5.6.0-SNAPSHOT");
release.setApiDocUrl("https://docs.spring.io/spring-security/site/docs/{version}/api/");
release.setReferenceDocUrl("https://docs.spring.io/spring-security/site/docs/{version}/reference/html5/");
this.sagan.createReleaseForProject(release, "spring-security");
RecordedRequest request = this.server.takeRequest(1, TimeUnit.SECONDS);
assertThat(request.getRequestUrl().toString()).isEqualTo(this.baseUrl + "/projects/spring-security/releases");
assertThat(request.getMethod()).isEqualToIgnoringCase("post");
assertThat(request.getHeaders().get("Authorization")).isEqualTo("Basic bm90LXVzZWQ6bW9jay1vYXV0aC10b2tlbg==");
assertThat(request.getBody().readString(Charset.defaultCharset())).isEqualToIgnoringWhitespace("{\n" +
" \"version\":\"5.6.0-SNAPSHOT\",\n" +
" \"current\":false,\n" +
" \"referenceDocUrl\":\"https://docs.spring.io/spring-security/site/docs/{version}/reference/html5/\",\n" +
" \"apiDocUrl\":\"https://docs.spring.io/spring-security/site/docs/{version}/api/\"\n" +
"}");
}
@Test
public void deleteWhenValidThenNoException() throws Exception {
this.server.enqueue(new MockResponse());
this.sagan.deleteReleaseForProject("5.6.0-SNAPSHOT", "spring-security");
RecordedRequest request = this.server.takeRequest(1, TimeUnit.SECONDS);
assertThat(request.getRequestUrl().toString()).isEqualTo(this.baseUrl + "/projects/spring-security/releases/5.6.0-SNAPSHOT");
assertThat(request.getMethod()).isEqualToIgnoringCase("delete");
assertThat(request.getHeaders().get("Authorization")).isEqualTo("Basic bm90LXVzZWQ6bW9jay1vYXV0aC10b2tlbg==");
assertThat(request.getBody().readString(Charset.defaultCharset())).isEmpty();
}
}

View File

@@ -0,0 +1,388 @@
package io.spring.gradle.github.milestones;
import okhttp3.mockwebserver.MockResponse;
import okhttp3.mockwebserver.MockWebServer;
import okhttp3.mockwebserver.RecordedRequest;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.gradle.github.milestones.GitHubMilestoneApi;
import org.springframework.gradle.github.milestones.RepositoryRef;
import java.util.concurrent.TimeUnit;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
public class GitHubMilestoneApiTests {
private GitHubMilestoneApi github;
private RepositoryRef repositoryRef = RepositoryRef.owner("spring-projects").repository("spring-security").build();
private MockWebServer server;
private String baseUrl;
@BeforeEach
public void setup() throws Exception {
this.server = new MockWebServer();
this.server.start();
this.github = new GitHubMilestoneApi("mock-oauth-token");
this.baseUrl = this.server.url("/api").toString();
this.github.setBaseUrl(this.baseUrl);
}
@AfterEach
public void cleanup() throws Exception {
this.server.shutdown();
}
@Test
public void findMilestoneNumberByTitleWhenFoundThenSuccess() throws Exception {
String responseJson = "[\n" +
" {\n" +
" \"url\":\"https://api.github.com/repos/spring-projects/spring-security/milestones/207\",\n" +
" \"html_url\":\"https://github.com/spring-projects/spring-security/milestone/207\",\n" +
" \"labels_url\":\"https://api.github.com/repos/spring-projects/spring-security/milestones/207/labels\",\n" +
" \"id\":6611880,\n" +
" \"node_id\":\"MDk6TWlsZXN0b25lNjYxMTg4MA==\",\n" +
" \"number\":207,\n" +
" \"title\":\"5.6.x\",\n" +
" \"description\":\"\",\n" +
" \"creator\":{\n" +
" \"login\":\"jgrandja\",\n" +
" \"id\":10884212,\n" +
" \"node_id\":\"MDQ6VXNlcjEwODg0MjEy\",\n" +
" \"avatar_url\":\"https://avatars.githubusercontent.com/u/10884212?v=4\",\n" +
" \"gravatar_id\":\"\",\n" +
" \"url\":\"https://api.github.com/users/jgrandja\",\n" +
" \"html_url\":\"https://github.com/jgrandja\",\n" +
" \"followers_url\":\"https://api.github.com/users/jgrandja/followers\",\n" +
" \"following_url\":\"https://api.github.com/users/jgrandja/following{/other_user}\",\n" +
" \"gists_url\":\"https://api.github.com/users/jgrandja/gists{/gist_id}\",\n" +
" \"starred_url\":\"https://api.github.com/users/jgrandja/starred{/owner}{/repo}\",\n" +
" \"subscriptions_url\":\"https://api.github.com/users/jgrandja/subscriptions\",\n" +
" \"organizations_url\":\"https://api.github.com/users/jgrandja/orgs\",\n" +
" \"repos_url\":\"https://api.github.com/users/jgrandja/repos\",\n" +
" \"events_url\":\"https://api.github.com/users/jgrandja/events{/privacy}\",\n" +
" \"received_events_url\":\"https://api.github.com/users/jgrandja/received_events\",\n" +
" \"type\":\"User\",\n" +
" \"site_admin\":false\n" +
" },\n" +
" \"open_issues\":1,\n" +
" \"closed_issues\":0,\n" +
" \"state\":\"open\",\n" +
" \"created_at\":\"2021-03-31T11:29:17Z\",\n" +
" \"updated_at\":\"2021-03-31T11:30:47Z\",\n" +
" \"due_on\":null,\n" +
" \"closed_at\":null\n" +
" },\n" +
" {\n" +
" \"url\":\"https://api.github.com/repos/spring-projects/spring-security/milestones/191\",\n" +
" \"html_url\":\"https://github.com/spring-projects/spring-security/milestone/191\",\n" +
" \"labels_url\":\"https://api.github.com/repos/spring-projects/spring-security/milestones/191/labels\",\n" +
" \"id\":5884208,\n" +
" \"node_id\":\"MDk6TWlsZXN0b25lNTg4NDIwOA==\",\n" +
" \"number\":191,\n" +
" \"title\":\"5.5.0-RC1\",\n" +
" \"description\":\"\",\n" +
" \"creator\":{\n" +
" \"login\":\"jzheaux\",\n" +
" \"id\":3627351,\n" +
" \"node_id\":\"MDQ6VXNlcjM2MjczNTE=\",\n" +
" \"avatar_url\":\"https://avatars.githubusercontent.com/u/3627351?v=4\",\n" +
" \"gravatar_id\":\"\",\n" +
" \"url\":\"https://api.github.com/users/jzheaux\",\n" +
" \"html_url\":\"https://github.com/jzheaux\",\n" +
" \"followers_url\":\"https://api.github.com/users/jzheaux/followers\",\n" +
" \"following_url\":\"https://api.github.com/users/jzheaux/following{/other_user}\",\n" +
" \"gists_url\":\"https://api.github.com/users/jzheaux/gists{/gist_id}\",\n" +
" \"starred_url\":\"https://api.github.com/users/jzheaux/starred{/owner}{/repo}\",\n" +
" \"subscriptions_url\":\"https://api.github.com/users/jzheaux/subscriptions\",\n" +
" \"organizations_url\":\"https://api.github.com/users/jzheaux/orgs\",\n" +
" \"repos_url\":\"https://api.github.com/users/jzheaux/repos\",\n" +
" \"events_url\":\"https://api.github.com/users/jzheaux/events{/privacy}\",\n" +
" \"received_events_url\":\"https://api.github.com/users/jzheaux/received_events\",\n" +
" \"type\":\"User\",\n" +
" \"site_admin\":false\n" +
" },\n" +
" \"open_issues\":21,\n" +
" \"closed_issues\":23,\n" +
" \"state\":\"open\",\n" +
" \"created_at\":\"2020-09-16T13:28:03Z\",\n" +
" \"updated_at\":\"2021-04-06T23:47:10Z\",\n" +
" \"due_on\":\"2021-04-12T07:00:00Z\",\n" +
" \"closed_at\":null\n" +
" }\n" +
"]";
this.server.enqueue(new MockResponse().setBody(responseJson));
long milestoneNumberByTitle = this.github.findMilestoneNumberByTitle(this.repositoryRef, "5.5.0-RC1");
RecordedRequest recordedRequest = this.server.takeRequest(1, TimeUnit.SECONDS);
assertThat(recordedRequest.getMethod()).isEqualToIgnoringCase("get");
assertThat(recordedRequest.getRequestUrl().toString()).isEqualTo(this.baseUrl + "/repos/spring-projects/spring-security/milestones?per_page=100");
assertThat(milestoneNumberByTitle).isEqualTo(191);
}
@Test
public void findMilestoneNumberByTitleWhenNotFoundThenException() throws Exception {
String responseJson = "[\n" +
" {\n" +
" \"url\":\"https://api.github.com/repos/spring-projects/spring-security/milestones/207\",\n" +
" \"html_url\":\"https://github.com/spring-projects/spring-security/milestone/207\",\n" +
" \"labels_url\":\"https://api.github.com/repos/spring-projects/spring-security/milestones/207/labels\",\n" +
" \"id\":6611880,\n" +
" \"node_id\":\"MDk6TWlsZXN0b25lNjYxMTg4MA==\",\n" +
" \"number\":207,\n" +
" \"title\":\"5.6.x\",\n" +
" \"description\":\"\",\n" +
" \"creator\":{\n" +
" \"login\":\"jgrandja\",\n" +
" \"id\":10884212,\n" +
" \"node_id\":\"MDQ6VXNlcjEwODg0MjEy\",\n" +
" \"avatar_url\":\"https://avatars.githubusercontent.com/u/10884212?v=4\",\n" +
" \"gravatar_id\":\"\",\n" +
" \"url\":\"https://api.github.com/users/jgrandja\",\n" +
" \"html_url\":\"https://github.com/jgrandja\",\n" +
" \"followers_url\":\"https://api.github.com/users/jgrandja/followers\",\n" +
" \"following_url\":\"https://api.github.com/users/jgrandja/following{/other_user}\",\n" +
" \"gists_url\":\"https://api.github.com/users/jgrandja/gists{/gist_id}\",\n" +
" \"starred_url\":\"https://api.github.com/users/jgrandja/starred{/owner}{/repo}\",\n" +
" \"subscriptions_url\":\"https://api.github.com/users/jgrandja/subscriptions\",\n" +
" \"organizations_url\":\"https://api.github.com/users/jgrandja/orgs\",\n" +
" \"repos_url\":\"https://api.github.com/users/jgrandja/repos\",\n" +
" \"events_url\":\"https://api.github.com/users/jgrandja/events{/privacy}\",\n" +
" \"received_events_url\":\"https://api.github.com/users/jgrandja/received_events\",\n" +
" \"type\":\"User\",\n" +
" \"site_admin\":false\n" +
" },\n" +
" \"open_issues\":1,\n" +
" \"closed_issues\":0,\n" +
" \"state\":\"open\",\n" +
" \"created_at\":\"2021-03-31T11:29:17Z\",\n" +
" \"updated_at\":\"2021-03-31T11:30:47Z\",\n" +
" \"due_on\":null,\n" +
" \"closed_at\":null\n" +
" },\n" +
" {\n" +
" \"url\":\"https://api.github.com/repos/spring-projects/spring-security/milestones/191\",\n" +
" \"html_url\":\"https://github.com/spring-projects/spring-security/milestone/191\",\n" +
" \"labels_url\":\"https://api.github.com/repos/spring-projects/spring-security/milestones/191/labels\",\n" +
" \"id\":5884208,\n" +
" \"node_id\":\"MDk6TWlsZXN0b25lNTg4NDIwOA==\",\n" +
" \"number\":191,\n" +
" \"title\":\"5.5.0-RC1\",\n" +
" \"description\":\"\",\n" +
" \"creator\":{\n" +
" \"login\":\"jzheaux\",\n" +
" \"id\":3627351,\n" +
" \"node_id\":\"MDQ6VXNlcjM2MjczNTE=\",\n" +
" \"avatar_url\":\"https://avatars.githubusercontent.com/u/3627351?v=4\",\n" +
" \"gravatar_id\":\"\",\n" +
" \"url\":\"https://api.github.com/users/jzheaux\",\n" +
" \"html_url\":\"https://github.com/jzheaux\",\n" +
" \"followers_url\":\"https://api.github.com/users/jzheaux/followers\",\n" +
" \"following_url\":\"https://api.github.com/users/jzheaux/following{/other_user}\",\n" +
" \"gists_url\":\"https://api.github.com/users/jzheaux/gists{/gist_id}\",\n" +
" \"starred_url\":\"https://api.github.com/users/jzheaux/starred{/owner}{/repo}\",\n" +
" \"subscriptions_url\":\"https://api.github.com/users/jzheaux/subscriptions\",\n" +
" \"organizations_url\":\"https://api.github.com/users/jzheaux/orgs\",\n" +
" \"repos_url\":\"https://api.github.com/users/jzheaux/repos\",\n" +
" \"events_url\":\"https://api.github.com/users/jzheaux/events{/privacy}\",\n" +
" \"received_events_url\":\"https://api.github.com/users/jzheaux/received_events\",\n" +
" \"type\":\"User\",\n" +
" \"site_admin\":false\n" +
" },\n" +
" \"open_issues\":21,\n" +
" \"closed_issues\":23,\n" +
" \"state\":\"open\",\n" +
" \"created_at\":\"2020-09-16T13:28:03Z\",\n" +
" \"updated_at\":\"2021-04-06T23:47:10Z\",\n" +
" \"due_on\":\"2021-04-12T07:00:00Z\",\n" +
" \"closed_at\":null\n" +
" }\n" +
"]";
this.server.enqueue(new MockResponse().setBody(responseJson));
assertThatExceptionOfType(RuntimeException.class)
.isThrownBy(() -> this.github.findMilestoneNumberByTitle(this.repositoryRef, "missing"));
}
@Test
public void isOpenIssuesForMilestoneNumberWhenAllClosedThenFalse() throws Exception {
String responseJson = "[]";
long milestoneNumber = 202;
this.server.enqueue(new MockResponse().setBody(responseJson));
assertThat(this.github.isOpenIssuesForMilestoneNumber(this.repositoryRef, milestoneNumber)).isFalse();
RecordedRequest recordedRequest = this.server.takeRequest(1, TimeUnit.SECONDS);
assertThat(recordedRequest.getMethod()).isEqualToIgnoringCase("get");
assertThat(recordedRequest.getRequestUrl().toString()).isEqualTo(this.baseUrl + "/repos/spring-projects/spring-security/issues?per_page=1&milestone=" + milestoneNumber);
}
@Test
public void isOpenIssuesForMilestoneNumberWhenOpenIssuesThenTrue() throws Exception {
String responseJson = "[\n" +
" {\n" +
" \"url\":\"https://api.github.com/repos/spring-projects/spring-security/issues/9562\",\n" +
" \"repository_url\":\"https://api.github.com/repos/spring-projects/spring-security\",\n" +
" \"labels_url\":\"https://api.github.com/repos/spring-projects/spring-security/issues/9562/labels{/name}\",\n" +
" \"comments_url\":\"https://api.github.com/repos/spring-projects/spring-security/issues/9562/comments\",\n" +
" \"events_url\":\"https://api.github.com/repos/spring-projects/spring-security/issues/9562/events\",\n" +
" \"html_url\":\"https://github.com/spring-projects/spring-security/pull/9562\",\n" +
" \"id\":851886504,\n" +
" \"node_id\":\"MDExOlB1bGxSZXF1ZXN0NjEwMjMzMDcw\",\n" +
" \"number\":9562,\n" +
" \"title\":\"Add package-list\",\n" +
" \"user\":{\n" +
" \"login\":\"jzheaux\",\n" +
" \"id\":3627351,\n" +
" \"node_id\":\"MDQ6VXNlcjM2MjczNTE=\",\n" +
" \"avatar_url\":\"https://avatars.githubusercontent.com/u/3627351?v=4\",\n" +
" \"gravatar_id\":\"\",\n" +
" \"url\":\"https://api.github.com/users/jzheaux\",\n" +
" \"html_url\":\"https://github.com/jzheaux\",\n" +
" \"followers_url\":\"https://api.github.com/users/jzheaux/followers\",\n" +
" \"following_url\":\"https://api.github.com/users/jzheaux/following{/other_user}\",\n" +
" \"gists_url\":\"https://api.github.com/users/jzheaux/gists{/gist_id}\",\n" +
" \"starred_url\":\"https://api.github.com/users/jzheaux/starred{/owner}{/repo}\",\n" +
" \"subscriptions_url\":\"https://api.github.com/users/jzheaux/subscriptions\",\n" +
" \"organizations_url\":\"https://api.github.com/users/jzheaux/orgs\",\n" +
" \"repos_url\":\"https://api.github.com/users/jzheaux/repos\",\n" +
" \"events_url\":\"https://api.github.com/users/jzheaux/events{/privacy}\",\n" +
" \"received_events_url\":\"https://api.github.com/users/jzheaux/received_events\",\n" +
" \"type\":\"User\",\n" +
" \"site_admin\":false\n" +
" },\n" +
" \"labels\":[\n" +
" {\n" +
" \"id\":322225043,\n" +
" \"node_id\":\"MDU6TGFiZWwzMjIyMjUwNDM=\",\n" +
" \"url\":\"https://api.github.com/repos/spring-projects/spring-security/labels/in:%20build\",\n" +
" \"name\":\"in: build\",\n" +
" \"color\":\"e8f9de\",\n" +
" \"default\":false,\n" +
" \"description\":\"An issue in the build\"\n" +
" },\n" +
" {\n" +
" \"id\":322225079,\n" +
" \"node_id\":\"MDU6TGFiZWwzMjIyMjUwNzk=\",\n" +
" \"url\":\"https://api.github.com/repos/spring-projects/spring-security/labels/type:%20bug\",\n" +
" \"name\":\"type: bug\",\n" +
" \"color\":\"e3d9fc\",\n" +
" \"default\":false,\n" +
" \"description\":\"A general bug\"\n" +
" }\n" +
" ],\n" +
" \"state\":\"open\",\n" +
" \"locked\":false,\n" +
" \"assignee\":{\n" +
" \"login\":\"rwinch\",\n" +
" \"id\":362503,\n" +
" \"node_id\":\"MDQ6VXNlcjM2MjUwMw==\",\n" +
" \"avatar_url\":\"https://avatars.githubusercontent.com/u/362503?v=4\",\n" +
" \"gravatar_id\":\"\",\n" +
" \"url\":\"https://api.github.com/users/rwinch\",\n" +
" \"html_url\":\"https://github.com/rwinch\",\n" +
" \"followers_url\":\"https://api.github.com/users/rwinch/followers\",\n" +
" \"following_url\":\"https://api.github.com/users/rwinch/following{/other_user}\",\n" +
" \"gists_url\":\"https://api.github.com/users/rwinch/gists{/gist_id}\",\n" +
" \"starred_url\":\"https://api.github.com/users/rwinch/starred{/owner}{/repo}\",\n" +
" \"subscriptions_url\":\"https://api.github.com/users/rwinch/subscriptions\",\n" +
" \"organizations_url\":\"https://api.github.com/users/rwinch/orgs\",\n" +
" \"repos_url\":\"https://api.github.com/users/rwinch/repos\",\n" +
" \"events_url\":\"https://api.github.com/users/rwinch/events{/privacy}\",\n" +
" \"received_events_url\":\"https://api.github.com/users/rwinch/received_events\",\n" +
" \"type\":\"User\",\n" +
" \"site_admin\":false\n" +
" },\n" +
" \"assignees\":[\n" +
" {\n" +
" \"login\":\"rwinch\",\n" +
" \"id\":362503,\n" +
" \"node_id\":\"MDQ6VXNlcjM2MjUwMw==\",\n" +
" \"avatar_url\":\"https://avatars.githubusercontent.com/u/362503?v=4\",\n" +
" \"gravatar_id\":\"\",\n" +
" \"url\":\"https://api.github.com/users/rwinch\",\n" +
" \"html_url\":\"https://github.com/rwinch\",\n" +
" \"followers_url\":\"https://api.github.com/users/rwinch/followers\",\n" +
" \"following_url\":\"https://api.github.com/users/rwinch/following{/other_user}\",\n" +
" \"gists_url\":\"https://api.github.com/users/rwinch/gists{/gist_id}\",\n" +
" \"starred_url\":\"https://api.github.com/users/rwinch/starred{/owner}{/repo}\",\n" +
" \"subscriptions_url\":\"https://api.github.com/users/rwinch/subscriptions\",\n" +
" \"organizations_url\":\"https://api.github.com/users/rwinch/orgs\",\n" +
" \"repos_url\":\"https://api.github.com/users/rwinch/repos\",\n" +
" \"events_url\":\"https://api.github.com/users/rwinch/events{/privacy}\",\n" +
" \"received_events_url\":\"https://api.github.com/users/rwinch/received_events\",\n" +
" \"type\":\"User\",\n" +
" \"site_admin\":false\n" +
" }\n" +
" ],\n" +
" \"milestone\":{\n" +
" \"url\":\"https://api.github.com/repos/spring-projects/spring-security/milestones/191\",\n" +
" \"html_url\":\"https://github.com/spring-projects/spring-security/milestone/191\",\n" +
" \"labels_url\":\"https://api.github.com/repos/spring-projects/spring-security/milestones/191/labels\",\n" +
" \"id\":5884208,\n" +
" \"node_id\":\"MDk6TWlsZXN0b25lNTg4NDIwOA==\",\n" +
" \"number\":191,\n" +
" \"title\":\"5.5.0-RC1\",\n" +
" \"description\":\"\",\n" +
" \"creator\":{\n" +
" \"login\":\"jzheaux\",\n" +
" \"id\":3627351,\n" +
" \"node_id\":\"MDQ6VXNlcjM2MjczNTE=\",\n" +
" \"avatar_url\":\"https://avatars.githubusercontent.com/u/3627351?v=4\",\n" +
" \"gravatar_id\":\"\",\n" +
" \"url\":\"https://api.github.com/users/jzheaux\",\n" +
" \"html_url\":\"https://github.com/jzheaux\",\n" +
" \"followers_url\":\"https://api.github.com/users/jzheaux/followers\",\n" +
" \"following_url\":\"https://api.github.com/users/jzheaux/following{/other_user}\",\n" +
" \"gists_url\":\"https://api.github.com/users/jzheaux/gists{/gist_id}\",\n" +
" \"starred_url\":\"https://api.github.com/users/jzheaux/starred{/owner}{/repo}\",\n" +
" \"subscriptions_url\":\"https://api.github.com/users/jzheaux/subscriptions\",\n" +
" \"organizations_url\":\"https://api.github.com/users/jzheaux/orgs\",\n" +
" \"repos_url\":\"https://api.github.com/users/jzheaux/repos\",\n" +
" \"events_url\":\"https://api.github.com/users/jzheaux/events{/privacy}\",\n" +
" \"received_events_url\":\"https://api.github.com/users/jzheaux/received_events\",\n" +
" \"type\":\"User\",\n" +
" \"site_admin\":false\n" +
" },\n" +
" \"open_issues\":21,\n" +
" \"closed_issues\":23,\n" +
" \"state\":\"open\",\n" +
" \"created_at\":\"2020-09-16T13:28:03Z\",\n" +
" \"updated_at\":\"2021-04-06T23:47:10Z\",\n" +
" \"due_on\":\"2021-04-12T07:00:00Z\",\n" +
" \"closed_at\":null\n" +
" },\n" +
" \"comments\":0,\n" +
" \"created_at\":\"2021-04-06T23:47:10Z\",\n" +
" \"updated_at\":\"2021-04-07T17:00:00Z\",\n" +
" \"closed_at\":null,\n" +
" \"author_association\":\"MEMBER\",\n" +
" \"active_lock_reason\":null,\n" +
" \"pull_request\":{\n" +
" \"url\":\"https://api.github.com/repos/spring-projects/spring-security/pulls/9562\",\n" +
" \"html_url\":\"https://github.com/spring-projects/spring-security/pull/9562\",\n" +
" \"diff_url\":\"https://github.com/spring-projects/spring-security/pull/9562.diff\",\n" +
" \"patch_url\":\"https://github.com/spring-projects/spring-security/pull/9562.patch\"\n" +
" },\n" +
" \"body\":\"Closes gh-9528\\r\\n\\r\\n<!--\\r\\nFor Security Vulnerabilities, please use https://pivotal.io/security#reporting\\r\\n-->\\r\\n\\r\\n<!--\\r\\nBefore creating new features, we recommend creating an issue to discuss the feature. This ensures that everyone is on the same page before extensive work is done.\\r\\n\\r\\nThanks for contributing to Spring Security. Please provide a brief description of your pull-request and reference any related issue numbers (prefix references with gh-).\\r\\n-->\\r\\n\",\n" +
" \"performed_via_github_app\":null\n" +
" }\n" +
"]";
long milestoneNumber = 191;
this.server.enqueue(new MockResponse().setBody(responseJson));
assertThat(this.github.isOpenIssuesForMilestoneNumber(this.repositoryRef, milestoneNumber)).isTrue();
RecordedRequest recordedRequest = this.server.takeRequest(1, TimeUnit.SECONDS);
assertThat(recordedRequest.getMethod()).isEqualToIgnoringCase("get");
assertThat(recordedRequest.getRequestUrl().toString()).isEqualTo(this.baseUrl + "/repos/spring-projects/spring-security/issues?per_page=1&milestone=" + milestoneNumber);
}
}

View File

@@ -0,0 +1,386 @@
package org.springframework.gradle.github.milestones;
import okhttp3.mockwebserver.MockResponse;
import okhttp3.mockwebserver.MockWebServer;
import okhttp3.mockwebserver.RecordedRequest;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.util.concurrent.TimeUnit;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
public class GitHubMilestoneApiTests {
private GitHubMilestoneApi github;
private RepositoryRef repositoryRef = RepositoryRef.owner("spring-projects").repository("spring-security").build();
private MockWebServer server;
private String baseUrl;
@BeforeEach
public void setup() throws Exception {
this.server = new MockWebServer();
this.server.start();
this.github = new GitHubMilestoneApi("mock-oauth-token");
this.baseUrl = this.server.url("/api").toString();
this.github.setBaseUrl(this.baseUrl);
}
@AfterEach
public void cleanup() throws Exception {
this.server.shutdown();
}
@Test
public void findMilestoneNumberByTitleWhenFoundThenSuccess() throws Exception {
String responseJson = "[\n" +
" {\n" +
" \"url\":\"https://api.github.com/repos/spring-projects/spring-security/milestones/207\",\n" +
" \"html_url\":\"https://github.com/spring-projects/spring-security/milestone/207\",\n" +
" \"labels_url\":\"https://api.github.com/repos/spring-projects/spring-security/milestones/207/labels\",\n" +
" \"id\":6611880,\n" +
" \"node_id\":\"MDk6TWlsZXN0b25lNjYxMTg4MA==\",\n" +
" \"number\":207,\n" +
" \"title\":\"5.6.x\",\n" +
" \"description\":\"\",\n" +
" \"creator\":{\n" +
" \"login\":\"jgrandja\",\n" +
" \"id\":10884212,\n" +
" \"node_id\":\"MDQ6VXNlcjEwODg0MjEy\",\n" +
" \"avatar_url\":\"https://avatars.githubusercontent.com/u/10884212?v=4\",\n" +
" \"gravatar_id\":\"\",\n" +
" \"url\":\"https://api.github.com/users/jgrandja\",\n" +
" \"html_url\":\"https://github.com/jgrandja\",\n" +
" \"followers_url\":\"https://api.github.com/users/jgrandja/followers\",\n" +
" \"following_url\":\"https://api.github.com/users/jgrandja/following{/other_user}\",\n" +
" \"gists_url\":\"https://api.github.com/users/jgrandja/gists{/gist_id}\",\n" +
" \"starred_url\":\"https://api.github.com/users/jgrandja/starred{/owner}{/repo}\",\n" +
" \"subscriptions_url\":\"https://api.github.com/users/jgrandja/subscriptions\",\n" +
" \"organizations_url\":\"https://api.github.com/users/jgrandja/orgs\",\n" +
" \"repos_url\":\"https://api.github.com/users/jgrandja/repos\",\n" +
" \"events_url\":\"https://api.github.com/users/jgrandja/events{/privacy}\",\n" +
" \"received_events_url\":\"https://api.github.com/users/jgrandja/received_events\",\n" +
" \"type\":\"User\",\n" +
" \"site_admin\":false\n" +
" },\n" +
" \"open_issues\":1,\n" +
" \"closed_issues\":0,\n" +
" \"state\":\"open\",\n" +
" \"created_at\":\"2021-03-31T11:29:17Z\",\n" +
" \"updated_at\":\"2021-03-31T11:30:47Z\",\n" +
" \"due_on\":null,\n" +
" \"closed_at\":null\n" +
" },\n" +
" {\n" +
" \"url\":\"https://api.github.com/repos/spring-projects/spring-security/milestones/191\",\n" +
" \"html_url\":\"https://github.com/spring-projects/spring-security/milestone/191\",\n" +
" \"labels_url\":\"https://api.github.com/repos/spring-projects/spring-security/milestones/191/labels\",\n" +
" \"id\":5884208,\n" +
" \"node_id\":\"MDk6TWlsZXN0b25lNTg4NDIwOA==\",\n" +
" \"number\":191,\n" +
" \"title\":\"5.5.0-RC1\",\n" +
" \"description\":\"\",\n" +
" \"creator\":{\n" +
" \"login\":\"jzheaux\",\n" +
" \"id\":3627351,\n" +
" \"node_id\":\"MDQ6VXNlcjM2MjczNTE=\",\n" +
" \"avatar_url\":\"https://avatars.githubusercontent.com/u/3627351?v=4\",\n" +
" \"gravatar_id\":\"\",\n" +
" \"url\":\"https://api.github.com/users/jzheaux\",\n" +
" \"html_url\":\"https://github.com/jzheaux\",\n" +
" \"followers_url\":\"https://api.github.com/users/jzheaux/followers\",\n" +
" \"following_url\":\"https://api.github.com/users/jzheaux/following{/other_user}\",\n" +
" \"gists_url\":\"https://api.github.com/users/jzheaux/gists{/gist_id}\",\n" +
" \"starred_url\":\"https://api.github.com/users/jzheaux/starred{/owner}{/repo}\",\n" +
" \"subscriptions_url\":\"https://api.github.com/users/jzheaux/subscriptions\",\n" +
" \"organizations_url\":\"https://api.github.com/users/jzheaux/orgs\",\n" +
" \"repos_url\":\"https://api.github.com/users/jzheaux/repos\",\n" +
" \"events_url\":\"https://api.github.com/users/jzheaux/events{/privacy}\",\n" +
" \"received_events_url\":\"https://api.github.com/users/jzheaux/received_events\",\n" +
" \"type\":\"User\",\n" +
" \"site_admin\":false\n" +
" },\n" +
" \"open_issues\":21,\n" +
" \"closed_issues\":23,\n" +
" \"state\":\"open\",\n" +
" \"created_at\":\"2020-09-16T13:28:03Z\",\n" +
" \"updated_at\":\"2021-04-06T23:47:10Z\",\n" +
" \"due_on\":\"2021-04-12T07:00:00Z\",\n" +
" \"closed_at\":null\n" +
" }\n" +
"]";
this.server.enqueue(new MockResponse().setBody(responseJson));
long milestoneNumberByTitle = this.github.findMilestoneNumberByTitle(this.repositoryRef, "5.5.0-RC1");
RecordedRequest recordedRequest = this.server.takeRequest(1, TimeUnit.SECONDS);
assertThat(recordedRequest.getMethod()).isEqualToIgnoringCase("get");
assertThat(recordedRequest.getRequestUrl().toString()).isEqualTo(this.baseUrl + "/repos/spring-projects/spring-security/milestones?per_page=100");
assertThat(milestoneNumberByTitle).isEqualTo(191);
}
@Test
public void findMilestoneNumberByTitleWhenNotFoundThenException() throws Exception {
String responseJson = "[\n" +
" {\n" +
" \"url\":\"https://api.github.com/repos/spring-projects/spring-security/milestones/207\",\n" +
" \"html_url\":\"https://github.com/spring-projects/spring-security/milestone/207\",\n" +
" \"labels_url\":\"https://api.github.com/repos/spring-projects/spring-security/milestones/207/labels\",\n" +
" \"id\":6611880,\n" +
" \"node_id\":\"MDk6TWlsZXN0b25lNjYxMTg4MA==\",\n" +
" \"number\":207,\n" +
" \"title\":\"5.6.x\",\n" +
" \"description\":\"\",\n" +
" \"creator\":{\n" +
" \"login\":\"jgrandja\",\n" +
" \"id\":10884212,\n" +
" \"node_id\":\"MDQ6VXNlcjEwODg0MjEy\",\n" +
" \"avatar_url\":\"https://avatars.githubusercontent.com/u/10884212?v=4\",\n" +
" \"gravatar_id\":\"\",\n" +
" \"url\":\"https://api.github.com/users/jgrandja\",\n" +
" \"html_url\":\"https://github.com/jgrandja\",\n" +
" \"followers_url\":\"https://api.github.com/users/jgrandja/followers\",\n" +
" \"following_url\":\"https://api.github.com/users/jgrandja/following{/other_user}\",\n" +
" \"gists_url\":\"https://api.github.com/users/jgrandja/gists{/gist_id}\",\n" +
" \"starred_url\":\"https://api.github.com/users/jgrandja/starred{/owner}{/repo}\",\n" +
" \"subscriptions_url\":\"https://api.github.com/users/jgrandja/subscriptions\",\n" +
" \"organizations_url\":\"https://api.github.com/users/jgrandja/orgs\",\n" +
" \"repos_url\":\"https://api.github.com/users/jgrandja/repos\",\n" +
" \"events_url\":\"https://api.github.com/users/jgrandja/events{/privacy}\",\n" +
" \"received_events_url\":\"https://api.github.com/users/jgrandja/received_events\",\n" +
" \"type\":\"User\",\n" +
" \"site_admin\":false\n" +
" },\n" +
" \"open_issues\":1,\n" +
" \"closed_issues\":0,\n" +
" \"state\":\"open\",\n" +
" \"created_at\":\"2021-03-31T11:29:17Z\",\n" +
" \"updated_at\":\"2021-03-31T11:30:47Z\",\n" +
" \"due_on\":null,\n" +
" \"closed_at\":null\n" +
" },\n" +
" {\n" +
" \"url\":\"https://api.github.com/repos/spring-projects/spring-security/milestones/191\",\n" +
" \"html_url\":\"https://github.com/spring-projects/spring-security/milestone/191\",\n" +
" \"labels_url\":\"https://api.github.com/repos/spring-projects/spring-security/milestones/191/labels\",\n" +
" \"id\":5884208,\n" +
" \"node_id\":\"MDk6TWlsZXN0b25lNTg4NDIwOA==\",\n" +
" \"number\":191,\n" +
" \"title\":\"5.5.0-RC1\",\n" +
" \"description\":\"\",\n" +
" \"creator\":{\n" +
" \"login\":\"jzheaux\",\n" +
" \"id\":3627351,\n" +
" \"node_id\":\"MDQ6VXNlcjM2MjczNTE=\",\n" +
" \"avatar_url\":\"https://avatars.githubusercontent.com/u/3627351?v=4\",\n" +
" \"gravatar_id\":\"\",\n" +
" \"url\":\"https://api.github.com/users/jzheaux\",\n" +
" \"html_url\":\"https://github.com/jzheaux\",\n" +
" \"followers_url\":\"https://api.github.com/users/jzheaux/followers\",\n" +
" \"following_url\":\"https://api.github.com/users/jzheaux/following{/other_user}\",\n" +
" \"gists_url\":\"https://api.github.com/users/jzheaux/gists{/gist_id}\",\n" +
" \"starred_url\":\"https://api.github.com/users/jzheaux/starred{/owner}{/repo}\",\n" +
" \"subscriptions_url\":\"https://api.github.com/users/jzheaux/subscriptions\",\n" +
" \"organizations_url\":\"https://api.github.com/users/jzheaux/orgs\",\n" +
" \"repos_url\":\"https://api.github.com/users/jzheaux/repos\",\n" +
" \"events_url\":\"https://api.github.com/users/jzheaux/events{/privacy}\",\n" +
" \"received_events_url\":\"https://api.github.com/users/jzheaux/received_events\",\n" +
" \"type\":\"User\",\n" +
" \"site_admin\":false\n" +
" },\n" +
" \"open_issues\":21,\n" +
" \"closed_issues\":23,\n" +
" \"state\":\"open\",\n" +
" \"created_at\":\"2020-09-16T13:28:03Z\",\n" +
" \"updated_at\":\"2021-04-06T23:47:10Z\",\n" +
" \"due_on\":\"2021-04-12T07:00:00Z\",\n" +
" \"closed_at\":null\n" +
" }\n" +
"]";
this.server.enqueue(new MockResponse().setBody(responseJson));
assertThatExceptionOfType(RuntimeException.class)
.isThrownBy(() -> this.github.findMilestoneNumberByTitle(this.repositoryRef, "missing"));
}
@Test
public void isOpenIssuesForMilestoneNumberWhenAllClosedThenFalse() throws Exception {
String responseJson = "[]";
long milestoneNumber = 202;
this.server.enqueue(new MockResponse().setBody(responseJson));
assertThat(this.github.isOpenIssuesForMilestoneNumber(this.repositoryRef, milestoneNumber)).isFalse();
RecordedRequest recordedRequest = this.server.takeRequest(1, TimeUnit.SECONDS);
assertThat(recordedRequest.getMethod()).isEqualToIgnoringCase("get");
assertThat(recordedRequest.getRequestUrl().toString()).isEqualTo(this.baseUrl + "/repos/spring-projects/spring-security/issues?per_page=1&milestone=" + milestoneNumber);
}
@Test
public void isOpenIssuesForMilestoneNumberWhenOpenIssuesThenTrue() throws Exception {
String responseJson = "[\n" +
" {\n" +
" \"url\":\"https://api.github.com/repos/spring-projects/spring-security/issues/9562\",\n" +
" \"repository_url\":\"https://api.github.com/repos/spring-projects/spring-security\",\n" +
" \"labels_url\":\"https://api.github.com/repos/spring-projects/spring-security/issues/9562/labels{/name}\",\n" +
" \"comments_url\":\"https://api.github.com/repos/spring-projects/spring-security/issues/9562/comments\",\n" +
" \"events_url\":\"https://api.github.com/repos/spring-projects/spring-security/issues/9562/events\",\n" +
" \"html_url\":\"https://github.com/spring-projects/spring-security/pull/9562\",\n" +
" \"id\":851886504,\n" +
" \"node_id\":\"MDExOlB1bGxSZXF1ZXN0NjEwMjMzMDcw\",\n" +
" \"number\":9562,\n" +
" \"title\":\"Add package-list\",\n" +
" \"user\":{\n" +
" \"login\":\"jzheaux\",\n" +
" \"id\":3627351,\n" +
" \"node_id\":\"MDQ6VXNlcjM2MjczNTE=\",\n" +
" \"avatar_url\":\"https://avatars.githubusercontent.com/u/3627351?v=4\",\n" +
" \"gravatar_id\":\"\",\n" +
" \"url\":\"https://api.github.com/users/jzheaux\",\n" +
" \"html_url\":\"https://github.com/jzheaux\",\n" +
" \"followers_url\":\"https://api.github.com/users/jzheaux/followers\",\n" +
" \"following_url\":\"https://api.github.com/users/jzheaux/following{/other_user}\",\n" +
" \"gists_url\":\"https://api.github.com/users/jzheaux/gists{/gist_id}\",\n" +
" \"starred_url\":\"https://api.github.com/users/jzheaux/starred{/owner}{/repo}\",\n" +
" \"subscriptions_url\":\"https://api.github.com/users/jzheaux/subscriptions\",\n" +
" \"organizations_url\":\"https://api.github.com/users/jzheaux/orgs\",\n" +
" \"repos_url\":\"https://api.github.com/users/jzheaux/repos\",\n" +
" \"events_url\":\"https://api.github.com/users/jzheaux/events{/privacy}\",\n" +
" \"received_events_url\":\"https://api.github.com/users/jzheaux/received_events\",\n" +
" \"type\":\"User\",\n" +
" \"site_admin\":false\n" +
" },\n" +
" \"labels\":[\n" +
" {\n" +
" \"id\":322225043,\n" +
" \"node_id\":\"MDU6TGFiZWwzMjIyMjUwNDM=\",\n" +
" \"url\":\"https://api.github.com/repos/spring-projects/spring-security/labels/in:%20build\",\n" +
" \"name\":\"in: build\",\n" +
" \"color\":\"e8f9de\",\n" +
" \"default\":false,\n" +
" \"description\":\"An issue in the build\"\n" +
" },\n" +
" {\n" +
" \"id\":322225079,\n" +
" \"node_id\":\"MDU6TGFiZWwzMjIyMjUwNzk=\",\n" +
" \"url\":\"https://api.github.com/repos/spring-projects/spring-security/labels/type:%20bug\",\n" +
" \"name\":\"type: bug\",\n" +
" \"color\":\"e3d9fc\",\n" +
" \"default\":false,\n" +
" \"description\":\"A general bug\"\n" +
" }\n" +
" ],\n" +
" \"state\":\"open\",\n" +
" \"locked\":false,\n" +
" \"assignee\":{\n" +
" \"login\":\"rwinch\",\n" +
" \"id\":362503,\n" +
" \"node_id\":\"MDQ6VXNlcjM2MjUwMw==\",\n" +
" \"avatar_url\":\"https://avatars.githubusercontent.com/u/362503?v=4\",\n" +
" \"gravatar_id\":\"\",\n" +
" \"url\":\"https://api.github.com/users/rwinch\",\n" +
" \"html_url\":\"https://github.com/rwinch\",\n" +
" \"followers_url\":\"https://api.github.com/users/rwinch/followers\",\n" +
" \"following_url\":\"https://api.github.com/users/rwinch/following{/other_user}\",\n" +
" \"gists_url\":\"https://api.github.com/users/rwinch/gists{/gist_id}\",\n" +
" \"starred_url\":\"https://api.github.com/users/rwinch/starred{/owner}{/repo}\",\n" +
" \"subscriptions_url\":\"https://api.github.com/users/rwinch/subscriptions\",\n" +
" \"organizations_url\":\"https://api.github.com/users/rwinch/orgs\",\n" +
" \"repos_url\":\"https://api.github.com/users/rwinch/repos\",\n" +
" \"events_url\":\"https://api.github.com/users/rwinch/events{/privacy}\",\n" +
" \"received_events_url\":\"https://api.github.com/users/rwinch/received_events\",\n" +
" \"type\":\"User\",\n" +
" \"site_admin\":false\n" +
" },\n" +
" \"assignees\":[\n" +
" {\n" +
" \"login\":\"rwinch\",\n" +
" \"id\":362503,\n" +
" \"node_id\":\"MDQ6VXNlcjM2MjUwMw==\",\n" +
" \"avatar_url\":\"https://avatars.githubusercontent.com/u/362503?v=4\",\n" +
" \"gravatar_id\":\"\",\n" +
" \"url\":\"https://api.github.com/users/rwinch\",\n" +
" \"html_url\":\"https://github.com/rwinch\",\n" +
" \"followers_url\":\"https://api.github.com/users/rwinch/followers\",\n" +
" \"following_url\":\"https://api.github.com/users/rwinch/following{/other_user}\",\n" +
" \"gists_url\":\"https://api.github.com/users/rwinch/gists{/gist_id}\",\n" +
" \"starred_url\":\"https://api.github.com/users/rwinch/starred{/owner}{/repo}\",\n" +
" \"subscriptions_url\":\"https://api.github.com/users/rwinch/subscriptions\",\n" +
" \"organizations_url\":\"https://api.github.com/users/rwinch/orgs\",\n" +
" \"repos_url\":\"https://api.github.com/users/rwinch/repos\",\n" +
" \"events_url\":\"https://api.github.com/users/rwinch/events{/privacy}\",\n" +
" \"received_events_url\":\"https://api.github.com/users/rwinch/received_events\",\n" +
" \"type\":\"User\",\n" +
" \"site_admin\":false\n" +
" }\n" +
" ],\n" +
" \"milestone\":{\n" +
" \"url\":\"https://api.github.com/repos/spring-projects/spring-security/milestones/191\",\n" +
" \"html_url\":\"https://github.com/spring-projects/spring-security/milestone/191\",\n" +
" \"labels_url\":\"https://api.github.com/repos/spring-projects/spring-security/milestones/191/labels\",\n" +
" \"id\":5884208,\n" +
" \"node_id\":\"MDk6TWlsZXN0b25lNTg4NDIwOA==\",\n" +
" \"number\":191,\n" +
" \"title\":\"5.5.0-RC1\",\n" +
" \"description\":\"\",\n" +
" \"creator\":{\n" +
" \"login\":\"jzheaux\",\n" +
" \"id\":3627351,\n" +
" \"node_id\":\"MDQ6VXNlcjM2MjczNTE=\",\n" +
" \"avatar_url\":\"https://avatars.githubusercontent.com/u/3627351?v=4\",\n" +
" \"gravatar_id\":\"\",\n" +
" \"url\":\"https://api.github.com/users/jzheaux\",\n" +
" \"html_url\":\"https://github.com/jzheaux\",\n" +
" \"followers_url\":\"https://api.github.com/users/jzheaux/followers\",\n" +
" \"following_url\":\"https://api.github.com/users/jzheaux/following{/other_user}\",\n" +
" \"gists_url\":\"https://api.github.com/users/jzheaux/gists{/gist_id}\",\n" +
" \"starred_url\":\"https://api.github.com/users/jzheaux/starred{/owner}{/repo}\",\n" +
" \"subscriptions_url\":\"https://api.github.com/users/jzheaux/subscriptions\",\n" +
" \"organizations_url\":\"https://api.github.com/users/jzheaux/orgs\",\n" +
" \"repos_url\":\"https://api.github.com/users/jzheaux/repos\",\n" +
" \"events_url\":\"https://api.github.com/users/jzheaux/events{/privacy}\",\n" +
" \"received_events_url\":\"https://api.github.com/users/jzheaux/received_events\",\n" +
" \"type\":\"User\",\n" +
" \"site_admin\":false\n" +
" },\n" +
" \"open_issues\":21,\n" +
" \"closed_issues\":23,\n" +
" \"state\":\"open\",\n" +
" \"created_at\":\"2020-09-16T13:28:03Z\",\n" +
" \"updated_at\":\"2021-04-06T23:47:10Z\",\n" +
" \"due_on\":\"2021-04-12T07:00:00Z\",\n" +
" \"closed_at\":null\n" +
" },\n" +
" \"comments\":0,\n" +
" \"created_at\":\"2021-04-06T23:47:10Z\",\n" +
" \"updated_at\":\"2021-04-07T17:00:00Z\",\n" +
" \"closed_at\":null,\n" +
" \"author_association\":\"MEMBER\",\n" +
" \"active_lock_reason\":null,\n" +
" \"pull_request\":{\n" +
" \"url\":\"https://api.github.com/repos/spring-projects/spring-security/pulls/9562\",\n" +
" \"html_url\":\"https://github.com/spring-projects/spring-security/pull/9562\",\n" +
" \"diff_url\":\"https://github.com/spring-projects/spring-security/pull/9562.diff\",\n" +
" \"patch_url\":\"https://github.com/spring-projects/spring-security/pull/9562.patch\"\n" +
" },\n" +
" \"body\":\"Closes gh-9528\\r\\n\\r\\n<!--\\r\\nFor Security Vulnerabilities, please use https://pivotal.io/security#reporting\\r\\n-->\\r\\n\\r\\n<!--\\r\\nBefore creating new features, we recommend creating an issue to discuss the feature. This ensures that everyone is on the same page before extensive work is done.\\r\\n\\r\\nThanks for contributing to Spring Security. Please provide a brief description of your pull-request and reference any related issue numbers (prefix references with gh-).\\r\\n-->\\r\\n\",\n" +
" \"performed_via_github_app\":null\n" +
" }\n" +
"]";
long milestoneNumber = 191;
this.server.enqueue(new MockResponse().setBody(responseJson));
assertThat(this.github.isOpenIssuesForMilestoneNumber(this.repositoryRef, milestoneNumber)).isTrue();
RecordedRequest recordedRequest = this.server.takeRequest(1, TimeUnit.SECONDS);
assertThat(recordedRequest.getMethod()).isEqualToIgnoringCase("get");
assertThat(recordedRequest.getRequestUrl().toString()).isEqualTo(this.baseUrl + "/repos/spring-projects/spring-security/issues?per_page=1&milestone=" + milestoneNumber);
}
}

View File

@@ -0,0 +1,18 @@
plugins {
id 'io.spring.convention.integration-test'
}
apply plugin: 'java'
apply plugin: 'groovy'
repositories {
mavenCentral()
}
dependencies {
testImplementation platform('org.junit:junit-bom:5.8.1')
testImplementation 'org.junit.jupiter:junit-jupiter-api'
testImplementation 'org.junit.jupiter:junit-jupiter-engine'
testImplementation 'org.spockframework:spock-core:1.0-groovy-2.4'
integrationTestCompile 'org.springframework:spring-core:4.3.7.RELEASE'
}

Some files were not shown because too many files have changed in this diff Show More