Skip to content

Commit f37f346

Browse files
committed
Initial Commit
0 parents  commit f37f346

File tree

30 files changed

+1292
-0
lines changed

30 files changed

+1292
-0
lines changed

.github/workflows/ci.yml

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
name: ci
2+
on:
3+
push:
4+
branches:
5+
- main
6+
jobs:
7+
build:
8+
runs-on: ubuntu-latest
9+
steps:
10+
- uses: actions/checkout@v2
11+
- name: Setup java
12+
uses: fluentci-io/setup-fluentci@v5
13+
with:
14+
wasm: true
15+
plugin: java
16+
args: setup zulu-17.46.19
17+
- name: Setup maven
18+
run: |
19+
fluentci run --wasm maven setup
20+
- name: Build
21+
run: |
22+
mvn -q package jmeter:configure -Dmaven.test.skip=true
23+
env:
24+
GITHUB_ACCESS_TOKEN: ${{ secrets.GITHUB_TOKEN }}
25+
JAVA_HOME: /home/runner/.local/share/mise/installs/java/zulu-17.46.19
26+
- name: Test
27+
run: |
28+
mvn -q test-compile -Dmaven.test.skip=true
29+
fluentci run --wasm maven test
30+
fluentci run --wasm maven test -Pintegration-testing
31+
env:
32+
GITHUB_ACCESS_TOKEN: ${{ secrets.GITHUB_TOKEN }}
33+
JAVA_HOME: /home/runner/.local/share/mise/installs/java/zulu-17.46.19
34+
- name: Performance tests
35+
run: |
36+
java -version
37+
java -jar target/spring-pipeline-demo.jar > /dev/null &
38+
sleep 20
39+
mvn -q jmeter:jmeter
40+
mvn jmeter:results
41+
env:
42+
GITHUB_ACCESS_TOKEN: ${{ secrets.GITHUB_TOKEN }}
43+
JAVA_HOME: /home/runner/.local/share/mise/installs/java/zulu-17.46.19

