Repository: Clinical-Genomics/trailblazer

Issue:
Trailblazer cancel overwrites existing comments
When running `trailblazer cancel ANALYSIS_ID` - It overwrites any comment and writes `Analysis cancelled manually by user: USER!`

**Solution:**
- Instead of overwriting a comment, append to a comment to keep any previous comments added to that field. 

Discussion:
sonarcloud[bot]: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=Clinical-Genomics_trailblazer&pullRequest=449) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 New issues](https://sonarcloud.io/project/issues?id=Clinical-Genomics_trailblazer&pullRequest=449&resolved=false&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/project/issues?id=Clinical-Genomics_trailblazer&pullRequest=449&resolutions=WONTFIX)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=Clinical-Genomics_trailblazer&pullRequest=449&resolved=false&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/no-data-16px.png '') No data about Coverage  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=Clinical-Genomics_trailblazer&pullRequest=449&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarCloud](https://sonarcloud.io/dashboard?id=Clinical-Genomics_trailblazer&pullRequest=449)


sonarcloud[bot]: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=Clinical-Genomics_trailblazer&pullRequest=449) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 New issues](https://sonarcloud.io/project/issues?id=Clinical-Genomics_trailblazer&pullRequest=449&resolved=false&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/project/issues?id=Clinical-Genomics_trailblazer&pullRequest=449&resolutions=WONTFIX)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=Clinical-Genomics_trailblazer&pullRequest=449&resolved=false&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/no-data-16px.png '') No data about Coverage  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=Clinical-Genomics_trailblazer&pullRequest=449&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarCloud](https://sonarcloud.io/dashboard?id=Clinical-Genomics_trailblazer&pullRequest=449)


sonarcloud[bot]: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=Clinical-Genomics_trailblazer&pullRequest=449) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 New issues](https://sonarcloud.io/project/issues?id=Clinical-Genomics_trailblazer&pullRequest=449&resolved=false&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/project/issues?id=Clinical-Genomics_trailblazer&pullRequest=449&resolutions=WONTFIX)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=Clinical-Genomics_trailblazer&pullRequest=449&resolved=false&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/no-data-16px.png '') No data about Coverage  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=Clinical-Genomics_trailblazer&pullRequest=449&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarCloud](https://sonarcloud.io/dashboard?id=Clinical-Genomics_trailblazer&pullRequest=449)


sonarcloud[bot]: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=Clinical-Genomics_trailblazer&pullRequest=449) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 New issues](https://sonarcloud.io/project/issues?id=Clinical-Genomics_trailblazer&pullRequest=449&resolved=false&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/project/issues?id=Clinical-Genomics_trailblazer&pullRequest=449&resolutions=WONTFIX)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=Clinical-Genomics_trailblazer&pullRequest=449&resolved=false&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/no-data-16px.png '') No data about Coverage  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=Clinical-Genomics_trailblazer&pullRequest=449&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarCloud](https://sonarcloud.io/dashboard?id=Clinical-Genomics_trailblazer&pullRequest=449)


sonarcloud[bot]: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=Clinical-Genomics_trailblazer&pullRequest=449) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 New issues](https://sonarcloud.io/project/issues?id=Clinical-Genomics_trailblazer&pullRequest=449&resolved=false&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/project/issues?id=Clinical-Genomics_trailblazer&pullRequest=449&resolutions=WONTFIX)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=Clinical-Genomics_trailblazer&pullRequest=449&resolved=false&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/no-data-16px.png '') No data about Coverage  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=Clinical-Genomics_trailblazer&pullRequest=449&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarCloud](https://sonarcloud.io/dashboard?id=Clinical-Genomics_trailblazer&pullRequest=449)


sonarcloud[bot]: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=Clinical-Genomics_trailblazer&pullRequest=449) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 New issues](https://sonarcloud.io/project/issues?id=Clinical-Genomics_trailblazer&pullRequest=449&resolved=false&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/project/issues?id=Clinical-Genomics_trailblazer&pullRequest=449&resolutions=WONTFIX)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=Clinical-Genomics_trailblazer&pullRequest=449&resolved=false&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/no-data-16px.png '') No data about Coverage  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=Clinical-Genomics_trailblazer&pullRequest=449&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarCloud](https://sonarcloud.io/dashboard?id=Clinical-Genomics_trailblazer&pullRequest=449)


islean: Tested in stage:

![image](https://github.com/Clinical-Genomics/trailblazer/assets/40887124/5018ad1f-9c4e-480e-9be0-f187516e43db)


Patch:
diff --git a/trailblazer/server/api.py b/trailblazer/server/api.py
index bbfbcb4..636a3bb 100644
--- a/trailblazer/server/api.py
+++ b/trailblazer/server/api.py
@@ -255,7 +255,7 @@ def add_comment():
     try:
         case_id: str = put_request.get("case_id")
         comment: str = put_request.get("comment")
-        store.update_analysis_comment(case_id=case_id, comment=comment)
+        store.update_latest_analysis_comment(case_id=case_id, comment=comment)
         return jsonify("Success! Adding comment request sent"), HTTPStatus.CREATED
     except Exception as error:
         return jsonify(f"Exception: {error}"), HTTPStatus.CONFLICT
diff --git a/trailblazer/store/crud/update.py b/trailblazer/store/crud/update.py
index 8ca12c6..801f457 100644
--- a/trailblazer/store/crud/update.py
+++ b/trailblazer/store/crud/update.py
@@ -179,10 +179,11 @@ class UpdateHandler(BaseHandler):
         LOG.info(f"Case {analysis.case_id} - Analysis {analysis.id}: cancelled successfully!")
         self.update_run_status(analysis_id=analysis_id, analysis_host=analysis_host)
         analysis.status = TrailblazerStatus.CANCELLED
-        analysis.comment = (
+        new_comment: str = (
             f"Analysis cancelled manually by user:"
             f" {(self.get_user(email=email).name if self.get_user(email=email) else (email or 'Unknown'))}!"
         )
+        self.update_analysis_comment(analysis=analysis, comment=new_comment)
         session: Session = get_session()
         session.commit()
 
@@ -226,8 +227,12 @@ class UpdateHandler(BaseHandler):
         session: Session = get_session()
         session.commit()
 
-    def update_analysis_comment(self, case_id: str, comment: str) -> None:
+    def update_latest_analysis_comment(self, case_id: str, comment: str) -> None:
         analysis: Analysis | None = self.get_latest_analysis_for_case(case_id)
+        self.update_analysis_comment(analysis=analysis, comment=comment)
+
+    @staticmethod
+    def update_analysis_comment(analysis: Analysis, comment: str):
         analysis.comment: str = (
             " ".join([analysis.comment, comment]) if analysis.comment else comment
         )


Test patch:
diff --git a/tests/store/crud/test_read.py b/tests/store/crud/test_read.py
index 19ec757..da8ed75 100644
--- a/tests/store/crud/test_read.py
+++ b/tests/store/crud/test_read.py
@@ -14,7 +14,7 @@ def test_get_analyses_by_status_started_at_and_comment(
     existing_analysis: Analysis = analysis_store.get_query(table=Analysis).first()
 
     # GIVEN a comment
-    analysis_store.update_analysis_comment(
+    analysis_store.update_latest_analysis_comment(
         case_id=existing_analysis.case_id, comment="a new comment"
     )
 
@@ -35,7 +35,7 @@ def test_get_analyses_by_status_started_at_and_comment_with_comment(analysis_sto
     existing_analysis: Analysis = analysis_store.get_query(table=Analysis).first()
 
     # GIVEN a comment
-    analysis_store.update_analysis_comment(
+    analysis_store.update_latest_analysis_comment(
         case_id=existing_analysis.case_id, comment="a new comment"
     )
 
diff --git a/tests/store/crud/test_update.py b/tests/store/crud/test_update.py
index 8e0e4f4..49e1de2 100644
--- a/tests/store/crud/test_update.py
+++ b/tests/store/crud/test_update.py
@@ -335,7 +335,7 @@ def test_update_analysis_comment(analysis_store: MockStore, case_id: str):
     comment: str = "test comment"
 
     # WHEN adding a comment
-    analysis_store.update_analysis_comment(case_id=analysis.case_id, comment=comment)
+    analysis_store.update_latest_analysis_comment(case_id=analysis.case_id, comment=comment)
 
     # THEN a comment should have been added
     assert analysis.comment == comment
@@ -350,8 +350,8 @@ def test_update_analysis_comment_when_existing(analysis_store: MockStore, case_i
     second_comment: str = "Second"
 
     # WHEN adding a comment
-    analysis_store.update_analysis_comment(case_id=analysis.case_id, comment=first_comment)
-    analysis_store.update_analysis_comment(case_id=analysis.case_id, comment=second_comment)
+    analysis_store.update_latest_analysis_comment(case_id=analysis.case_id, comment=first_comment)
+    analysis_store.update_latest_analysis_comment(case_id=analysis.case_id, comment=second_comment)
 
     # THEN comments should have been added
     assert analysis.comment == f"{first_comment} {second_comment}"