Merge pull request 'Release/0.0.5' (#6) from release/0.0.5 into main
CI / Tests & couverture (push) Has been cancelled

Reviewed-on: Bonsai/Bonsai-api#6
This commit is contained in:
2026-05-25 18:38:53 +02:00
16 changed files with 212 additions and 11 deletions
+6 -6
View File
@@ -13,12 +13,12 @@ jobs:
- name: Checkout - name: Checkout
uses: https://github.com/actions/checkout@v4 uses: https://github.com/actions/checkout@v4
- name: Setup Java 25 - name: Install Java 25
uses: https://github.com/actions/setup-java@v4 run: |
with: wget -q https://github.com/adoptium/temurin25-binaries/releases/download/jdk-25.0.3%2B9/OpenJDK25U-jdk_x64_alpine-linux_hotspot_25.0.3_9.tar.gz
java-version: '25' tar -xzf OpenJDK25U-jdk_x64_alpine-linux_hotspot_25.0.3_9.tar.gz -C /opt
distribution: 'temurin' echo "JAVA_HOME=/opt/jdk-25.0.3+9" >> $GITHUB_ENV
cache: 'gradle' echo "/opt/jdk-25.0.3+9/bin" >> $GITHUB_PATH
- name: Build JAR - name: Build JAR
run: ./gradlew build -x test run: ./gradlew build -x test
+7 -4
View File
@@ -21,17 +21,20 @@ jobs:
- name: Install curl - name: Install curl
run: apk add --no-cache curl run: apk add --no-cache curl
- name: Create PR release → develop - name: Create PR main → develop
run: | run: |
RELEASE_BRANCH="${{ github.event.pull_request.head.ref }}" RELEASE_BRANCH="${{ github.event.pull_request.head.ref }}"
curl -X POST \ STATUS=$(curl -s -o /tmp/pr_response.json -w "%{http_code}" -X POST \
-H "Authorization: token ${{ secrets.RELEASE_TOKEN }}" \ -H "Authorization: token ${{ secrets.RELEASE_TOKEN }}" \
-H "Content-Type: application/json" \ -H "Content-Type: application/json" \
-d "{ -d "{
\"title\": \"chore: sync ${RELEASE_BRANCH} into develop\", \"title\": \"chore: sync ${RELEASE_BRANCH} into develop\",
\"head\": \"${RELEASE_BRANCH}\", \"head\": \"main\",
\"base\": \"develop\", \"base\": \"develop\",
\"body\": \"Synchronisation automatique après merge de ${RELEASE_BRANCH} dans main.\" \"body\": \"Synchronisation automatique après merge de ${RELEASE_BRANCH} dans main.\"
}" \ }" \
"${{ gitea.server_url }}/api/v1/repos/${{ gitea.repository }}/pulls" "https://git.goutailler-olivier.com/api/v1/repos/${{ gitea.repository }}/pulls")
echo "POST /pulls → HTTP $STATUS"
cat /tmp/pr_response.json
[ "$STATUS" = "201" ] || exit 1
+1
View File
@@ -0,0 +1 @@
.env
+24
View File
@@ -0,0 +1,24 @@
meta {
name: Get Token
type: http
seq: 1
}
post {
url: {{keycloakUrl}}/protocol/openid-connect/token
body: formUrlEncoded
auth: none
}
body:form-urlencoded {
grant_type: password
client_id: {{clientId}}
username: {{username}}
password: {{password}}
}
script:post-response {
if (res.status === 200) {
bru.setEnvVar("accessToken", res.body.access_token);
}
}
+6
View File
@@ -0,0 +1,6 @@
{
"version": "1",
"name": "Bonsai API",
"type": "collection",
"ignore": []
}
+12
View File
@@ -0,0 +1,12 @@
vars {
baseUrl: http://localhost:8080/api
keycloakUrl: https://auth.goutailler-olivier.com/realms/bonsai
clientId: bonsai-webapp
}
vars:secret [
username,
password,
clientSecret,
accessToken
]
+11
View File
@@ -0,0 +1,11 @@
vars {
baseUrl: https://bonsai.goutailler-olivier.com/api
keycloakUrl: https://auth.goutailler-olivier.com/realms/bonsai
clientId: bonsai-webapp
}
vars:secret [
username,
password,
clientSecret,
accessToken
]
+32
View File
@@ -0,0 +1,32 @@
meta {
name: Create Issue
type: http
seq: 2
}
post {
url: {{baseUrl}}/issues
body: json
auth: bearer
}
auth:bearer {
token: {{accessToken}}
}
body:json {
{
"type": "Story",
"name": "Nouvelle issue",
"priority": "Moyenne",
"status": "todo",
"progress": 0,
"assignee": null,
"epic": null,
"dueDate": null,
"description": null,
"estimatedTime": null,
"dependsOnIds": [],
"comments": []
}
}
+15
View File
@@ -0,0 +1,15 @@
meta {
name: Delete Issue
type: http
seq: 4
}
delete {
url: {{baseUrl}}/issues/1
body: none
auth: bearer
}
auth:bearer {
token: {{accessToken}}
}
+15
View File
@@ -0,0 +1,15 @@
meta {
name: Get All Issues
type: http
seq: 1
}
get {
url: {{baseUrl}}/issues
body: none
auth: bearer
}
auth:bearer {
token: {{accessToken}}
}
+32
View File
@@ -0,0 +1,32 @@
meta {
name: Update Issue
type: http
seq: 3
}
put {
url: {{baseUrl}}/issues/1
body: json
auth: bearer
}
auth:bearer {
token: {{accessToken}}
}
body:json {
{
"type": "Story",
"name": "Issue mise à jour",
"priority": "Haute",
"status": "in-progress",
"progress": 50,
"assignee": null,
"epic": null,
"dueDate": "2026-06-01",
"description": null,
"estimatedTime": 3.5,
"dependsOnIds": [],
"comments": []
}
}
+11
View File
@@ -0,0 +1,11 @@
meta {
name: Get Version
type: http
seq: 1
}
get {
url: {{baseUrl}}/version
body: none
auth: none
}
+5
View File
@@ -20,6 +20,7 @@ repositories {
dependencies { dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.8.6'
implementation 'org.springframework.boot:spring-boot-starter-actuator' implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'org.springframework.boot:spring-boot-starter-security' implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-oauth2-resource-server' implementation 'org.springframework.boot:spring-boot-starter-oauth2-resource-server'
@@ -36,3 +37,7 @@ dependencies {
tasks.named('test') { tasks.named('test') {
useJUnitPlatform() useJUnitPlatform()
} }
springBoot {
buildInfo()
}
@@ -0,0 +1,24 @@
package fr.bonsai.api.adapter.in.web;
import org.springframework.boot.info.BuildProperties;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/version")
public class VersionController {
private final BuildProperties buildProperties;
public VersionController(BuildProperties buildProperties) {
this.buildProperties = buildProperties;
}
@GetMapping
public VersionResponse get() {
return new VersionResponse(buildProperties.getVersion());
}
public record VersionResponse(String version) {}
}
@@ -22,6 +22,8 @@ public class SecurityConfig {
session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.authorizeHttpRequests(auth -> auth .authorizeHttpRequests(auth -> auth
.requestMatchers(HttpMethod.OPTIONS, "/**").permitAll() .requestMatchers(HttpMethod.OPTIONS, "/**").permitAll()
.requestMatchers(HttpMethod.GET, "/version").permitAll()
.requestMatchers("/swagger-ui/**", "/v3/api-docs/**", "/swagger-ui.html").permitAll()
.anyRequest().authenticated() .anyRequest().authenticated()
) )
.oauth2ResourceServer(oauth2 -> oauth2 .oauth2ResourceServer(oauth2 -> oauth2
+8
View File
@@ -1,5 +1,7 @@
server: server:
port: 8080 port: 8080
servlet:
context-path: /api
spring: spring:
datasource: datasource:
@@ -18,6 +20,12 @@ spring:
jwt: jwt:
jwk-set-uri: ${KEYCLOAK_JWKS_URI:https://auth.goutailler-olivier.com/realms/bonsai/protocol/openid-connect/certs} jwk-set-uri: ${KEYCLOAK_JWKS_URI:https://auth.goutailler-olivier.com/realms/bonsai/protocol/openid-connect/certs}
springdoc:
api-docs:
path: /v3/api-docs
swagger-ui:
path: /swagger-ui.html
app: app:
cors: cors:
allowed-origins: "http://localhost:4200,${CORS_ALLOWED_ORIGIN_PROD:https://bonsai.goutailler-olivier.com}" allowed-origins: "http://localhost:4200,${CORS_ALLOWED_ORIGIN_PROD:https://bonsai.goutailler-olivier.com}"