Dockerfile

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
FROM openjdk:17-jdk-alpine
2+
ARG ENVIRONMENT
3+
ENV ENVIRONMENT ${ENVIRONMENT}
4+
COPY target/*.jar app.jar
5+
ENTRYPOINT ["java","-Dspring.profiles.active=${ENVIRONMENT}", "-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]

LICENSE

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
Copyright (c) 2023 Tsiry Sandratraina <[email protected]>
2+
3+
Permission is hereby granted, free of charge, to any person obtaining a copy
4+
of this software and associated documentation files (the "Software"), to deal
5+
in the Software without restriction, including without limitation the rights
6+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7+
copies of the Software, and to permit persons to whom the Software is
8+
furnished to do so, subject to the following conditions:
9+
10+
The above copyright notice and this permission notice shall be included in all
11+
copies or substantial portions of the Software.
12+
13+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19+
SOFTWARE.

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# FluentCI CI/CD demo for Java Spring
2+
3+
[![ci](https://github.com/fluentci-demos/fluentci-demo-java-spring/actions/workflows/ci.yml/badge.svg)](https://github.com/fluentci-demos/fluentci-demo-java-spring/actions/workflows/ci.yml)
4+
5+
This is an example application and CI/CD pipeline showing how to build, test a Java Spring application using FluentCI.

assets/pipeline-result.png

669 KB
Loading

docker-hub-secret.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
apiVersion: v1beta
2+
kind: Secret
3+
metadata:
4+
name: docker-hub
5+
data:
6+
env_vars:
7+
- name: DOCKER_USERNAME
8+
value: "username"
9+
- name: DOCKER_PASSWORD
10+
value: "secret"

pom.xml

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4+
<modelVersion>4.0.0</modelVersion>
5+
<parent>
6+
<groupId>org.springframework.boot</groupId>
7+
<artifactId>spring-boot-starter-parent</artifactId>
8+
<version>2.1.2.RELEASE</version>
9+
<relativePath/> <!-- lookup parent from repository -->
10+
</parent>
11+
<groupId>com.example</groupId>
12+
<artifactId>spring-pipeline-demo</artifactId>
13+
<version>0.0.1-SNAPSHOT</version>
14+
<name>spring-pipeline-demo</name>
15+
<description>Demo project for Spring Boot</description>
16+
<packaging>jar</packaging>
17+
18+
<properties>
19+
<myTestSourceDirectory>${project.basedir}/src/test/java</myTestSourceDirectory>
20+
<java.version>1.8</java.version>
21+
</properties>
22+
23+
<dependencies>
24+
<dependency>
25+
<groupId>org.springframework.boot</groupId>
26+
<artifactId>spring-boot-starter-data-jpa</artifactId>
27+
</dependency>
28+
<dependency>
29+
<groupId>org.springframework.boot</groupId>
30+
<artifactId>spring-boot-starter-security</artifactId>
31+
</dependency>
32+
<dependency>
33+
<groupId>org.springframework.boot</groupId>
34+
<artifactId>spring-boot-starter-thymeleaf</artifactId>
35+
</dependency>
36+
<dependency>
37+
<groupId>org.springframework.boot</groupId>
38+
<artifactId>spring-boot-starter-web</artifactId>
39+
</dependency>
40+
<dependency>
41+
<groupId>org.apache.commons</groupId>
42+
<artifactId>commons-lang3</artifactId>
43+
<version>3.12.0</version>
44+
</dependency>
45+
<dependency>
46+
<groupId>com.fasterxml.jackson.core</groupId>
47+
<artifactId>jackson-databind</artifactId>
48+
</dependency>
49+
50+
51+
<dependency>
52+
<groupId>com.h2database</groupId>
53+
<artifactId>h2</artifactId>
54+
<scope>runtime</scope>
55+
</dependency>
56+
<dependency>
57+
<groupId>org.springframework.boot</groupId>
58+
<artifactId>spring-boot-starter-test</artifactId>
59+
<scope>test</scope>
60+
</dependency>
61+
<dependency>
62+
<groupId>org.assertj</groupId>
63+
<artifactId>assertj-core</artifactId>
64+
<version>3.22.0</version>
65+
<scope>test</scope>
66+
</dependency>
67+
</dependencies>
68+
69+
<build>
70+
<testSourceDirectory>${myTestSourceDirectory}</testSourceDirectory>
71+
<finalName>spring-pipeline-demo</finalName>
72+
<plugins>
73+
<plugin>
74+
<groupId>org.springframework.boot</groupId>
75+
<artifactId>spring-boot-maven-plugin</artifactId>
76+
</plugin>
77+
<plugin>
78+
<groupId>com.lazerycode.jmeter</groupId>
79+
<artifactId>jmeter-maven-plugin</artifactId>
80+
<version>3.5.0</version>
81+
<executions>
82+
<execution>
83+
<id>configuration</id>
84+
<goals>
85+
<goal>configure</goal>
86+
</goals>
87+
</execution>
88+
<execution>
89+
<id>jmeter-tests</id>
90+
<goals>
91+
<goal>jmeter</goal>
92+
</goals>
93+
</execution>
94+
<execution>
95+
<id>jmeter-check-results</id>
96+
<goals>
97+
<goal>results</goal>
98+
</goals>
99+
</execution>
100+
</executions>
101+
</plugin>
102+
</plugins>
103+
</build>
104+
105+
<profiles>
106+
<profile>
107+
<id>integration-testing</id>
108+
<properties>
109+
<maven.test.skip>false</maven.test.skip>
110+
<myTestSourceDirectory>${project.basedir}/src/it/java</myTestSourceDirectory>
111+
</properties>
112+
</profile>
113+
</profiles>
114+
115+
</project>
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
package com.example.springpipelinedemo.controller;
2+
3+
import com.example.springpipelinedemo.SpringPipelineDemoApplication;
4+
import com.example.springpipelinedemo.model.User;
5+
import com.example.springpipelinedemo.service.UserService;
6+
import com.fasterxml.jackson.databind.ObjectMapper;
7+
import org.apache.tomcat.util.codec.binary.Base64;
8+
import org.junit.Before;
9+
import org.junit.Test;
10+
import org.junit.runner.RunWith;
11+
import org.springframework.beans.factory.annotation.Autowired;
12+
import org.springframework.boot.test.context.SpringBootTest;
13+
import org.springframework.boot.test.mock.mockito.MockBean;
14+
import org.springframework.http.HttpHeaders;
15+
import org.springframework.security.crypto.password.PasswordEncoder;
16+
import org.springframework.test.annotation.DirtiesContext;
17+
import org.springframework.test.context.TestPropertySource;
18+
import org.springframework.test.context.junit4.SpringRunner;
19+
import org.springframework.test.context.web.WebAppConfiguration;
20+
import org.springframework.test.web.servlet.MockMvc;
21+
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
22+
import org.springframework.web.context.WebApplicationContext;
23+
24+
import javax.servlet.Filter;
25+
26+
import java.nio.charset.Charset;
27+
28+
import static org.mockito.Mockito.doReturn;
29+
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
30+
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
31+
32+
/**
33+
* Created by Rimantas Jacikevičius on 19.2.14.
34+
*/
35+
@RunWith(SpringRunner.class)
36+
@WebAppConfiguration
37+
@SpringBootTest(classes = SpringPipelineDemoApplication.class)
38+
@TestPropertySource(properties = "testContext=true")
39+
@DirtiesContext
40+
public class AdminControllerTest {
41+
42+
@MockBean
43+
UserService userService;
44+
45+
@Autowired
46+
PasswordEncoder encoder;
47+
@Autowired
48+
private WebApplicationContext webApplicationContext;
49+
@Autowired
50+
private Filter springSecurityFilterChain;
51+
52+
private MockMvc mockMvc;
53+
private ObjectMapper objectMapper = new ObjectMapper();
54+
55+
@Before
56+
public void setup() throws Exception {
57+
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext)
58+
.addFilter(springSecurityFilterChain)
59+
.build();
60+
}
61+
62+
@Test
63+
public void home() throws Exception {
64+
String username = "[email protected]";
65+
String pass = "pass123";
66+
67+
User user = new User(username, encoder.encode(pass));
68+
doReturn(user).when(userService).loadUserByUsername(username);
69+
70+
String auth = username+":"+pass;
71+
72+
String token = "Basic "+ new String(Base64.encodeBase64(
73+
auth.getBytes(Charset.forName("US-ASCII"))));
74+
75+
mockMvc.perform(
76+
get("/admin/home")
77+
.header(HttpHeaders.AUTHORIZATION, token))
78+
.andExpect(
79+
status().isOk());
80+
}
81+
82+
@Test
83+
public void home_unauthorised() throws Exception {
84+
mockMvc.perform(
85+
get("/admin/home"))
86+
.andExpect(
87+
status().isUnauthorized());
88+
}
89+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
package com.example.springpipelinedemo.controller;
2+
3+
import com.example.springpipelinedemo.SpringPipelineDemoApplication;
4+
import com.example.springpipelinedemo.controller.forms.SignupForm;
5+
import com.example.springpipelinedemo.dto.UserDto;
6+
import com.example.springpipelinedemo.service.UserService;
7+
import com.fasterxml.jackson.databind.ObjectMapper;
8+
import org.junit.Before;
9+
import org.junit.Test;
10+
import org.junit.runner.RunWith;
11+
import org.springframework.beans.factory.annotation.Autowired;
12+
import org.springframework.boot.test.context.SpringBootTest;
13+
import org.springframework.boot.test.mock.mockito.MockBean;
14+
import org.springframework.http.MediaType;
15+
import org.springframework.test.annotation.DirtiesContext;
16+
import org.springframework.test.context.TestPropertySource;
17+
import org.springframework.test.context.junit4.SpringRunner;
18+
import org.springframework.test.context.web.WebAppConfiguration;
19+
import org.springframework.test.web.servlet.MockMvc;
20+
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
21+
import org.springframework.web.context.WebApplicationContext;
22+
23+
import javax.servlet.Filter;
24+
25+
import static org.hamcrest.Matchers.is;
26+
import static org.mockito.Mockito.*;
27+
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
28+
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
29+
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
30+
31+
/**
32+
* Created by Rimantas Jacikevičius on 19.2.14.
33+
*/
34+
@RunWith(SpringRunner.class)
35+
@WebAppConfiguration
36+
@SpringBootTest(classes = SpringPipelineDemoApplication.class)
37+
@TestPropertySource(properties = "testContext=true")
38+
@DirtiesContext
39+
public class UserControllerTest {
40+
41+
@MockBean
42+
UserService userService;
43+
44+
@Autowired
45+
private WebApplicationContext webApplicationContext;
46+
@Autowired
47+
private Filter springSecurityFilterChain;
48+
49+
private MockMvc mockMvc;
50+
private ObjectMapper objectMapper = new ObjectMapper();
51+
52+
@Before
53+
public void setup() throws Exception {
54+
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext)
55+
.addFilter(springSecurityFilterChain)
56+
.build();
57+
}
58+
59+
@Test
60+
public void signup() throws Exception {
61+
SignupForm form = new SignupForm("[email protected]","somepassword");
62+
63+
doReturn(new UserDto(form.email)).when(userService).createUser(form.email, form.password);
64+
65+
mockMvc.perform(
66+
post("/users")
67+
.contentType(MediaType.APPLICATION_JSON)
68+
.content(objectMapper.writeValueAsBytes(form)))
69+
.andExpect(
70+
status().isOk())
71+
.andExpect(
72+
jsonPath("$.username", is(form.email))
73+
);
74+
75+
verify(userService).createUser(form.email, form.password);
76+
verifyNoMoreInteractions(userService);
77+
}
78+
79+
}

0 commit comments

Comments
 (0)