From 658ccf3b0577283d23a7322c133118264745a470 Mon Sep 17 00:00:00 2001 From: "James J. Ye" Date: Tue, 9 Oct 2018 01:40:25 +0800 Subject: [PATCH 1/9] add profile properties and turn on actuator --- pom.xml | 27 +++++++++++++++++++ .../config/ApplicationProperties.java | 22 +++++++++++++++ .../config/SecurityConfiguration.java | 2 ++ src/main/resources/application-e2e.properties | 6 +++++ .../application-production.properties | 6 +++++ .../resources/application-staging.properties | 6 +++++ src/main/resources/application.properties | 12 +++++++++ 7 files changed, 81 insertions(+) create mode 100644 src/main/resources/application-e2e.properties create mode 100644 src/main/resources/application-production.properties create mode 100644 src/main/resources/application-staging.properties diff --git a/pom.xml b/pom.xml index 8a3dcfcf..d923a68f 100644 --- a/pom.xml +++ b/pom.xml @@ -27,6 +27,7 @@ 1.4.0 3.7.0 1.11.409 + 1.2 @@ -69,6 +70,15 @@ org.springframework.boot spring-boot-starter-amqp + + org.springframework.boot + spring-boot-starter-actuator + + + javax.interceptor + javax.interceptor-api + ${javax.interceptor.version} + mysql mysql-connector-java @@ -145,15 +155,32 @@ + + pl.project13.maven + git-commit-id-plugin + org.springframework.boot spring-boot-maven-plugin + + true + + + + build-info + + pre integration test start + + + e2e + + post integration test diff --git a/src/main/java/com/taskagile/config/ApplicationProperties.java b/src/main/java/com/taskagile/config/ApplicationProperties.java index ce4a1e5a..0ede15b4 100644 --- a/src/main/java/com/taskagile/config/ApplicationProperties.java +++ b/src/main/java/com/taskagile/config/ApplicationProperties.java @@ -35,6 +35,8 @@ public class ApplicationProperties { @NotNull private ImageSetting image; + private CdnSetting cdn; + public void setMailFrom(String mailFrom) { this.mailFrom = mailFrom; } @@ -75,6 +77,14 @@ public void setImage(ImageSetting image) { this.image = image; } + public CdnSetting getCdn() { + return cdn; + } + + public void setCdn(CdnSetting cdn) { + this.cdn = cdn; + } + //--------------------------------------- // Setting structure classes //--------------------------------------- @@ -166,4 +176,16 @@ public void setCommandSearchPath(String commandSearchPath) { this.commandSearchPath = commandSearchPath; } } + + private static class CdnSetting { + private String url = "http://taskagile.local"; + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + } } diff --git a/src/main/java/com/taskagile/config/SecurityConfiguration.java b/src/main/java/com/taskagile/config/SecurityConfiguration.java index 5783dd9d..40f0c141 100644 --- a/src/main/java/com/taskagile/config/SecurityConfiguration.java +++ b/src/main/java/com/taskagile/config/SecurityConfiguration.java @@ -6,6 +6,7 @@ import com.taskagile.web.apis.authenticate.SimpleAuthenticationFailureHandler; import com.taskagile.web.apis.authenticate.SimpleAuthenticationSuccessHandler; import com.taskagile.web.apis.authenticate.SimpleLogoutSuccessHandler; +import org.springframework.boot.actuate.autoconfigure.security.servlet.EndpointRequest; import org.springframework.context.annotation.Bean; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.WebSecurity; @@ -33,6 +34,7 @@ protected void configure(HttpSecurity http) throws Exception { .and() .authorizeRequests() .antMatchers(PUBLIC).permitAll() + .requestMatchers(EndpointRequest.toAnyEndpoint()).permitAll() .anyRequest().authenticated() .and() .addFilterAt(authenticationFilter(), UsernamePasswordAuthenticationFilter.class) diff --git a/src/main/resources/application-e2e.properties b/src/main/resources/application-e2e.properties new file mode 100644 index 00000000..c5522799 --- /dev/null +++ b/src/main/resources/application-e2e.properties @@ -0,0 +1,6 @@ +spring.datasource.url=jdbc:mysql://localhost:3306/task_agile_e2e?useSSL=false +spring.datasource.username=root +spring.datasource.password=1234 + +spring.jpa.hibernate.ddl-auto=create-drop + diff --git a/src/main/resources/application-production.properties b/src/main/resources/application-production.properties new file mode 100644 index 00000000..c3b54740 --- /dev/null +++ b/src/main/resources/application-production.properties @@ -0,0 +1,6 @@ +spring.datasource.url=jdbc:mysql://localhost:3306/task_agile?useSSL=false + +spring.mail.host=localhost +spring.mail.port=25 + +logging.level.com.taskagile=INFO diff --git a/src/main/resources/application-staging.properties b/src/main/resources/application-staging.properties new file mode 100644 index 00000000..c00fc2d0 --- /dev/null +++ b/src/main/resources/application-staging.properties @@ -0,0 +1,6 @@ +spring.datasource.url=jdbc:mysql://localhost:3306/task_agile?useSSL=false + +spring.mail.host=localhost +spring.mail.port=25 + +logging.level.com.taskagile=DEBUG diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index ffe192ef..2b25d01c 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -39,3 +39,15 @@ spring.mail.properties.mail.smtp.auth=false logging.level.com.taskagile=DEBUG logging.level.org.springframework.security=DEBUG + +# Actuator setting +management.server.port=9000 +management.endpoint.health.show-details=always +management.endpoints.web.exposure.include=health, info, metrics, env + +info.app.name=@name@ +info.app.description=@description@ +info.app.encoding=@project.build.sourceEncoding@ +info.app.java.source=@java.version@ +info.app.java.target=@java.version@ + From 97b9c1cde891c752fff9b96dd3c127678584de3f Mon Sep 17 00:00:00 2001 From: "James J. Ye" Date: Tue, 9 Oct 2018 01:42:38 +0800 Subject: [PATCH 2/9] fix: increase password field length --- src/main/java/com/taskagile/domain/model/user/User.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/taskagile/domain/model/user/User.java b/src/main/java/com/taskagile/domain/model/user/User.java index 2cb75f7b..b36d12f2 100644 --- a/src/main/java/com/taskagile/domain/model/user/User.java +++ b/src/main/java/com/taskagile/domain/model/user/User.java @@ -22,7 +22,7 @@ public class User extends AbstractBaseEntity { @Column(name = "email_address", nullable = false, length = 100, unique = true) private String emailAddress; - @Column(name = "password", nullable = false, length = 30) + @Column(name = "password", nullable = false, length = 128) private String password; @Column(name = "first_name", nullable = false, length = 45) From 6df4175562bef5b0eb9e2edbe9ff00101637e6a9 Mon Sep 17 00:00:00 2001 From: "James J. Ye" Date: Thu, 11 Oct 2018 13:36:02 +0800 Subject: [PATCH 3/9] add integration test of registration api --- .../RegistrationApiIntegrationTests.java | 90 +++++++++++++++++++ src/test/resources/application.properties | 2 + src/test/resources/mail-templates/welcome.ftl | 6 ++ 3 files changed, 98 insertions(+) create mode 100644 src/test/java/integration/RegistrationApiIntegrationTests.java create mode 100644 src/test/resources/mail-templates/welcome.ftl diff --git a/src/test/java/integration/RegistrationApiIntegrationTests.java b/src/test/java/integration/RegistrationApiIntegrationTests.java new file mode 100644 index 00000000..2c307e4a --- /dev/null +++ b/src/test/java/integration/RegistrationApiIntegrationTests.java @@ -0,0 +1,90 @@ +package integration; + +import com.taskagile.TaskAgileApplication; +import com.taskagile.utils.JsonUtils; +import com.taskagile.web.payload.RegistrationPayload; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@RunWith(SpringRunner.class) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK, classes = TaskAgileApplication.class) +@ActiveProfiles("test") +@AutoConfigureMockMvc +public class RegistrationApiIntegrationTests { + + @Autowired + private MockMvc mvcMock; + + private RegistrationPayload payload(String username, String emailAddress) { + RegistrationPayload payload = new RegistrationPayload(); + payload.setUsername(username); + payload.setEmailAddress(emailAddress); + payload.setPassword("MyPassword!"); + payload.setFirstName("User"); + payload.setLastName("Test"); + return payload; + } + + @Test + public void register_blankPayload_shouldFailAndReturn400() throws Exception { + mvcMock.perform(post("/api/registrations")) + .andExpect(status().is(400)); + } + + @Test + public void register_validPayload_shouldSucceedAndReturn201() throws Exception { + RegistrationPayload payload = payload("sunny", "sunny@taskagile.com"); + mvcMock.perform( + post("/api/registrations") + .contentType(MediaType.APPLICATION_JSON) + .content(JsonUtils.toJson(payload))) + .andExpect(status().is(201)); + } + + @Test + public void register_existedUsername_shouldFailAndReturn400() throws Exception { + RegistrationPayload payload = payload("exist", "test1@taskagile.com"); + mvcMock.perform( + post("/api/registrations") + .contentType(MediaType.APPLICATION_JSON) + .content(JsonUtils.toJson(payload))) + .andExpect(status().is(201)); + // Try to register again with the same username + RegistrationPayload payload2 = payload("exist", "test2@taskagile.com"); + mvcMock.perform( + post("/api/registrations") + .contentType(MediaType.APPLICATION_JSON) + .content(JsonUtils.toJson(payload2))) + .andExpect(status().is(400)) + .andExpect(jsonPath("$.message").value("Username already exists")); + } + + @Test + public void register_existedEmailAddress_shouldFailAndReturn400() throws Exception { + RegistrationPayload payload = payload("test1", "exist@taskagile.com"); + mvcMock.perform( + post("/api/registrations") + .contentType(MediaType.APPLICATION_JSON) + .content(JsonUtils.toJson(payload))) + .andExpect(status().is(201)); + // Try to register with the same email address + RegistrationPayload payload2 = payload("test2", "exist@taskagile.com"); + mvcMock.perform( + post("/api/registrations") + .contentType(MediaType.APPLICATION_JSON) + .content(JsonUtils.toJson(payload2))) + .andExpect(status().is(400)) + .andExpect(jsonPath("$.message").value("Email address already exists")); + } +} diff --git a/src/test/resources/application.properties b/src/test/resources/application.properties index b79a2561..47a3a5a3 100644 --- a/src/test/resources/application.properties +++ b/src/test/resources/application.properties @@ -17,6 +17,8 @@ spring.jpa.open-in-view=false spring.jpa.hibernate.ddl-auto=create-drop spring.jpa.database-platform=org.hibernate.dialect.H2Dialect +spring.freemarker.template-loader-path=classpath:/mail-templates/ + spring.mail.host=localhost spring.mail.port=1025 spring.mail.properties.mail.smtp.auth=false diff --git a/src/test/resources/mail-templates/welcome.ftl b/src/test/resources/mail-templates/welcome.ftl new file mode 100644 index 00000000..186a8581 --- /dev/null +++ b/src/test/resources/mail-templates/welcome.ftl @@ -0,0 +1,6 @@ +

Welcome!

+

Here is your registration information:

+
    +
  • Username: ${user.username}
  • +
  • Email Address: ${user.emailAddress}
  • +
From 388139307e4807189b20e319a1526c5ef42555c1 Mon Sep 17 00:00:00 2001 From: "James J. Ye" Date: Thu, 11 Oct 2018 17:20:02 +0800 Subject: [PATCH 4/9] refactor maven build process --- build.sh | 2 + front-end/package.json | 3 +- pom.xml | 100 +++++++++++++++++++++++++++-------------- 3 files changed, 70 insertions(+), 35 deletions(-) create mode 100644 build.sh diff --git a/build.sh b/build.sh new file mode 100644 index 00000000..fce6c405 --- /dev/null +++ b/build.sh @@ -0,0 +1,2 @@ +# Local build command include local e2e testing +mvn clean install -P local-e2e diff --git a/front-end/package.json b/front-end/package.json index 794b1255..39006b1a 100644 --- a/front-end/package.json +++ b/front-end/package.json @@ -8,7 +8,8 @@ "lint": "vue-cli-service lint", "test:unit": "vue-cli-service test:unit", "test:e2e": "vue-cli-service test:e2e", - "test:integration": "vue-cli-service test:e2e --url http://localhost:8080/", + "test:staging-e2e": "vue-cli-service test:e2e --url https://staging.taskagile.com/", + "test:local-e2e": "vue-cli-service test:e2e --url http://localhost:8080/", "test": "npm run test:unit && npm run test:e2e" }, "dependencies": { diff --git a/pom.xml b/pom.xml index d923a68f..7f4af5d4 100644 --- a/pom.xml +++ b/pom.xml @@ -28,6 +28,7 @@ 3.7.0 1.11.409 1.2 + 1.6.0 @@ -153,6 +154,70 @@
+ + + + local-e2e + + + + + org.springframework.boot + spring-boot-maven-plugin + + + pre local-e2e test + + start + + + + + e2e + + + + + post local-e2e test + + stop + + + + + + + org.codehaus.mojo + exec-maven-plugin + ${codehaus.version} + + + front-end local-e2e test + + exec + + integration-test + + npm + + run + test:local-e2e + + + + + + ${basedir}/front-end + + + + + + + @@ -171,29 +236,12 @@ build-info - - pre integration test - - start - - - - e2e - - - - - post integration test - - stop - - org.codehaus.mojo exec-maven-plugin - 1.6.0 + ${codehaus.version} font-end install @@ -236,20 +284,6 @@ - - front-end e2e test - - exec - - integration-test - - npm - - run - test:integration - - - ${basedir}/front-end @@ -257,7 +291,6 @@ maven-resources-plugin - 3.1.0 copy front-end template @@ -335,7 +368,6 @@ maven-clean-plugin - 3.1.0 From 92ec68f8ce0d5ec79a689a23e7f238c08748cba9 Mon Sep 17 00:00:00 2001 From: "James J. Ye" Date: Fri, 12 Oct 2018 01:24:31 +0800 Subject: [PATCH 5/9] fix: add test profile and turn off debug-level log --- src/main/resources/application.properties | 3 --- .../com/taskagile/web/apis/RegistrationApiControllerTests.java | 2 ++ .../web/apis/authenticate/AuthenticationFilterTests.java | 2 ++ 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 2b25d01c..f2b7095d 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -37,9 +37,6 @@ spring.mail.host=localhost spring.mail.port=1025 spring.mail.properties.mail.smtp.auth=false -logging.level.com.taskagile=DEBUG -logging.level.org.springframework.security=DEBUG - # Actuator setting management.server.port=9000 management.endpoint.health.show-details=always diff --git a/src/test/java/com/taskagile/web/apis/RegistrationApiControllerTests.java b/src/test/java/com/taskagile/web/apis/RegistrationApiControllerTests.java index aea8dbc1..020d8a74 100644 --- a/src/test/java/com/taskagile/web/apis/RegistrationApiControllerTests.java +++ b/src/test/java/com/taskagile/web/apis/RegistrationApiControllerTests.java @@ -12,6 +12,7 @@ import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.http.MediaType; +import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.web.servlet.MockMvc; @@ -25,6 +26,7 @@ @RunWith(SpringRunner.class) @ContextConfiguration(classes = {SecurityConfiguration.class, RegistrationApiController.class}) @WebMvcTest +@ActiveProfiles("test") public class RegistrationApiControllerTests { @Autowired diff --git a/src/test/java/com/taskagile/web/apis/authenticate/AuthenticationFilterTests.java b/src/test/java/com/taskagile/web/apis/authenticate/AuthenticationFilterTests.java index ab8b205f..2561193a 100644 --- a/src/test/java/com/taskagile/web/apis/authenticate/AuthenticationFilterTests.java +++ b/src/test/java/com/taskagile/web/apis/authenticate/AuthenticationFilterTests.java @@ -8,6 +8,7 @@ import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.InsufficientAuthenticationException; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.junit4.SpringRunner; import java.io.IOException; @@ -15,6 +16,7 @@ import static org.mockito.Mockito.verify; @RunWith(SpringRunner.class) +@ActiveProfiles("test") public class AuthenticationFilterTests { @MockBean From a9fbce403531d4b52709596d55c60e772b9ac73a Mon Sep 17 00:00:00 2001 From: "James J. Ye" Date: Mon, 15 Oct 2018 14:22:38 +0800 Subject: [PATCH 6/9] add Dockerfile and Jenkinsfile --- .gitignore | 1 + Jenkinsfile | 58 ++++++++++++++++++++++++++++ docker/Dockerfile | 11 ++++++ docker/application-docker.properties | 11 ++++++ docker/env.list | 16 ++++++++ docker/start.sh | 5 +++ 6 files changed, 102 insertions(+) create mode 100644 Jenkinsfile create mode 100644 docker/Dockerfile create mode 100644 docker/application-docker.properties create mode 100644 docker/env.list create mode 100755 docker/start.sh diff --git a/.gitignore b/.gitignore index a3b584a3..b70941ce 100644 --- a/.gitignore +++ b/.gitignore @@ -32,3 +32,4 @@ src/main/resources/static/favicon.ico src/main/resources/static/js/ src/main/resources/templates/index.html spy.log +docker/*.jar diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 00000000..4162c6f2 --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,58 @@ +pipeline { + agent any + + environment { + DOCKER_REPO = "taskagile/vuejs.spring-boot.mysql" + DOCKER_CREDENTIAL = "dockerhub" + JENKINS_AT_STAGING = "jenkins@staging.taskagile.com" + } + + stages { + stage("Build package") { + steps { + echo "Git commit: ${env.GIT_COMMIT}" + sh "mvn clean package" + } + } + + stage("Build Docker image") { + steps { + sh "cp target/app-0.0.1-SNAPSHOT.jar docker/app.jar" + sh "docker build -t ${DOCKER_REPO}:${env.GIT_COMMIT} docker/" + } + } + + stage("Push Docker build image") { + steps { + withDockerRegistry([ credentialsId: DOCKER_CREDENTIAL, url: '' ]) { + sh "docker push ${DOCKER_REPO}:${env.GIT_COMMIT}" + } + } + } + + stage("Deploy to staging") { + steps { + sh "ssh ${JENKINS_AT_STAGING} rm -fr /app/env.list /app/start.sh" + sh "scp ./docker/env.list ./docker/start.sh ${JENKINS_AT_STAGING}:/app" + sh "ssh ${JENKINS_AT_STAGING} \"cd /app && ./start.sh ${env.GIT_COMMIT}\"" + } + } + + stage("Run E2E tests") { + steps { + sh "cd ${env.WORKSPACE}/front-end && npm run test:staging-e2e" + } + } + } + + post { + always { + emailext ( + subject: "[Jenkins] ${env.JOB_NAME} Build #${env.BUILD_NUMBER} - ${currentBuild.currentResult}", + recipientProviders: [[$class: 'DevelopersRecipientProvider'], [$class: 'RequesterRecipientProvider']], + body: "${currentBuild.currentResult}\n\nJob: ${env.JOB_NAME}\nBuild: #${env.BUILD_NUMBER}\nGit commit: ${env.GIT_COMMIT}\nMore detail at: ${env.BUILD_URL}" + ) + sh "docker rmi -f ${DOCKER_REPO}:${env.GIT_COMMIT}" + } + } +} diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 00000000..34b60887 --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,11 @@ +From openjdk:8-jre-alpine + +RUN apk add graphicsmagick=1.3.30-r0 +RUN ln -s /usr/bin/gm /usr/local/bin/gm + +ADD app.jar /opt/taskagile/app.jar +ADD application-docker.properties /config/application-docker.properties + +EXPOSE 8080 9000 + +ENTRYPOINT [ "java", "-jar", "/opt/taskagile/app.jar" ] diff --git a/docker/application-docker.properties b/docker/application-docker.properties new file mode 100644 index 00000000..661ab66c --- /dev/null +++ b/docker/application-docker.properties @@ -0,0 +1,11 @@ +spring.datasource.url=jdbc:mysql://${TASK_AGILE_DB_HOST}:3306/${TASK_AGILE_DB_NAME}?useSSL=false +spring.datasource.username=${TASK_AGILE_DB_USERNAME} +spring.datasource.password=${TASK_AGILE_DB_PASSWORD} + +spring.rabbitmq.host=${TASK_AGILE_MQ_HOST} +spring.rabbitmq.port=${TASK_AGILE_MQ_PORT} +spring.rabbitmq.username=${TASK_AGILE_MQ_USERNAME} +spring.rabbitmq.password=${TASK_AGILE_MQ_PASSWORD} + +spring.mail.host=${TASK_AGILE_MAIL_HOST} +spring.mail.port=${TASK_AGILE_MAIL_PORT} diff --git a/docker/env.list b/docker/env.list new file mode 100644 index 00000000..d6ba435e --- /dev/null +++ b/docker/env.list @@ -0,0 +1,16 @@ +TASK_AGILE_TOKEN_SECRET_KEY=60dKuW2Qpc3YkUoaa9i6qY5cyaGgQM8clfxpDGWS3sY= + +TASK_AGILE_DB_HOST= +TASK_AGILE_DB_NAME=task_agile +TASK_AGILE_DB_USERNAME= +TASK_AGILE_DB_PASSWORD= + +TASK_AGILE_MQ_HOST= +TASK_AGILE_MQ_PORT=5672 +TASK_AGILE_MQ_USERNAME= +TASK_AGILE_MQ_PASSWORD= + +TASK_AGILE_MAIL_HOST= +TASK_AGILE_MAIL_PORT=25 + +TASK_AGILE_CDN_URL= diff --git a/docker/start.sh b/docker/start.sh new file mode 100755 index 00000000..8323aa19 --- /dev/null +++ b/docker/start.sh @@ -0,0 +1,5 @@ +docker pull taskagile/vuejs.spring-boot.mysql:$1 +docker container stop taskagile +docker run --detach --rm --name taskagile --env-file ./env.list \ + -e "SPRING_PROFILES_ACTIVE=staging,docker" \ + -p 8080:8080 -p 9000:9000 taskagile/vuejs.spring-boot.mysql:$1 From 50b7bbe24c708964f015df74b532c52bb1083847 Mon Sep 17 00:00:00 2001 From: "James J. Ye" Date: Mon, 15 Oct 2018 14:24:38 +0800 Subject: [PATCH 7/9] update README.md --- README.md | 44 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 2c2e5888..d6d51799 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,25 @@ Open source task management tool built with Vue.js 2, Spring Boot 2, and MySQL 5.7+ -## Local development +> This is the repository for the book [_Building applications with Spring 5 and Vue.js 2: A real-world practical guide to building a modern full-stack web application_](https://www.amazon.com/Building-applications-Spring-5-0-Vue-js-ebook/dp/B079X1VTST). -Create `src/main/resources/application-dev.properties` with the following settings to override the settings in `application.properties`. +## Local development setup + +### Prerequisites + +- JDK8 - OpenJDK Preferred +- MySQL 5.7+ +- RabbitMQ 3.6+ +- GraphicMagick 1.3+ + +### Database setup + +- Create database `task_agile` +- Initialize database with scripts in `setup` folder + +### Add dev properties file + +- Create `src/main/resources/application-dev.properties` with the following settings to override the settings in `application.properties`. ```properties spring.datasource.url=jdbc:mysql://localhost:3306/task_agile?useSSL=false @@ -14,8 +30,30 @@ spring.datasource.password= ## Commands -- Use `mvn install` to build both the front-end and the back-end - Use `mvn test` to run the tests of the back-end and the front-end - Use `mvn spring-boot:run` to start the back-end - Use `npm run serve` inside the `front-end` directory to start the front-end +- Use `mvn install` to build both the front-end and the back-end - Use `java -jar target/app-0.0.1-SNAPSHOT.jar` to start the bundled application + +## How to run application inside docker + +```bash +$ mvn clean package +$ cp target/app-0.0.1-SNAPSHOT.jar docker/app.jar +$ docker build -t taskagile:dev docker/ +``` + +### Start with dev profile locally + +```bash +$ docker run --rm --name taskagile -e "SPRING_PROFILES_ACTIVE=dev" -p 8080:8080 -p 9000:9000 taskagile +``` + +### Start on server + +With active profiles `staging` and `docker`. Make sure `docker` is the last one in the list so that the settings in `evn.list` will be applied. + +```bash +$ docker run --rm --name taskagile --env-file ./docker/env.list -e "SPRING_PROFILES_ACTIVE=staging,docker" -p 8080:8080 -p 9000:9000 taskagile +``` From 06d5c499e835e1722eed02fe83edcaacd82db520 Mon Sep 17 00:00:00 2001 From: "James J. Ye" Date: Mon, 15 Oct 2018 21:13:27 +0800 Subject: [PATCH 8/9] use existing env.list instead of copying over Keeping the env.list in the source code as a template. On the server side, keep/app/env.list between builds to avoid broken build in Jennkins --- Jenkinsfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 4162c6f2..c441ecff 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -32,8 +32,8 @@ pipeline { stage("Deploy to staging") { steps { - sh "ssh ${JENKINS_AT_STAGING} rm -fr /app/env.list /app/start.sh" - sh "scp ./docker/env.list ./docker/start.sh ${JENKINS_AT_STAGING}:/app" + sh "ssh ${JENKINS_AT_STAGING} rm -fr /app/start.sh" + sh "scp ./docker/start.sh ${JENKINS_AT_STAGING}:/app" sh "ssh ${JENKINS_AT_STAGING} \"cd /app && ./start.sh ${env.GIT_COMMIT}\"" } } From 057a8fc2139b0ad7c1396ba7c4af8743d54180b5 Mon Sep 17 00:00:00 2001 From: "James J. Ye" Date: Mon, 15 Oct 2018 21:14:27 +0800 Subject: [PATCH 9/9] increase the wait time for local remote e2e testing Once the Jenkins server is also deployed to AWS at https://ci.taskagile.com, the wait time will be decreased --- front-end/tests/e2e/specs/0.register.e2e.js | 2 +- front-end/tests/e2e/specs/1.login.e2e.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/front-end/tests/e2e/specs/0.register.e2e.js b/front-end/tests/e2e/specs/0.register.e2e.js index ec603af7..eda4ea5b 100644 --- a/front-end/tests/e2e/specs/0.register.e2e.js +++ b/front-end/tests/e2e/specs/0.register.e2e.js @@ -29,7 +29,7 @@ module.exports = { registerPage .navigate() - .waitForElementVisible('@app', 500) + .waitForElementVisible('@app', 30000) .assert.visible('@usernameInput') .assert.visible('@emailAddressInput') .assert.visible('@firstNameInput') diff --git a/front-end/tests/e2e/specs/1.login.e2e.js b/front-end/tests/e2e/specs/1.login.e2e.js index f715868d..c020bbf3 100644 --- a/front-end/tests/e2e/specs/1.login.e2e.js +++ b/front-end/tests/e2e/specs/1.login.e2e.js @@ -6,7 +6,7 @@ module.exports = { loginPage .navigate() - .waitForElementVisible('@app', 500) + .waitForElementVisible('@app', 30000) .assert.visible('@usernameInput') .assert.visible('@passwordInput') .assert.visible('@submitButton') @@ -20,7 +20,7 @@ module.exports = { .navigate() .login('not-exist', 'incorrect') - browser.pause(500) + browser.pause(2000) loginPage .assert.visible('@formError')