Skip to content

Commit 066bf24

Browse files
Merge pull request #4 from Breeding-Insight/develop
Release v1.2
2 parents 7498f44 + a3009e4 commit 066bf24

27 files changed

+821
-156
lines changed

.github/workflows/docker-build.yml

Lines changed: 114 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -6,59 +6,146 @@ on:
66
- develop
77
- release/**
88
- brapi-server-v2
9-
9+
1010
workflow_dispatch:
11+
inputs:
12+
upstream_repo:
13+
description: 'Optional: Override upstream repository (owner/repo). Defaults to the repository this was forked from if not set.'
14+
required: false
15+
default: 'plantbreeding/brapi-Java-ProdServer'
16+
upstream_pr_number:
17+
description: 'Required if merging an upstream PR: PR number from the upstream repository to merge into develop for this build. ex: 11'
18+
required: false # Still false overall, but logic will require it if this feature is used.
19+
type: string
1120

1221
jobs:
1322
docker:
1423
runs-on: ubuntu-latest
1524

1625
steps:
17-
- uses: actions/checkout@v2
18-
26+
- name: Checkout branch
27+
uses: actions/checkout@v4
28+
with:
29+
fetch-depth: 0 # Fetch all history to ensure common ancestor is found
30+
31+
- name: Conditionally Fetch and Merge Upstream PR
32+
# This step runs if a PR number is provided AND (an upstream_repo input is given OR a parent repo full_name is available)
33+
if: |
34+
github.event.inputs.upstream_pr_number &&
35+
github.event.inputs.upstream_repo
36+
run: |
37+
UPSTREAM_REPO_SPECIFIED="${{ github.event.inputs.upstream_repo }}"
38+
UPSTREAM_PR_NUMBER="${{ github.event.inputs.upstream_pr_number }}"
39+
40+
if [[ -z "$UPSTREAM_PR_NUMBER" ]]; then
41+
echo "No upstream PR number provided. Skipping PR merge."
42+
exit 0
43+
fi
44+
45+
TARGET_UPSTREAM_REPO=""
46+
if [[ -n "$UPSTREAM_REPO_SPECIFIED" ]]; then
47+
TARGET_UPSTREAM_REPO="$UPSTREAM_REPO_SPECIFIED"
48+
echo "Using specified upstream repository: $TARGET_UPSTREAM_REPO"
49+
else
50+
echo "Error: Upstream PR number '$UPSTREAM_PR_NUMBER' was provided, but no upstream_repo was specified and parent repository could not be determined."
51+
exit 1
52+
fi
53+
54+
echo "Upstream PR to merge: $UPSTREAM_PR_NUMBER from $TARGET_UPSTREAM_REPO"
55+
UPSTREAM_REPO_URL="https://github.com/$TARGET_UPSTREAM_REPO.git"
56+
57+
# Fetch the PR from the upstream repository
58+
git fetch $UPSTREAM_REPO_URL +refs/pull/$UPSTREAM_PR_NUMBER/head:upstream_pr_branch
59+
60+
echo "Fetched PR branch 'upstream_pr_branch'. Merging into current HEAD (develop)..."
61+
# Merge the fetched PR branch. If conflicts occur, the script will exit with an error.
62+
git config user.name "GitHub Actions"
63+
git config user.email "actions@github.com"
64+
git merge upstream_pr_branch --no-ff -m "Merge upstream PR #$UPSTREAM_PR_NUMBER from $TARGET_UPSTREAM_REPO for testing"
65+
66+
echo "Merge complete."
67+
shell: bash
68+
1969
- name: Extract branch name
2070
shell: bash
21-
run: echo ::set-output name=branch::$(echo ${GITHUB_REF#refs/heads/})
71+
run: echo "branch=$(echo ${GITHUB_REF#refs/heads/})" >> "$GITHUB_OUTPUT"
2272
id: extract_branch
23-
24-
- run: git pull origin ${{steps.extract_branch.outputs.branch}}
25-
73+
74+
# This pull is no longer needed as checkout handles fetching the correct ref,
75+
# and the PR merge step brings in specific upstream changes.
76+
# - run: git pull origin ${{steps.extract_branch.outputs.branch}}
77+
2678
- name: Set up JDK 21
2779
uses: actions/setup-java@v4
2880
with:
2981
distribution: temurin
3082
java-version: '21'
3183
cache: maven
32-
84+
3385
- name: Build with Maven
3486
run: mvn clean install
3587

3688
- name: Set up Docker Buildx
37-
uses: docker/setup-buildx-action@v2
89+
uses: docker/setup-buildx-action@v3
3890
- name: Set up QEMU
39-
uses: docker/setup-qemu-action@v2
91+
uses: docker/setup-qemu-action@v3
4092
with:
41-
platforms: 'arm64,arm,amd64,amd'
42-
93+
platforms: 'arm64,arm,amd64'
94+
4395
- name: Login to Docker Hub
44-
uses: docker/login-action@v1
96+
uses: docker/login-action@v3
4597
with:
4698
username: ${{ secrets.DOCKERHUB_USERNAME }}
4799
password: ${{ secrets.DOCKERHUB_PASSWORD }}
48-
- name: Set tag
49-
id: vars
50-
run: echo ::set-output name=imageName::$(echo breedinginsight/brapi-java-server:${{ github.run_number }})
51-
52-
- name: Tag develop
53-
if: steps.extract_branch.outputs.branch == 'develop'
54-
run: echo "streamName=breedinginsight/brapi-java-server:develop" >> $GITHUB_ENV
55-
- name: Tag release candidate
56-
if: contains(github.ref, '/release/')
57-
run: echo "streamName=breedinginsight/brapi-java-server:rc" >> $GITHUB_ENV
58-
- name: Tag latest
59-
if: steps.extract_branch.outputs.branch == 'brapi-server-v2'
60-
run: echo "streamName=breedinginsight/brapi-java-server:latest" >> $GITHUB_ENV
100+
101+
- name: Determine Docker Tags
102+
id: docker_tags
103+
shell: bash
104+
run: |
105+
PR_NUMBER="${{ github.event.inputs.upstream_pr_number }}"
106+
IMAGE_BASE_NAME="breedinginsight/brapi-java-server"
107+
TAGS=""
108+
IS_PR_BUILD="false"
109+
110+
if [[ -n "$PR_NUMBER" ]]; then
111+
echo "This is a PR build. Setting PR-specific tag."
112+
PR_TAG="$IMAGE_BASE_NAME:pr-$PR_NUMBER"
113+
TAGS="$PR_TAG"
114+
IS_PR_BUILD="true"
115+
else
116+
echo "This is a regular build. Setting standard tags."
117+
RUN_NUMBER_TAG="$IMAGE_BASE_NAME:${{ github.run_number }}"
118+
TAGS="$RUN_NUMBER_TAG"
119+
120+
BRANCH_NAME="${{ steps.extract_branch.outputs.branch }}"
121+
STREAM_NAME=""
122+
if [[ "$BRANCH_NAME" == "develop" ]]; then
123+
STREAM_NAME="$IMAGE_BASE_NAME:develop"
124+
elif [[ "$BRANCH_NAME" == "brapi-server-v2" ]]; then # Assuming brapi-server-v2 is 'latest'
125+
STREAM_NAME="$IMAGE_BASE_NAME:latest"
126+
elif [[ "${{ github.ref }}" == refs/heads/release/* ]]; then
127+
STREAM_NAME="$IMAGE_BASE_NAME:rc"
128+
fi
129+
130+
if [[ -n "$STREAM_NAME" ]]; then
131+
TAGS="$TAGS,$STREAM_NAME" # Comma-separated for docker/build-push-action
132+
fi
133+
fi
134+
echo "Final tags: $TAGS"
135+
echo "tags=$TAGS" >> "$GITHUB_OUTPUT"
136+
echo "is_pr_build=$IS_PR_BUILD" >> "$GITHUB_OUTPUT"
137+
138+
# The original 'Set tag' and 'Tag develop/rc/latest' steps are now incorporated into 'Determine Docker Tags'
139+
# and are conditioned by is_pr_build logic within that step.
61140

62141
- name: Build Docker and push image
63142
run: |
64-
docker buildx build . --file Dockerfile --tag ${{steps.vars.outputs.imageName}} --tag ${{env.streamName}} --push --platform=linux/arm64,linux/amd64
143+
# Note: The `docker/build-push-action` is generally recommended over manual scripting
144+
# as it handles tags more robustly. However, to keep the change minimal,
145+
# this script adapts the original logic.
146+
FORMATTED_TAGS=""
147+
IFS=',' read -ra TAG_ARRAY <<< "${{ steps.docker_tags.outputs.tags }}"
148+
for tag in "${TAG_ARRAY[@]}"; do
149+
FORMATTED_TAGS="$FORMATTED_TAGS --tag $tag"
150+
done
151+
docker buildx build . --file Dockerfile $FORMATTED_TAGS --push --platform=linux/arm64,linux/amd64

src/main/java/org/brapi/test/BrAPITestServer/controller/pheno/ObservationsApiController.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ public ResponseEntity<ObservationSingleResponse> observationsObservationDbIdPut(
121121
log.debug("Request: " + request.getRequestURI());
122122
validateSecurityContext(request, "ROLE_USER");
123123
validateAcceptHeader(request);
124-
Observation data = observationService.updateObservation(observationDbId, body);
124+
Observation data = observationService.updateObservationAndConvert(observationDbId, body);
125125
return responseOK(new ObservationSingleResponse(), data);
126126
}
127127

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package org.brapi.test.BrAPITestServer.model.dto;
2+
3+
import java.util.UUID;
4+
5+
public class ObservationUnitGermplasmData {
6+
private String germplasmDbId;
7+
private String germplasmName;
8+
9+
public ObservationUnitGermplasmData(String germplasmDbId,
10+
String germplasmName) {
11+
this.germplasmDbId = germplasmDbId;
12+
this.germplasmName = germplasmName;
13+
}
14+
15+
public String getGermplasmDbId() {
16+
return germplasmDbId;
17+
}
18+
19+
public void setGermplasmDbId(String germplasmDbId) {
20+
this.germplasmDbId = germplasmDbId;
21+
}
22+
23+
public String getGermplasmName() {
24+
return germplasmName;
25+
}
26+
27+
public void setGermplasmName(String germplasmName) {
28+
this.germplasmName = germplasmName;
29+
}
30+
}

src/main/java/org/brapi/test/BrAPITestServer/model/entity/core/ExperimentalDesignEntity.java

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,12 @@
33
import jakarta.persistence.*;
44
import org.brapi.test.BrAPITestServer.model.entity.BrAPIBaseEntity;
55

6-
@Entity
7-
@Table(name = "study_experimental_design")
8-
public class ExperimentalDesignEntity extends BrAPIBaseEntity {
9-
@Column
6+
@Embeddable
7+
public class ExperimentalDesignEntity {
8+
@Column(name = "pui", table = "study_experimental_design")
109
private String PUI;
11-
@Column
10+
@Column(name = "description", table = "study_experimental_design")
1211
private String description;
13-
@OneToOne(fetch = FetchType.LAZY)
14-
private StudyEntity study;
15-
16-
public StudyEntity getStudy() {
17-
return study;
18-
}
19-
20-
public void setStudy(StudyEntity study) {
21-
this.study = study;
22-
}
2312

2413
public String getPUI() {
2514
return PUI;

src/main/java/org/brapi/test/BrAPITestServer/model/entity/core/GrowthFacilityEntity.java

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,12 @@
33
import jakarta.persistence.*;
44
import org.brapi.test.BrAPITestServer.model.entity.BrAPIBaseEntity;
55

6-
@Entity
7-
@Table(name = "study_growth_facility")
8-
public class GrowthFacilityEntity extends BrAPIBaseEntity {
9-
@Column
6+
@Embeddable
7+
public class GrowthFacilityEntity {
8+
@Column(name = "pui", table = "study_growth_facility")
109
private String PUI;
11-
@Column
10+
@Column(name = "description", table = "study_growth_facility")
1211
private String description;
13-
@OneToOne(fetch = FetchType.LAZY)
14-
private StudyEntity study;
15-
16-
public StudyEntity getStudy() {
17-
return study;
18-
}
19-
20-
public void setStudy(StudyEntity study) {
21-
this.study = study;
22-
}
2312

2413
public String getPUI() {
2514
return PUI;

src/main/java/org/brapi/test/BrAPITestServer/model/entity/core/StudyEntity.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@
1212

1313
@Entity
1414
@Table(name = "study")
15+
@SecondaryTables({
16+
@SecondaryTable(name = "study_experimental_design", pkJoinColumns = @PrimaryKeyJoinColumn(name = "study_id")),
17+
@SecondaryTable(name = "study_growth_facility", pkJoinColumns = @PrimaryKeyJoinColumn(name = "study_id")),
18+
@SecondaryTable(name = "study_last_update", pkJoinColumns = @PrimaryKeyJoinColumn(name = "study_id"))
19+
})
1520
@Where(clause = "soft_deleted = false")
1621
public class StudyEntity extends BrAPIPrimaryEntity {
1722

@@ -32,11 +37,11 @@ public class StudyEntity extends BrAPIPrimaryEntity {
3237
private Date endDate;
3338
@OneToMany(mappedBy = "study")
3439
private List<EnvironmentParametersEntity> environmentParameters;
35-
@OneToOne(mappedBy = "study", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY)
40+
@Embedded
3641
private ExperimentalDesignEntity experimentalDesign;
37-
@OneToOne(mappedBy = "study", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY)
42+
@Embedded
3843
private GrowthFacilityEntity growthFacility;
39-
@OneToOne(mappedBy = "study", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY)
44+
@Embedded
4045
private StudyLastUpdateEntity lastUpdate;
4146
@Column
4247
private String license;

src/main/java/org/brapi/test/BrAPITestServer/model/entity/core/StudyLastUpdateEntity.java

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,12 @@
55

66
import java.util.Date;
77

8-
@Entity
9-
@Table(name = "study_last_update")
10-
public class StudyLastUpdateEntity extends BrAPIBaseEntity {
11-
@Column
8+
@Embeddable
9+
public class StudyLastUpdateEntity {
10+
@Column(name = "timestamp", table = "study_last_update")
1211
private Date timestamp;
13-
@Column
12+
@Column(name = "version", table = "study_last_update")
1413
private String version;
15-
@OneToOne(fetch = FetchType.LAZY)
16-
private StudyEntity study;
17-
18-
public StudyEntity getStudy() {
19-
return study;
20-
}
21-
22-
public void setStudy(StudyEntity study) {
23-
this.study = study;
24-
}
2514

2615
public Date getTimestamp() {
2716
return timestamp;

src/main/java/org/brapi/test/BrAPITestServer/model/entity/pheno/ObservationUnitEntity.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import org.brapi.test.BrAPITestServer.model.entity.germ.CrossEntity;
1111
import org.brapi.test.BrAPITestServer.model.entity.germ.GermplasmEntity;
1212
import org.brapi.test.BrAPITestServer.model.entity.germ.SeedLotEntity;
13+
import org.hibernate.annotations.BatchSize;
1314
import org.hibernate.annotations.Where;
1415

1516
import java.util.List;
@@ -28,6 +29,7 @@ public class ObservationUnitEntity extends BrAPIPrimaryEntity {
2829
private String observationUnitPUI;
2930
@ManyToOne(fetch = FetchType.LAZY)
3031
private SeedLotEntity seedLot;
32+
@BatchSize(size = 50)
3133
@OneToMany(mappedBy="observationUnit", cascade=CascadeType.ALL)
3234
private List<TreatmentEntity> treatments;
3335
@OneToOne(mappedBy="observationUnit", cascade=CascadeType.ALL, fetch = FetchType.LAZY)
@@ -40,6 +42,7 @@ public class ObservationUnitEntity extends BrAPIPrimaryEntity {
4042
private TrialEntity trial;
4143
@ManyToOne(fetch = FetchType.LAZY)
4244
private StudyEntity study;
45+
@BatchSize(size = 50)
4346
@OneToMany(mappedBy="observationUnit", cascade=CascadeType.ALL, fetch = FetchType.LAZY)
4447
private List<ObservationEntity> observations;
4548

src/main/java/org/brapi/test/BrAPITestServer/repository/BrAPIRepository.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import java.io.Serializable;
44
import java.util.List;
55
import java.util.Optional;
6+
import java.util.UUID;
67

78
import org.brapi.test.BrAPITestServer.exceptions.InvalidPagingException;
89
import org.brapi.test.BrAPITestServer.model.entity.BrAPIPrimaryEntity;
@@ -30,7 +31,7 @@ public interface BrAPIRepository<T extends BrAPIPrimaryEntity, ID extends Serial
3031

3132
public <S extends T> void refresh(S entity);
3233

33-
public void fetchXrefs(Page<T> page, Class<T> searchClass) throws InvalidPagingException;
34+
public void fetchXrefs(List<UUID> page, Page<T> pagedEntities, Class<T> searchClass) throws InvalidPagingException;
3435

3536
List<T> findByIdIn(List<ID> ids);
3637
}

src/main/java/org/brapi/test/BrAPITestServer/repository/BrAPIRepositoryImpl.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import org.brapi.test.BrAPITestServer.exceptions.InvalidPagingException;
1515
import org.brapi.test.BrAPITestServer.model.entity.BrAPIPrimaryEntity;
1616
import org.brapi.test.BrAPITestServer.model.entity.ExternalReferenceEntity;
17+
import org.brapi.test.BrAPITestServer.model.entity.germ.GermplasmEntity;
1718
import org.brapi.test.BrAPITestServer.service.SearchQueryBuilder;
1819
import org.brapi.test.BrAPITestServer.service.SecurityUtils;
1920

@@ -141,17 +142,17 @@ public <S extends T> void refresh(S entity) {
141142
this.entityManager.refresh(entity);
142143
}
143144

144-
public void fetchXrefs(Page<T> page, Class<T> searchClass) throws InvalidPagingException {
145-
SearchQueryBuilder<T> searchQuery = new SearchQueryBuilder<T>(searchClass);
145+
public void fetchXrefs(List<UUID> ids, Page<T> pagedEntities, Class<T> searchClass) {
146+
SearchQueryBuilder<T> searchQuery = new SearchQueryBuilder<>(searchClass);
146147
searchQuery.leftJoinFetch("externalReferences", "externalReferences")
147-
.appendList(page.stream().map(p -> p.getId().toString()).collect(Collectors.toList()), "id");
148+
.appendIds(ids);
148149

149-
Page<T> xrefs = findAllBySearchAndPaginate(searchQuery, PageRequest.of(0, page.getSize()));
150+
List<T> xrefs = findAllBySearch(searchQuery);
150151

151152
Map<UUID, List<ExternalReferenceEntity>> xrefByEntity = new HashMap<>();
152153
xrefs.forEach(entity -> xrefByEntity.put(entity.getId(), entity.getExternalReferences()));
153154

154-
page.forEach(entity -> entity.setExternalReferences(xrefByEntity.get(entity.getId())));
155+
pagedEntities.forEach(entity -> entity.setExternalReferences(xrefByEntity.get(entity.getId())));
155156
}
156157

157158
private void applyUserId(SearchQueryBuilder<T> searchQuery) {

0 commit comments

Comments
 (0)